数独游戏, 程序求解

xiaocai0001 2006-09-03 10:35:39
关于数独游戏的详细介绍就不多说了, 见下面这帖
http://www.topthinker.com/bbs/viewthread.php?tid=685&pid=5300&page=1&extra=page%3D1#pid5300

如果上不了, 可以去我的Blog看看详细介绍.
http://blog.csdn.net/xiaocai0001/archive/2006/09/03/1164188.aspx

大体就是:
游戏规则很简单:在九个九宫格里,填入1到9的数字,让每个数字在每个行、列及九宫格里都只出现一次。谜题中会预先填入若干数字,其它宫位则留白,玩家得依谜题中的数字分布状况,逻辑推敲出剩下的空格里是什么数字.

看到这个问题后, 偶想到用程序去搜索求解, 不过肯定会有回溯的问题.

想看看大家有什么开阔点的思路....
...全文
488 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
lw1a2 2006-09-06
  • 打赏
  • 举报
回复
哈哈,正在玩GBA上的,也写了一个,还没完成
xiaocai0001 2006-09-06
  • 打赏
  • 举报
回复
没人顶了, 分都没法给了.
lw1a2 2006-09-06
  • 打赏
  • 举报
回复
思路:将所有的0的座标加入到一个vector里,然后用回溯法遍历这个vector。

有谁写个非递归的?
lw1a2 2006-09-06
  • 打赏
  • 举报
回复
我用回溯写的:

#include <iostream>
#include <utility>
#include <vector>
using namespace std;

bool checkH(int ia[9][9], int x, int y)
{
for (int i=0; i<9 ;i++)
if ( x!=i && ia[i][y]!=0 && ia[i][y] == ia[x][y] ) return false;
return true;
}

bool checkV(int ia[9][9], int x, int y)
{
for (int i=0; i<9 ;i++)
if ( y!=i && ia[x][i]!=0 && ia[x][i] == ia[x][y] ) return false;
return true;
}

bool checkRect(int ia[9][9], int x, int y)
{
for (int i=x/3*3; i<=x/3*3+2; i++)
for ( int j=y/3*3; j<=y/3*3+2; j++)
{
if ( !(x==i && y==j) && ia[i][j]!=0 && ia[i][j] == ia[x][y] ) return false;
}
return true;
}

bool checkAll(int ia[9][9], int i, int j)
{
if (!checkH(ia, i, j) || !checkV(ia, i, j) || !checkRect(ia, i, j) ) return false;
else return true;
}


bool Backtrack( int ia[9][9], vector< pair<int, int> > &v, vector< pair<int, int> >::iterator it)
{
int i, j;
if (it!=v.end())
{
i=(*it).first;
j=(*it).second;
}
if (it==v.end())
{
return true;
}
else
{
int m;
for (m=1; m<=9; m++)
{
ia[i][j]=m;
if (checkAll(ia, i, j))
{
if (Backtrack(ia, v, it+1)) return true;;
}
}

ia[i][j]=0;
return false;
}
}


int main()
{
//初始
/*int ia[9][9]={ { 6, 0, 0, 2, 0, 0, 9, 0, 0 },
{ 0, 0, 0, 5, 0, 0, 7, 4, 0 },
{ 0, 7, 4, 9, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 8, 0, 5, 4 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 9 },
{ 8, 9, 0, 3, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 9, 2, 7, 0 },
{ 0, 2, 9, 0, 0, 3, 0, 0, 0 },
{ 0, 0, 3, 0, 0, 2, 0, 0, 8 } };*/

int ia[9][9]={ { 9, 0, 0, 0, 5, 7, 0, 0, 0 },
{ 0, 6, 2, 1, 0, 0, 7, 4, 0 },
{ 3, 0, 0, 9, 4, 2, 0, 0, 1 },
{ 0, 0, 0, 7, 0, 0, 8, 0, 6 },
{ 0, 8, 7, 0, 3, 0, 9, 2, 0 },
{ 6, 0, 9, 0, 0, 8, 0, 0, 0 },
{ 8, 0, 0, 2, 9, 1, 0, 0, 7 },
{ 0, 3, 1, 0, 0, 4, 5, 9, 0 },
{ 0, 0, 0, 3, 7, 0, 0, 0, 4 } };
vector< pair<int, int> > v;
for (int i=0; i<9; i++)
for (int j=0; j<9; j++)
{
if (!checkAll(ia, i, j))
{
cout<<"初始数错误,位置:"<<i<<' '<<j<<endl;
system("pause");
return 1;
}
if (ia[i][j]==0) v.push_back(make_pair(i,j));
}

Backtrack(ia, v, v.begin());

//显示
for (int i=0; i<9; i++)
{
for (int j=0; j<9; j++)
cout<<ia[i][j]<<' ';
cout<<endl;
}

system("pause");
}
fengfeiwuwq 2006-09-06
  • 打赏
  • 举报
