ER

// 2010-11-10
bool Sudoku::EmptyRectangle()
{
    /*
    A===============B  强链
    |
    |
    |
    C---------------ER
    */
   
    for (int r = 0; r < 18; ++r) // 先row,后col
    {
        _CandiCnt_Map mapCandi;
        if (r < 9)
            GetLinks(HOUSE_ROW, r, true, 0, mapCandi);
        else
            GetLinks(HOUSE_COL, r-9, true, 0, mapCandi);

        _CandiCnt_Map::iterator _itCandi;
        for (_itCandi=mapCandi.begin(); _itCandi!=mapCandi.end(); ++_itCandi)
        {
            int nX = _itCandi->first;    // 候选数
           
            for (int InLoop = 0; InLoop < 2; ++InLoop)
            {
                _Point A = *_itCandi->second.begin();
                _Point B = * ++_itCandi->second.begin();
               
                if (InLoop == 1) swap(A, B);
               
                // A, B 点不可用在同一box中
                if (A.BoxNo() == B.BoxNo()) continue;
               
                // 找C点
                _CandiCnt_Map candiLinks;
                GetLinks(HOUSE_COL, A.c, false, nX, candiLinks);
               
                // 无弱链,如果满足该条件,则是Hidden/Naked Single
                if (candiLinks.empty()) continue;
               
                list<_Point> & lstPt = candiLinks.begin()->second;
                for (list<_Point>::iterator ipt=lstPt.begin(); ipt!=lstPt.end();++ipt)
                {
                    _Point & C = *ipt;
                    if (A.BoxNo() == C.BoxNo()) continue;
                   
                    _Point D;
                    D.r = C.r;
                    D.c = B.c;
                   
                    _Point arrEr[4];
                    _Point arrCandi[5];
                    int num;
                    if (IsER(D, nX, arrEr, arrCandi, num) )
                    {
                        printf("ER(candi:%d) strong link: A(%d,%d), B(%d,%d), C(%d,%d)/n",
                            nX, A.r, A.c, B.r, B.c, C.r, C.c);
                        printf("num=%d/n", num);
                    }
                }
            }
        }
    }
   
    return false;
}

// 判断p点所在的box在去掉p所看到的行和列上的5点后是否能构成ER,其中候选数为X
bool Sudoku::IsER(_Point & p, int X, _Point arrEr[4], _Point arrCandi[5], int & num )
{
    int m = p.BoxNo(); // box的序号(0-8)   
    int er = 0;
    num = 0;

    int rowBegin = (m/3)*3;
    int rowEnd = rowBegin + 3;
    for (int r1 = rowBegin; r1 < rowEnd; ++r1)
    {
        int colBegin = (m%3) * 3;
        int colEnd = colBegin + 3;
        for (int c1 = colBegin; c1 < colEnd; ++c1)
        {
            bool bValEqual = false;
            for (int i = 0; i < m_anCell[r1][c1].n; ++i)
            {
                if (m_anCell[r1][c1].candi[i] == X)
                {
                    bValEqual = true;
                    break;
                }
            }

            if (r1==p.r || c1==p.c) // 和p点同行或者同列
            {
                if (bValEqual)
                {
                    arrCandi[num].r = r1;
                    arrCandi[num].c = c1;
                    ++num;
                }
            }
            else    // ER点
            {
                if (bValEqual || m_cell[r1][c1] == X) return false;

                arrEr[er].r = r1;
                arrEr[er].c = c1;
                ++er;
            }
        }
    }

    if (num<=2) return false;

    return true;
}


// p1 和  p2 可以共同看到的数格中,存在候选数 candi(个数为n)的数格通过 arrDel
// 输出。返回值为arrDel的元素个数
int Sudoku::GetDelPos(_Point& p1, _Point& p2, int candi[9], int n, _Point arrDel[20])
{
    _Point arrOut[20];
    int num = GetInterSection(p1, p2, 20, arrOut);
   

    int k = 0;
    for (int i = 0; i < num; ++i)
    {
        ANSudokuCell &cTmp = m_anCell[arrOut[i].r][arrOut[i].c];
        for (int j = 0; j < cTmp.n; ++j)
        {
            for (int m = 0; m < n; ++m)
            {
                bool bValEqual = false;
                if (cTmp.candi[j] == candi[m])
                {
                    bValEqual = true;
                    arrDel[k] = arrOut[i];
                    ++k;
                    break;
                }

                if (bValEqual) break;
            }
        }
    }

    return k;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值