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