回复
mark
xiaocai0001 2006-09-06
  • 打赏
  • 举报
回复
楼上的程序还有很多改进的地方, 比如说
bool puzzle::checkPuzzle(int x, int y)
可以改进得更高效一些.
sharkoasis 2006-09-06
  • 打赏
  • 举报
回复
这么多分,我来一个,以前写的,借鉴了一个网友的算法!
/****************puzzle.h********************/
#ifndef _PUZZLE_H_
#define _PUZZLE_H_

#include <iostream>
using namespace std;

class puzzle
{
private:
int array[9][9];
int tab[9][9];
string filename;
int end;
public:
puzzle();
puzzle(int a[][9]);
puzzle(string);
~puzzle();
void printPuzzle();
void printFile();
bool solvePuzzle();
bool checkPuzzle(int,int);
bool exec();
};

#endif //_PUZZLE_H_
/***********************end puzzle.h***************************/


/***********************puzzle.cpp***********************/
#include <iostream>
#include <fstream>

#include "puzzle.h"

using namespace std;


string
trimString(string &str)
{
string temp;
for (string::iterator iter = str.begin(); iter != str.end(); ++iter)
{
if ( !isspace(*iter) )
{
temp.push_back(*iter);
}
}
return temp;
}

puzzle::puzzle()
{
int i,j;
cout<<("please input the puzzle:\n");
for(i=0;i<9;i++)
{
string str;
cin>>str;

for(j=0;j<9;j++)
{
array[i][j]=str[j]-'0';
tab[i][j]=array[i][j];
}
}
}

puzzle::puzzle(int a[][9])
{
int i,j;
for(i=0;i<9;i++)
for(j=0;j<9;j++)
{
array[i][j]=a[i][j];
tab[i][j]=array[i][j];
}
}

puzzle::puzzle(string fname)
{
filename=fname;
int i,j;
ifstream infile;
string strbuf;
infile.open(fname.c_str());
if (infile.fail())
{
cerr << "Fail to open input file \"" << filename << "\"!" << endl;
exit(-1);
}

if(!infile.eof())
{
//getline(infile,strbuf,'\n');
//strbuf=trimString(strbuf);
//cout<<strbuf<<endl;

for(i=0;i<9;i++)
{
getline(infile,strbuf,'\n');
strbuf=trimString(strbuf);
//cout<<strbuf<<endl;
for(j=0;j<9;j++)
{
array[i][j]=strbuf[j]-'0';
tab[i][j]=array[i][j];
}
}

}
end=infile.tellg();
infile.close();
}

puzzle::~puzzle()
{

}

void puzzle::printPuzzle()
{
int i,j;
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
{
cout<<array[i][j]<<" ";
}
cout<<'\n';
}
cout<<endl;
}

void puzzle::printFile()
{
ofstream outfile;
outfile.open(filename.c_str(),ios_base::app);
if (outfile.fail())
{
cerr << "Fail to open input file \"" << filename << "\"!" << endl;
exit(-1);
}
//outfile.seekg(end);
outfile<<endl;
outfile<<"The Result is:"<<endl;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
outfile<<array[i][j]<<" ";
outfile<<endl;
}
outfile.close();
}

bool puzzle::solvePuzzle()
{
int i, j;
i = j = 0;
bool bw=false;
while (i < 9 && j < 9 && i>-1 && j>-1)
{
if (tab[i][j]==0)
{
bw=false;
array[i][j]++;
for (; array[i][j] <= 9; array[i][j]++)
{
if (checkPuzzle(i, j))
break;
}
if (array[i][j] >= 10)
{
// backward
bw=true;
array[i][j] = 0;
}
}
if(bw==true)
{
//backward
if (j == 0)
{
j = 8;
i--;
}
else
{
j--;
}

}
else
{
j++;
i+=j/9;
j%=9;
}
}
if(i<0 || j<0)
return false;
else
return true;
}
bool puzzle::checkPuzzle(int x, int y)
{
int i;
int tag[10];
// check row

for (i = 0; i < 10; i++)
tag[i] = 0;
for (i = 0; i < 9; i++)
tag[array[x][i]]++;
for (i = 1; i < 9; i++)
if (tag[i] > 1)
return false;
// check colomn

for (i = 0; i <10; i++)
tag[i] = 0;
for (i = 0; i < 9; i++)
tag[array[i][y]]++;
for (i = 1; i < 10; i++)
if (tag[i] > 1)
return false;
// check small puzzle

for (i = 0; i < 10; i++)
tag[i] = 0;

int xx, yy;
xx = x - x % 3;
yy = y - y % 3;
int j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
tag[array[xx + i][yy + j]]++;
for (i = 1; i < 10; i++)
if (tag[i] > 1)
return false;

return true;

}

bool puzzle::exec()
{
if(solvePuzzle())
return true;
else
return false;

}
/*************************end puzzle.cpp***************************/

