数独游戏设计与源码

上传人:ch****o 文档编号:138557932 上传时间:2022-08-21 格式:DOC 页数:17 大小:62KB
收藏 版权申诉 举报 下载
数独游戏设计与源码_第1页
第1页 / 共17页
数独游戏设计与源码_第2页
第2页 / 共17页
数独游戏设计与源码_第3页
第3页 / 共17页
资源描述:

《数独游戏设计与源码》由会员分享,可在线阅读,更多相关《数独游戏设计与源码(17页珍藏版)》请在装配图网上搜索。

1、数据结构大型作业实验报告书设计题目:“数独”游戏设计与求解一 题目说明 数独的游戏规则:1、 在99的大九宫格内,已给定若干数字,其他宫位留白,玩家需要自己按照逻辑推敲出剩下的空格里是什么数字。2、必须满足的条件:每一行与每一列都有1到9的数字,每个小九宫格里也有1到9的数字,并且一个数字在每行、每列及每个小九宫格里只能出现一次,既不能重复也不能少。3、每个数独游戏都可根据给定的数字为线索,推算解答出来。 按照数独的游戏规则,用计算机实现已知数独的求解和数独题目的出题。二 数据结构说明数据结构一维数组、二维数组以及类似于“栈”的数据结构。主要操作有:进栈,出栈,栈顶元素的操作等等三 抽象数据类

2、型(Abstract Data Type 简称ADT) 五个全局变量数组,其中两个二维数组,三个一维数组。int a1010接受输入数据,空白处则初始化为0。之所以把数组范围设计为10*10,是为了程序的可读性。符合人的习惯思维。int sd82在实现“回溯”算法的时候,因为要用到栈的数据结构,所以把a1010二维数组中的数据转换储存进sd82一维数组。方便处理题目以及保存最后结果。int fix82对应于sd82,记录哪些位置已经确定。确定则fix值为1,未确定为0。int possible8210第一维对应着sd82中的每一个,第二维的下标为每个位置的可能值。有可能则为第二维的下标,不可能

3、则为-1。int stack82类似于“栈”数据结构的数组,实现“回溯”算法的关键所在。回溯之前,把所有fix值为0的数据存如stack数组中,即进栈。回溯中逐渐确定这些位置的数值,无法确定者(即1-9都不适合的)则应回退到前一位置,修改其fix值,以此类推。直至stack中所有的值都确定下来(即题目完成),或者回退到了最初点的前一位置(说明题目有误)。四 算法设计程序可以考虑人工智能的算法。所谓人工智能的算法,应当是算法设计者对该游戏的特性有较为深入的了解,依据其内在联系设计出的和人类思维相似的解决算法。但这似乎太过复杂,所以这里决定采用“回溯”的方法解决数独问题。基本框架如下:“回溯法计算

4、数独从界面读取数据到a1010预处理,算出所有fix和possible值将a1010中数据转存入sd82五数独程序代码:#includestdio.h /标准输入输出头文件#includeconio.h /包含getch()的头文件#includestdlib.h /包含rand()的头文件#includeassert.h /包含assert()的头文件#includetime.h /包含srand()的头文件/五个全局变量数组int a1010;/用来接收输入数据的数组int sd82;/处理题目以及保存最终结果int fix82;/记录哪些位置是确定的,确定为1,否则为0int possi

5、ble8210;/记录所有未确定数字的可能性int stack82;/用来放置填入的数的栈void clssd()/初始化函数,所有位置设为0int i,j,k;for(i=0;i9;i+)for(j=0;j9;j+)aij=0;for(k=1;k=81;k+)sdk=0;int line(int line,int value)/检验行int i;for(i=1;i=9;i+)if(alinei=value) return 0;return 1;int row(int row,int value)/检验列int i;for(i=1;i=9;i+)if(airow=value) return 0

