其中ResovleCells()函数的参数含义是: 输入数独游戏的原始状态.
如下就是data.txt一个范例:
0 0 0 8 0 2 1 0 0
0 0 0 0 0 0 6 0 5
0 0 4 6 1 5 0 0 0
6 9 0 0 0 0 0 3 0
4 0 0 1 6 8 0 0 9
0 7 0 0 0 0 0 4 6
0 0 0 7 8 1 5 0 0
7 0 2 0 0 0 0 0 0
0 0 8 2 0 9 0 0 0
可以运行本程序求解得到:
5 3 6 8 7 2 1 9 4
2 1 7 9 3 4 6 8 5
9 8 4 6 1 5 3 2 7
6 9 5 4 2 7 8 3 1
4 2 3 1 6 8 7 5 9
8 7 1 5 9 3 2 4 6
3 4 9 7 8 1 5 6 2
7 5 2 3 4 6 9 1 8
1 6 8 2 5 9 4 7 3
Successful
//================================================
// main.cpp
#include "ShuDu.h"
int main()
{
CShuDu shudu;
shudu.ResolveCells("data.txt");
return 0;
}
//===============================================
// ShuDu.h
#ifndef __SHUDU_H__
#define __SHUDU_H__
#include <memory.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
typedef int ELEMTYPE;
typedef int BOOL;
#define FALSE 0
#define TRUE 1
class CShuDu
{
public:
CShuDu();
BOOL ResolveCells(const string &filename);
~CShuDu();
private:
BOOL InitCells(const string &filename);
BOOL RecursionBody(int position);
BOOL CheckValid(int row, int col);
BOOL PrintCells();
protected:
ELEMTYPE m_iCells[9][9];
BOOL m_bReadOnly[9][9];
};
// ============================================================
CShuDu::CShuDu()
{
// Initial primative cells to 0.
memset(m_iCells, 9*9, sizeof(ELEMTYPE));
}
CShuDu::~CShuDu()
{
// nothing to do
}
BOOL CShuDu::InitCells(const string &filename)
{
ifstream infile;
ELEMTYPE iCount;
infile.open(filename.data());
if(!infile)
{
// open file fail
cout<<filename<<" open fail!"<<endl;
return FALSE;
}
iCount = 0;
while(!infile.eof() && iCount < 81)
{
// read data to m_iCells array
ELEMTYPE *pCurrentInput = &m_iCells[iCount/9][iCount%9];
BOOL *pCurrentBool = &m_bReadOnly[iCount/9][iCount%9];
infile>>*pCurrentInput;
if(*pCurrentInput < 0 || *pCurrentInput > 9)
{
cout<<"Init data "<<*pCurrentInput<<" out of range!"<<endl;
return FALSE;
}
else
{
if(*pCurrentInput != 0)
*pCurrentBool = TRUE;
else
*pCurrentBool = FALSE;
++iCount;
}
}
if(iCount != 81)
{
// total number error
cout<<"Total input data number error!"<<endl;
return FALSE;
}
return TRUE;
}
BOOL CShuDu::PrintCells()
{
int i, j;
for(i=0; i<9; ++i)
{
for(j=0; j<9; ++j)
cout<<" "<<m_iCells[i][j];
cout<<endl;
}
return TRUE;
}
BOOL CShuDu::CheckValid(int row, int col)
{
int i, j;
ELEMTYPE *pCurrent = &m_iCells[row][col];
// check row
for(j=0; j<9; ++j)
{
if(m_iCells[row][j] == *pCurrent)
{
if(j != col)
return FALSE;
}
}
// check col
for(i=0; i<9; ++i)
{
if(m_iCells[i][col] == *pCurrent)
{
if(i != row)
return FALSE;
}
}
// check sub 9-cells
int m = row / 3;
int n = col / 3;
for(i=m*3; i<(m+1)*3; ++i)
{
for(j=n*3; j<(n+1)*3; ++j)
{
if(m_iCells[i][j] == *pCurrent)
{
if(pCurrent != &m_iCells[i][j])
return FALSE;
}
}
}
// no the same element yet, it is valid at present status.
return TRUE;
}
BOOL CShuDu::ResolveCells(const string &filename)
{
if(!InitCells(filename))
return FALSE;
BOOL bResult = RecursionBody(0);
if(bResult)
cout<<"Successful"<<endl;
else
cout<<"Failure"<<endl;
return bResult;
}
BOOL CShuDu::RecursionBody(int position)
{
if(position >= 81)
{
// get the right answer
PrintCells();
return TRUE;
}
int row, col;
row = position / 9;
col = position % 9;
while(position < 81 && m_bReadOnly[row][col])
{
++position;
row = position / 9;
col = position % 9;
}
if(position >= 81)
return RecursionBody(position);
// still exist cells that have not be filled.
ELEMTYPE *pCurrent = &m_iCells[row][col];
for(int i=1; i<=9; ++i)
{
*pCurrent = i;
if(!CheckValid(row, col))
continue;
// get the correct answer
if(RecursionBody(position+1))
return TRUE;
}
*pCurrent = 0;
return FALSE;
}
#endif