/**************************main.cpp******************************/
#include <iostream>
#include <string>

#include "puzzle.h"

using namespace std;

#define PUZZLE_TOOL_NAME "Auto Solve Sudoku Tools"
#define PUZZLE_VERSION "1.0"
#define PUZZLE_COPYRIGHT "Coded by Lijing"

void showCopyright()
{
cout << "================================================" << endl;
cout << " " << PUZZLE_TOOL_NAME << endl;
cout << " Ver " << PUZZLE_VERSION << endl;
cout << " " << PUZZLE_COPYRIGHT << endl ;
cout << "================================================" << endl << endl;

}
void printUsage()
{
cout<<endl
<<"Usage:"<<endl
<<" puzzle -f <filename> -i -d -s"<<endl
<<"-f <filename> input from file"<<endl
<<"-i input from console"<<endl
<<"-d demo"<<endl
<<endl;
}

void demo(int matrix[][9])
{
puzzle puz(matrix);
cout<<"The demo matrix is:"<<endl;
puz.printPuzzle();
if(puz.exec())
{
cout<<"The result matrix is:"<<endl;
puz.printPuzzle();
}
else
cout<<"The matrix can't be solved"<<endl;
}

void input()
{
puzzle puz;
cout<<"You input matrix is:"<<endl;
puz.printPuzzle();
if(puz.exec())
{
cout<<"The result matrix is:"<<endl;
puz.printPuzzle();
}
else
cout<<"The matrix can't be solved"<<endl;
}

void file(string name)
{
puzzle puz(name);
cout<<"File input matrix is:"<<endl;
puz.printPuzzle();
if(puz.exec())
{
cout<<"The result matrix is into the \""<<name<<"\":"<<endl;
puz.printFile();
}
else
cout<<"The matrix can't be solved"<<endl;
}


int main(int argc,char** argv)
{
int matrix[9][9]={
0, 0, 8, 2, 0, 4, 0, 9, 0,
0, 1, 0, 5, 0, 0, 4, 2, 0,
5, 0, 0, 0, 8, 0, 0, 0, 3,
0, 7, 2, 0, 0, 0, 3, 0, 0,
8, 0, 0, 7, 0, 0, 0, 0, 6,
0, 0, 0, 1, 0, 0, 0, 0, 9,
0, 4, 7, 0, 0, 1, 0, 0, 0,
2, 0, 0, 0, 9, 0, 0, 5, 0,
0, 0, 0, 0, 7, 0, 0, 8, 0
};
//test
/*
// puzzle puz1(matrix);
puzzle puz1("aaa");
cout<<"input the matrix is:"<<endl;
puz1.printPuzzle();

if(puz1.exec())
{
cout<<"the solved matrix is:"<<endl;
puz1.printPuzzle();
//puz1.printFile();
}
else
cout<<("cant be solved\n");

*/
showCopyright();

if(argc==1)
demo(matrix);
else if(argc==2)
{
if(strcmp(argv[1],"-i")==0)
input();
else if(strcmp(argv[1],"-d")==0)
demo(matrix);
else
printUsage();
}
else if(argc==3)
{
if(strcmp(argv[1],"-f")==0)
file(argv[2]);
else
printUsage();
}
else
printUsage();




return 0;
}

/**************************end main.cpp**************************/
mathe 2006-09-04
  • 打赏
  • 举报
回复
可以同时使用回溯和规则。如果规则用的比较多,那么大部分情况就都可以用规则了。
我放了个程序在:http://blog.csdn.net/mathe/archive/2006/09/04/1175498.aspx
39457760 2006-09-03
  • 打赏
  • 举报
回复
约束满足问题
回溯+前向检验可以解决,效率也很高。
仅仅使用回溯效率太低
OOPhaisky 2006-09-03
  • 打赏
  • 举报
回复
帮楼主顶一下:)
DentistryDoctor 2006-09-03
  • 打赏
  • 举报
回复
好像属于算法类问题。
jixingzhong 2006-09-03
  • 打赏
  • 举报
回复
给小雨点人气 ^_^
mathe 2006-09-03
  • 打赏
  • 举报
回复
数独游戏都是唯一结果的,回溯很简单。我些国
xiaocai0001 2006-09-03
  • 打赏
  • 举报
回复
自己先Mark一下, 好找帖子.
donglangbeigu 2006-09-03
  • 打赏
  • 举报
回复
mark
睡在床板下_ 2006-09-03
  • 打赏
  • 举报
回复
mark
  • 打赏
  • 举报
回复
应该用回溯可以解决。Mark一下。
0黄瓜0 2006-09-03
  • 打赏
  • 举报
回复
看看。
唐巧 2006-09-03
  • 打赏
  • 举报
回复
因为大小只是9x9,所以即使是回溯也不会花太长时间的。我个人认为回溯就是很好的解法了。

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