6、;return 1;int square(int line,int row,int value)/检验3*3的九宫int L,R,i,j;L=(line%3!=0)+line/3;/L表示所在九宫的行数R=(row%3!=0)+row/3;/R表示所在九宫的列数for(i=(L-1)*3+1;i=L*3;i+)for(j=(R-1)*3+1;jalinerow之间的转换int line;line=i/9+(i%9!=0);return line;int transform_to_row(int i)/实现sdi-alinerow之间的转换int row;row=i%9+9*(i%9=0);re

7、turn row;void transform_to_a(int i)/sdi-alinerow的转换int l,r;l=transform_to_line(i);r=transform_to_row(i);alr=sdi;void transform_to_sd()/实现alinerow-sdi的转换int line,row,i=1;for(line=1;line=9;line+)for(row=1;row=9;row+)dosdi=alinerow;i+;break;while(i=81);/输出函数void printAll()int i;for(i=0;i81;i+)if(i%9=0)

8、printf(nntt);printf(%4d,sdi+1);printf(nnn);void input()/输入数据到a1010system(cls);/清屏int b3=0,0,0,i,j;printf(请输入已知数据);printf(nn例如输入7 8 9,表示第8行 第9列的数值为7,以此类推。nnn);doprintf(n输入数据:按照 值 / 行 / 列的顺序,以0结束);for(i=0;i0&j10)bi=j;printf(%3d,bi);else i-;ab1b2=b0;while(j);transform_to_sd();printf(nnnt您输入的题目为:nn);/打印

9、输入的数独printAll();/三个重要函数bool beExist(int i,int j)/判断 sd 数组中位置为 i 的元素是否存在int l,r;l=transform_to_line(i);r=transform_to_row(i);/if(sdi!=0) return 1; 关键的错误所在!if(line(l,j)*row(r,j)*square(l,r,j)=0) return 1;else return 0;void setPb()/控制possible数组int i,j;for(i=1;i=81;i+)for(j=1;j=9;j+)if(sdi!=0) possiblei

10、j=-1;/如果sdi为已知输入数据,则将可能值设为-1else if( beExist(i,j)possibleij=-1;/若在行、列、九宫内,存在相同数值则possible设为-1else possibleij=j;/其他情况讲可能值保存进possible数组bool fixAll(int sd,int fix,int possible8210)/控制fix数组int i,j;int k82;for(i=1;i=81;i+)/将已经存在的数据对应fix数组中的值设为1,不存在设为0if(sdi!=0) fixi=1;else fixi=0;for(i=1;i=81;i+)/判断未确定空格

11、处值的可能性if(sdi!=0) continue;if(fixi=0)for(j=1;j=9;j+)if(possibleij!=-1)ki+;if(ki=1)/如果存在只有一种可能的位置则将fixi改为1fixi=1;sdi=possibleij;for(i=1;i=81;i+)/判断是否存在只有一种可能的位置,若没有返回0if(ki=1) return 1;else return 0;/判断是否完成int isFull(int sd)int i;for(i=1;i=81;i+)if(sdi=0) return 0;return 1;void preDo()/预处理while(1)setP

12、b();if(!fixAll(sd,fix,possible) /即不存在只有一种可能性的位置break;if(isFull(sd) /若已经推出全部结果break;if(isFull(sd)printAll();/打印结果int calculate()/填数独 (关键算法!)preDo();/预处理,找出所有的位置的可能数值if(isFull(sd) return 1;int top=0;/将所有为0的位置入栈for(int i=1;i=0);/宏定义,调试程序之用if(flag)int j;for(j=1;j=max) return 1;break;if(j9)/该空所有可能值都不可以,则

13、退一格-top;if(top0) printAll(); return 0;flag=false;elseif(sdstacktop=9)/说明当前这个top也没有可以选择的数,继续回退fixstacktop=0;sdstacktop=0;transform_to_a(stacktop);-top;if(top9)break;if(temp9)/当前节点没有更换的可能性,继续退回fixstacktop=0;sdstacktop=0;transform_to_a(stacktop);-top;if(top0) printAll(); return 0;elsesdstacktop=temp;tr

14、ansform_to_a(stacktop);+top;flag=true;/重新设定flagvoid solve_problem()/解题int p;system(cls); /清屏clssd(); /赋初值为0input(); /输入数据transform_to_sd(); /转换为sdi数组p=calculate(); /计算数独if(p=0)printf(t题目有误! );printf(nnt答案为:n);printAll();void random()/从1-9中随机产生几个值输入sd1至sd9int i,j,r;int change=1;int b10=0,0,0,0,0,0,0,

15、0,0,0; for(i=1;i=9;)/从1-9中随机产生几个值 change=1;j=1+rand()%9;for(r=1;r=9;r+) if(br=j) change=0;if(change=1)bi=j; i+; for(i=1;i5|f1);/一共5个级别for(i=1;i=f)/利用随机数出现的概率出题printf(%4d,sdi);elseprintf( 0);if(i%9=0)printf(nn);void make_problem()/出题函数system(cls);/初始化clssd();random();/填9个随机值calculate();/算出答案hide();/遮

16、罩,将答案中一些数值遮住printf(ttt注意:题目中0代表待填数据nntt 按空格键输出答案,其他键退出程序n);int f;dof=getch()-32;if(!f)printAll();else break;while(f);void main()/主函数srand(unsigned)time(0);/设置时间种子为0system(cls);/清屏clssd();printf(nt数独游戏nnt1.你出题,电脑来解nnt2.电脑出题,你来解);int i;doi=getch()-48;switch(i)case 1:solve_problem();break;case 2:make_p

17、roblem();break;while(i2|i=0)top是栈顶元素的“指针”,用来操控栈中元素。正常情况下top=0的。如果出现异常情况,则assert函数会弹出对话框报错。这表示calculate函数在回溯的时候top值总是会回到栈底元素之前。事实上,开始因为在beExist()函数中用了错误的判断方式,运行程序时总是会使得top0。4. 上面一条提到的,beExist()中用到了错误的判断语句(/if(sdi!=0) return 1;),这就是关键的错误所在。调试程序的时候总是会导致top0却一直找不到为什么。开始以为是possible的值没有随着回溯算法的进行跟随sd的变化而变化

18、,于是在每次sd变化之后都加上了一个setPb()函数,使得possible值每填一个数据就变化一次。但是导致的结果却是一旦开始回溯,必定会回溯到栈底之前。运用调试工具观察possible和top值的变化才发现。回溯的时候,之前填的空格处possible值都为-1,所以top每次都将回到栈底之前。于是以为是setPb()用的太多了,又重新删掉多余setPb()函数,结果还是一样。又经过几个小时的调试,终于发现是在calculate函数执行时,判断每次判断是否回溯都会运行函数beExist( ),调试时,进入beExist()函数发现,自己之前在写这个函数的时候想当然的把sdi!=0当作了判断已经存在(即beExist为真)的条件。直接导致top回溯到了栈底。于是屏蔽掉这条/if(sdi!=0) return 1之后,程序就基本可以正常运行了。5. 上一条中的错误之所以会出现,是因为在设计程序之初没有想好,不够完善。于是出现了,自己设计的判断方法与计算数独矛盾的结果。得到的教训是,动手之前应该先考虑清楚完整的架构和应该考虑到的细节。七 测试结果分析下面为规定测试数据:342172914579576231543182725419732531376852361

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!