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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章