//----------------------------------
// [11/12/2010 anning]
// 获取链 In 以首(isHead=true)或者尾为起始点的弱强(-=)链。
void Sudoku::XY_ChainGetWeakStrongLinks(list<sdLink> & In, bool isHead, list<sdLink> & Out)
{
_Point p1, p2; // p1, 链首; p2, 链尾
int nX; // 候选数
sdLink ln;
list<sdLink>::const_iterator cit;
if (isHead) { // (1,3)---> (3,Z)
cit = --In.end();
p1.r = cit->a/9;
p1.c = cit->a%9;
p2.r = cit->b/9;
p2.c = cit->b%9;
nX = cit->y;
ln.x = nX;
}
else // (Z,1) <--- (1,3)
{
cit = In.begin();
p1.r = cit->b/9;
p1.c = cit->b%9;
p2.r = cit->a/9;
p2.c = cit->a%9;
nX = cit->x;
ln.y = nX;
}
Out.clear();
list<_Point> lstPt;
list<_Point>::iterator _iLstPt;
GetAllLinks(false, nX, p2, p1, lstPt);
for (_iLstPt=lstPt.begin(); _iLstPt!=lstPt.end(); ++_iLstPt)
{
ANSudokuCell & cell = m_anCell[_iLstPt->r][_iLstPt->c];
if (cell.n != 2) continue;
ln.a = ln.b = _iLstPt->r * SD_SIZE + _iLstPt->c;
if (isHead)
ln.y = cell.candi[0]==nX ? cell.candi[1] : cell.candi[0];
else
ln.x = cell.candi[0]==nX ? cell.candi[1] : cell.candi[0];
Out.push_back(ln);
}
}
// (1,2) (2,3) (3,4) (4,2) (2,1) 这里只判断和首节点的1有相同候选数的位置是否可消,
// 没有判断中间的满足条件的数格,比如(2,3)(3,4)(4,2)链,有共同数字2。
// -----------------------------------------------------------------------------
// 这里没有过滤两个节点组成的XY-Chain,因为两个节点组成的XY-Chain为数对, 例如:
// (1,2)(2,1),由Naked Pair 方法消除。
bool Sudoku::XY_Chain()
{
for (int i = 0; i < 81; ++i) // 81个数格(编号0-80)
{
ANSudokuCell & cell = m_anCell[i/9][i%9];
if (cell.n != 2) continue;
list<list<sdLink> > linksI; // 循环查找弱强链所用的容器
list<list<sdLink> > linksN; // 向右侧查找弱强链所用的容器
bool bLeft = true; // 为true,则向链的左侧延伸
sdLink ln;
ln.a = ln.b = i;
ln.x = cell.candi[0];
ln.y = cell.candi[1];
list<sdLink> lk;
lk.push_back(ln);
linksI.push_back(lk);
while(!linksI.empty())
{
// 将I 中的第一个元素移到 N 中
linksN.splice(linksN.begin(), linksI, linksI.begin());
list<sdLink>::const_iterator cit;
_Point pt;
int X;
if(bLeft) {
cit = --linksN.begin()->end();
pt.r = cit->b / 9;
pt.c = cit->b % 9;
X = cit->y;
}
else {
cit = linksN.begin()->begin();
pt.r = cit->a / 9;
pt.c = cit->a % 9;
X = cit->x;
}
XY_ChainGetWeakStrongLinks(*linksN.begin(), !bLeft, lk);
for (list<sdLink>::iterator ilk=lk.begin(); ilk!=lk.end(); ++ilk)
{
if ( IsExist(*linksN.begin(), *ilk) ) continue;
int arrCandi[1];
_Point p; // 端点节点
if(bLeft) {
p.r = ilk->a / 9;
p.c = ilk->a % 9;
arrCandi[0] = ilk->x;
}
else {
p.r = ilk->b / 9;
p.c = ilk->b % 9;
arrCandi[0] = ilk->y;
}
list<sdLink> links = *linksN.begin(); // 测试后的链
if(bLeft) links.push_front(*ilk);
else links.push_back(*ilk);
int k = 0;
_Point arrDelPt[20];
if (arrCandi[0] == X)
k = GetDelPos(pt, p, arrCandi, 1, arrDelPt);
if (k <= 0) linksI.push_back(links);
if (k <= 0) continue;
printf("XY-Chian:");
for (list<sdLink>::const_iterator _iL=links.begin(); _iL!=links.end(); ++_iL)
{
printf("(%d,%d)", _iL->a / 9, _iL->a % 9);
}
printf(", Candi:%d Cells to del:", X);
for (int i = 0; i < k; ++i)
{
printf("(%d,%d) ", arrDelPt[i].r, arrDelPt[i].c);
}
printf("/n");
}
}
// 向另一个方向查找链
bLeft = !bLeft;
while(!linksN.empty())
{
list<sdLink>::const_iterator cit;
_Point pt;
int X;
if(bLeft) {
cit = --linksN.begin()->end();
pt.r = cit->b / 9;
pt.c = cit->b % 9;
X = cit->y;
}
else {
cit = linksN.begin()->begin();
pt.r = cit->a / 9;
pt.c = cit->a % 9;
X = cit->x;
}
XY_ChainGetWeakStrongLinks(*linksN.begin(), !bLeft, lk);
for (list<sdLink>::iterator ilk=lk.begin(); ilk!=lk.end(); ++ilk)
{
if ( IsExist(*linksN.begin(), *ilk) ) continue;
int arrCandi[1];
_Point p; // 端点节点
if(bLeft) {
p.r = ilk->a / 9;
p.c = ilk->a % 9;
arrCandi[0] = ilk->x;
}
else {
p.r = ilk->b / 9;
p.c = ilk->b % 9;
arrCandi[0] = ilk->y;
}
list<sdLink> links = *linksN.begin(); // 测试后的链
if(bLeft) links.push_front(*ilk);
else links.push_back(*ilk);
int k = 0;
_Point arrDelPt[20];
if (arrCandi[0] == X)
k = GetDelPos(pt, p, arrCandi, 1, arrDelPt);
if (k <= 0) linksN.push_back(links);
if (k <= 0) continue;
printf("XY-Chian:");
for (list<sdLink>::const_iterator _iL=links.begin(); _iL!=links.end(); ++_iL)
{
printf("(%d,%d)", _iL->a / 9, _iL->a % 9);
}
printf(", Candi:%d Cells to del:", X);
for (int i = 0; i < k; ++i)
{
printf("(%d,%d) ", arrDelPt[i].r, arrDelPt[i].c);
}
printf("/n");
}
linksN.erase(linksN.begin());
}
}
return false;
}
// 链l是否包含链t
bool IsExist(list<sdLink> & l, sdLink & t)
{
for (list<sdLink>::iterator ipt = l.begin(); ipt != l.end(); ++ipt)
if (ipt->a==t.a && ipt->b==t.b || ipt->a==t.b && ipt->b==t.a) return true;
return false;
}