数独游戏程序

mathe的专栏  http://blog.csdn.net/mathe/article/details/1175498


 

数独游戏程序

分类: 软件   22389人阅读  评论(26)  收藏  举报

数独简介:
    数独是一个智力小游戏。一个9*9的棋盘,共有9行9列以及9个互不相交的3*3九宫格。里面某些格子开始已经填上了1-9中的一些数字。要求玩家在余下的空格中填上1-9中数字,使得每行,每列和每个3*3九宫格中都正好包含1-9数字各一个。数独游戏保证结果的存在和唯一性。
例子:
  

我下载了一些网上的数独游戏程序,玩起来觉得不是很舒服,所以决定自己开发一个。
现游戏具有的功能:
  i)  随机产生任意多的游戏(理论上可以产生2^9679228162514264337593543950336个不同的游戏)
  ii) 
游戏分成四个不同级别(入门级,高级,专家级,骨灰级)
  iii) 
通过模拟人工解数独问题提供人性化的提示,几乎所有游戏都完全可以仅用提示解决
iv)
提供尝试功能(使用Shift键加数字键或鼠标左键)
 v)
可以用户自定义游戏,用户可以直接输入或者通过剪切板复制游戏
  vi)
可以将计算机模拟人工求解过程复制到剪切板(Ctrl+U),会使用人工推理方法:唯一数隐含唯一数数对隐含数对唯一矩形法三链数隐含三链数四链数隐含四链数区域删减法矩形法(X-WING, SwordFish, JellyFish),关连数删减法(Forcing Chain)等

  vii)
语音提示功能(M键切换语音功能)
 viii)
历史记录图形化回放功能
 ix) 最新2.4版添加了语音命令功能

最新下载链接(932K)(2.4.1版):

   下载地址1:      无限数独2.41版安装程序  (932K,添加语音命令功能)

  下载地址2:   http://download.csdn.net/source/273047 (仅CSDN用户可用)


游戏说明:

1.玩游戏过程:
 
  
如上图,在游戏中还没有填充的格子中,在候选数显示模式,计算机会自动显示所有的候选数。其中黑色大数字是游戏事先设置好的数字,蓝色大数字是玩家填充的数字,黑色小数字是每个格子的候选数。但是在非候选数模式,计算机不会显示候选数。
用户可以使用鼠标或键盘玩游戏。用鼠标左键点击一个候选数(仅用于候选数显示模式)或鼠标在格子上时按数字键选择一个数1-9。用鼠标右键或同时按住Ctrl和数字键来减少或添加候选数(仅用于候选数显示模式)。按HCtrl+H获得提示。

显示部分候选数功能:仅提供键盘操作。按住Ctrl+Shift+数字键1-9分别只显示候选数19Ctrl+Shift+0显示所有候选数。而在显示部分候选数时,也可以通过左右键改变当前显示的候选数。
 

游戏还提供无限制步数的取消和重做功能,任何时候可以通过菜单项"编辑/取消”或热键Ctrl+Z取消上一步操作。对于取消后的步骤可以通过Ctrl+Y键重做。 批量取消功能:通过用鼠标右键点击一个用户已经设置好的数据,这将取消这个格子里面的数据,并且所有在设置这个数字后面的步骤全部被取消。同样,用右键点击一个已经被加灰(推理删除)的候选数(仅用于候选数显示模式),将取消将这个候选数隐含的步骤,同时它后面的所有步骤也全部取消。在批量取消后,同样可以通过选择菜单项“重做”来重新使用这些被取消的步骤,如果因为错误操作(比如不小心用鼠标右键点中一个格子),可以通过按Shift+Y来重做所有被取消的步骤。
任何时候,我们还可以通过Shift+Z键来检查我们前面的游戏过程是否出现错误,如果出现错误,计算机会自动取消所有错误的步骤

在候选数显示模式,可以按住Shift然后用鼠标选择一个数字,表示尝试使用这个数据,计算机将在这个选择的数据上打上标签,如上图中H7B2格子分别打上标签T1T2.这个表示用户先尝试了H6=4,然后又尝试了B2=5. 在非候选数显示模式,可以通过Shift+数字键来使用尝试功能。
在游戏出现矛盾时(发现尝试失败),可以通过按住Shift然后用鼠标右键选择一个尝试过的格子(通常应该选择最大标签的格子),这样计算机就认为这个尝试失败,会退回尝试前状态并且自动将这个错误候选数剔除。也可以不按住Shift而是直接用右键选择这个格子,这时只是使用了普通批量撤销功能到使用这个尝试之前的状态。

通过复制和粘贴功能,可以输入输出游戏。任何时候,按Ctrl+C或者用菜单项"编辑/复制"将把当前游戏局面(所有填充格子的数据被复制)以文本方式复制到粘贴板;然后用户可以将这个局面复制到任何地方。如果用户想复制游戏的起始局面,可以先按Ctrl+R到游戏的起始状态,然后复制游戏,如果再想恢复到自己玩的状态,使用Shift+Y键重新回到前一个步骤就可以了同样,对于其他地方以文本形式存在的数独游戏,用户可以先复制到粘贴板,然后切换到游戏按Ctrl+V或者用菜单项"编辑/粘贴"将当前游戏设置成此游戏;计算机会尽量去猜测用户输入局面的格式,但是不能保证总是成功。 对于无法通过粘贴输入的游戏,可以通过使用菜单项"文件/手工输入"来输入游戏,选择这个菜单项后,依次用鼠标或键盘输入预定义数字,输入完毕后,选择菜单项”文件/完成手工输入“来结束游戏的输入,计算机会自动判断输入局面是否只有唯一解。

在不显示候选数模式,用鼠标左键点击任意一个方格,状态条将显示这个方格中所有候选数。
任何时候按R键,将显示鼠标所在行各个候选数所在格子
任何时候按C键,将显示鼠标所在列各个候选数所在格子
任何时候按B键,将显示鼠标所在九宫各个候选数所在格子

历史记录浏览
在历史记录浏览模式,可以使用左右键浏览过去玩过的游戏,计算机会猜测玩家使用过的策略,并且用图形模式显示出来。按HOMEEND键分别跳到开始和结束状态。按ESC键退出历史模式。

在历史模式使用Ctrl+U键将把用户的解答过程用文本方式复制到粘贴板,而非历史模式,使用Ctrl+U键计算机将自动产生一个模拟人工解答过程,并且把它以文本方式复制到粘贴板。

4.计算机提供提示中所用到的方法:
现在提供了:唯一数隐含唯一数数对隐含数对唯一矩形法三链数隐含三链数四链数隐含四链数区域删减法矩形法(X-WING, SwordFish, JellyFish),关连数删减法(Forcing Chain)

5. 游戏难度划分:
 入门级:使用唯一数隐含唯一数数对就可以解决的游戏
高级:    除了入门级的方法,还需使用隐含数对区域删减法三链数的。
专家级:使用了4中除关连数删减法外提供的方法能够找到结果,但是仅仅用高级的方法还不够的。
骨灰级:需要使用关连数删减法才有可能解决的问题

6. 游戏技巧(以及计算机提示方法介绍)
i)唯一数法

如果我们发现某个格子中只有一个可用候选数,那么这个格子必然是这个数字,这就是唯一数法
如下面例子,H5格子中只有唯一候选数3

如果没有使用候选数模式,那么得到提示信息会如下图


ii)隐含唯一数法

如果我们发现某一行某一列或某个九宫有一个候选数只出现在一个格子里面,那么这个格子必然是这个数字,这就是隐含唯一数法,如下面例子,第3列候选数4只出现在格子I3中. 本软件还提供了一种显示单一候选数的模式,在单一候选数模式,我们可以更加容易找到隐含唯一数。比如在这里,我们按Ctrl+Shift+4,那么软件将会只显示候选数4,在这种模式下,就可以非常容易看出I3中的4是隐含唯一数。

如果没有使用候选数模式,得到提示如下:

而对于隐含唯一候选数法(还有区间删减法和各种矩形法)我们还可以使用单一候选数模式,比如对于这个例子
我们可以通过按Ctrl+Shift+4键只显示候选数4,得到如下一个图,根据下图,很显然I3中4是隐含唯一数

iii)数对法

如果我们发现某一行某一列或某个九宫有两个格子只使用了两个候选数,那么这两个格子必然正好是这两个数字,那么在这个单元(行,列,或九宫)中,其它格子不会出现这两个候选数,这就是数对法,如下面例子,第一列中B1和G1的候选数都是7,8;那么D1,H1中的候选数7,8可以删除。

iv)三链数法

如果我们发现某一行某一列或某个九宫有三个格子只使用了三个候选数,那么这三个格子必然正好是这三个数字,那么在这个单元(行,列,或九宫)中,其它格子不会出现这三个候选数,这就是三链数法,如下面例子,
最下面中间的九宫中格子H4,H5,I5三个格子都只使用候选数2,8,6;所以G4,G6,I6中出现的8,6都可以删除

v)四链数法

如果我们发现某一行某一列或某个九宫有四个格子只使用了四个候选数,那么这四个格子必然正好是这四个数字,那么在这个单元(行,列,或九宫)中,其它格子不会出现这四个候选数,这就是四链数法;如下面例子中
上面中间的九宫中四个格子A5,B5,C4,C5都只使用了数字1,2,3,4;所以另外4个格子A4,A6,B4,C6中出现的数字1,2,3,4可以删除

vi)隐含数对法

如果我们发现某一行某一列或某个九宫中有两个候选数只出现在两个格子中,那么这两个格子必然正好是这两个数字,那么这两格子中其他候选数可以删除,这就是隐含数对法;如下面例子,第A行中,只有格子A7,A8使用了数字6,8;所以这两个格子中其它数字2,5,9都可以删除

vii)隐含三链数法

如果我们发现某一行某一列或某个九宫中有三个候选数只出现在三个格子中,那么这三个格子必然正好是这三个数字,那么这三格子中其他候选数可以删除,这就是隐含三链数法,如下面例子,第8列中只有格子C8,F8,G8使用了数字1,3,4;所以格子F8中出现的其它数字6,7,8可以删除

viii)隐含四链数法

如果我们发现某一行某一列或某个九宫中有四个候选数只出现在四个格子中,那么这四个格子必然正好是这四个数字,那么这四格子中其他候选数可以删除,这就是隐含四链数法,我们借用四链数中的例子,可以发现上面中间的九宫格中,只有格子A4,A6,B4,C6使用了四个数字5,6,7,9;所以它们使用的其他数字1,2,3,4可以删除。

ix)区域删减法

如果我们发现某一候选数在某一单元(行,列,九宫)中完全处在同另外一个单元的交集中,那么在另外一个单元中,不在交集中的这个候选数必然可以删除,如下面例子,第D行中所有数字5都正好在左边中间的九宫中,所以在这个九宫中,不在第D行的候选数5(E3中)可以删除。本软件中,我们也可以使用显示单一候选数模式来更加容易的发现区域删减法的机会。

x) 矩形法

如果某个候选数在某两行(列)中只出现在某两行(列)中,那么在那两行(列)中,不在那两列(行)的这个候选数都可以删除,如下面例子,第C行和第F行的候选数3都正好是两个而且出现在第1列和第8列;所以第1列和第8列中,不在第C行和第F行的候选数3 (A8,D1,D8,I1,I8)都可以删除。矩形法也可以在显示单一候选数模式下发现

把它扩展到三行或四行就可以得到高阶矩形法,同样下面例子中可以删除蓝色的候选数6

下面的例子中粉色4可以删除

 xi)唯一矩形法

最新添加唯一矩形法,这个方法利用了数独结果唯一性的特性:如果有四个构成矩形顶点的格子只使用两个数字,而且同在一行或同在一列的格子在同一个宫格中,那么这个局面的结果必然不是唯一的(交换它们使用的数字同样可以得到合法的数独结果),必然不是合法的数独局面。通过这个结论我们分别得到两种删减法:
如下图A3,C3,A9,C9中,C3必然不能取候选数19(不然结果必然不唯一),所以C3只能取候选数5

如下图,D2F2中必然有一个格子结果是3,不然D2,F2,D9,F9都只能是数字19,结果必然不唯一。
由此进一步得出第2列中H2不能取3(同样还可以得出在左中宫格中F3不能取3)

xii)关连数删减法

通过找到一串强关联数据来得出矛盾来删除候选数。
如下图,第9列只有G9D9有候选数3,它们之间就是一种强关联数据,同样D4I4之间也是强关联的。而如果一个格子中只有两个候选数,那么我们认为这两个候选数也是强关联的数据。
此外D9D4之间在同一行都使用数据3,它们是弱关联,同样在一个格子中两个不同候选数也可以看成弱关联。这样通过一系列强弱关联(弱关联可以用强关联替代),
如果我们可以得到一个矛盾链。如下图,我们可以通过提示中逻辑推理排除G6=3(实际上还可以排除I7=3I8=3)

下面是一个更加复杂的例子,用到了多个不同候选数值:

 

查看评论
22楼  xieyuebo 昨天 01:18发表 [回复]
刚刚开始玩这个游戏,发现你讲解得很好,3Q
21楼  yuanwei1314 2012-04-26 10:57发表 [回复]
您好,请问怎么样才能保证数独的唯一性啊。。。求赐教
20楼  cuixiping 2011-09-23 06:37发表 [回复]
我这两天思考数独的问题,有一个没想明白,特请教一下。
开局最少17个数字大家都知道,那开局最多有多少个数字呢?
(冗余可删除的数字不算,有效开局指删除其中任何一个数字都会导致多解)
你对这个有没有研究或者想法?
19楼  jsgame 2011-08-10 10:06发表 [回复]
你好,你的数独是我见过写的最强的。
能否说说你压缩局面的算法?
就是这个:976B2247BC518A205B3F6EA
我也是用的算术编码压缩,但是结果比你的要长几个字符,请问你用的概率是怎么样的?
18楼  lc_cc 2011-02-05 09:21发表 [回复]
[e01]正在看2008MCM,参考一下
17楼  zoomlp 2010-11-18 17:07发表 [回复]
自从用了h键再也不能用数标左键一步步解题了,如何恢复一步步解题(手工在候选数模式下)。请赐教!!!谢谢!!!!
16楼  zoomlp 2010-11-12 12:26发表 [回复]
2007年的作品还真的不错,虽说现在最强的是HoDoKu v2.01。但作为中国人喜欢用你的。
15楼  cuimolei 2010-07-11 22:58发表 [回复]
数独数组的唯一性解是怎么样确保的?
14楼  匿名用户 2010-03-14 12:08发表 [回复]
[e01]
13楼  匿名用户 2010-02-08 17:01发表 [回复]
niu
12楼  rhddx007 2009-06-29 14:32发表 [回复]
楼主真是太有才啦!那个简单的源代码就看得俺直头大!其实什么隐含数对,三链数、四链数等等,偶也看不太明白,看来逻辑学还是要重新学习才是。暴汗~~
11楼  copooo 2009-04-19 23:25发表 [回复]
mathe兄弟好牛X,能否发一下源程序,让俺也学习学习吧?
10楼  jackyboy 2009-02-23 23:00发表 [回复]
数学研发论坛 提示信息

对不起,本站规定会员每小时最多只能发表 5 个帖子。

mathe 发表于2009-02-04 10:18:59 IP: 192.55.44.*
找到了一个1.13版本的源代码(挺旧的一个版本了,不过更新版本的我就找不到了),放在了:
http://bbs.emath.ac.cn/thread-13-1-1.html
9楼  jackyboy 2009-02-23 17:15发表 [回复]
还要注册论坛,然后半小时后才能发帖,真要从那个URL下载,很不容易哦。
8楼  mathe 2009-02-04 10:18发表 [回复]
找到了一个1.13版本的源代码(挺旧的一个版本了,不过更新版本的我就找不到了),放在了:
http://bbs.emath.ac.cn/thread-13-1-1.html
7楼  jackyboy 2009-01-11 21:34发表 [回复]
安装后的帮助文档index.htm里有一些错别字,比如:

专家级:使用了4中除关连数删减法外提供的方法能够找到结果,但是仅仅用高级的方法 海 不够的。
6楼  mathe 2008-05-09 13:00发表 [回复]
发现这个版本也有BUG,在非候选数模式下,本来应该可以用键盘输入的,不知道为什么,不能够用键盘输入了。所以就没法在非候选数模式下面玩了。不过由于我丢失源码,所以这个BUG也没办法修正了。也许大家可以从csdn下载中心中找到一些旧一些的版本,应该有可以支持非候选数模式的版本。

另外程序中有几个隐含功能,现在也公开一下:
i)选择游戏功能:对于机器随机产生的数独初试局面,我们可以看到在游戏标题上会显示一个长长的16进制数字串,这个数字串是这个初试局面的一个标识符。可以通过按Ctrl+Alt+Shift+S键来输入初试局面标识符来选择游戏局面。
ii)如上面说明,通过Ctrl+U可以将当前数独局面的计算机模拟手工解答的过程以文本方式复制到剪切板中;而我们还可以选择Ctrl+Alt+Shift+U将模拟解答过程以另外一种方式复制出来。
5楼  oc 2008-04-11 11:07发表 [回复]
有手工输入真不错,提个问题:当手工输入遇到解不惟一时不能结束输入怎么半?
Re:  mathe 2008-04-13 15:15发表 [回复]
没有好的方法。可以放弃或者尝试继续输入一些数据。<br />如果选择继续输入,为了避免输入过程产生一些无解的局面,最好打开候选数模式,然后可以使用游戏的帮组功能(比如连续按H键),让计算机先填充那些能够推理出来的格子(这些不会作为初试局面的一部分),知道计算机无法推理的时候,在手工尝试输入一个数据,然后继续让计算机填充。直到最后得到矛盾或得到有解的局面。然后可以用重新开始游戏功能得到游戏的开始局面。
4楼  ddlmz 2008-02-20 13:43发表 [回复]
原来是这样~这个tricky很有才~呵呵~我没有想到~
我的数据结构是用二进制表示状态,那么一个integer就可以存下来某个格子的候选数字和这些数字的个数。接下来就是一连串的位操作。不知这个和楼主“采用了大量的比特位运算”是否一样。
由于比赛的所鼓励的创新精神,我没有选用“挖格子”的方法。虽然知道这种方法可行,而且效果不错(正如楼主所做出来的结果)。相反采用了一个一个“填格子”的方法,但是结果就会使得最后需要29个数字左右生成棋盘,也许这就是这两个方法在结果上面的不同之处吧。同意楼主的观点,程序运行的时间其实跟自己对于难度的定义有关。如果某个难度范围的棋盘产生的几率较小,那么自然需要运行很长时间。
3楼  ddlmz 2008-02-19 21:18发表 [回复]
刚参加完MCM,最终做出的生成器还是没有楼主的那么好。如果要生成较高难度的局面,需要很长的时间。还有一点就是,我发现无论什么难度,楼主的局面永远都是在25个初始数字左右徘徊,我只能做到都在29个左右。个人认为,而如果初始数字过多,局面会缺乏美感。在这方面楼主有什么诀窍吗?多谢指教。
Re:  mathe 2008-02-20 09:54发表 [回复]
至于速度问题,我觉得有时候可能是数据结构选择不当,局部算法不够优化等原因都有可能引起。<br />我的博客里面还有一个产生数独的源程序,这里的'MCM'说他阅读过的(不过很难读懂:) ),我没有测试过这个程序的具体速度如何,你可以运行一下比较比较看看。<br />无限数独里面使用的是另外的数据结构,采用了大量的比特位运算,从这个角度来看,速度要快很多。但是无限数独程序用C++写的,对于搜索过程用到的递归过程优化没有那个程序做到好,这方面反而可能慢一些。但是到底那个程序更优,我没有比较过。<br />还有需要说明,我的程序里面产生速度最慢的是"专家"难度的游戏而不是“骨灰”级的,这个同游戏分布的概率有关,也同使用方法有关系。<br />实际上根据我的经验,要快速产生游戏,除了使用唯一法和隐含唯一法以外,其他逻辑法都没有必要采用,不然只会降低速度。但是现在"专家"级一下的游戏都是通过“逻辑”法筛选产生的,所以速度反而可能没有骨灰级的高。其实我的游戏里面“专家”级游戏产生速度没有做到实时,由于开发时间不长,我使用了一个Tricky, 对每个级别的游戏都缓存了20个事先搜索好的游戏。由于用户在玩游戏过程中会有很多空闲时间,所以在空闲中,程序会继续搜索游戏替换这20个缓存的游戏。<br />此外还有说明的是,我写这个软件的时候,很多时候只是自己想做一个测试(比如我做了很多古怪的功能,如果安装了MAPI就可以使用TTS和语音识别功能),而不是为了写出最优的程序,所以可以改进的地方非常多。甚至我还想过添加一个模式识别模块,从而用户可以将网络上图形模式的数独游戏直接复制到游戏中。而关于搜索速度,有很多可以改善的方法我都没有试验过,一个就是我说的改善递归过程;其次还有很多部分代码,明明可以提高速度的地方,但是为了开发速度,我直接调用了一些效率差很多(特别是递归过程)但是现成的代码;第三个是我的博客中有一个搜索数独终局总数的代码,用类似的算法也可以设计一个判断局面是否为唯一解的方法(考虑到数独初局至少会含17个数),应该可以设计一个只包含64比特整数位运算的搜索算法,但是我还没有时间测试过,只是一种想法而已。<br />而这一切的一切都在我丢掉源代码以后停止了(现在我手里还有一个非常就版本的源代码,但是功能差很多),实际上另外一个原因就是现在开发的兴趣也降低了很多。毕竟写这样一个程序还是要花费很多业余时间的。
Re:  mathe 2008-02-20 09:35发表 [回复]
我的程序是从终局开始搜索的,给定终局,然后尝试按随机顺序去除一些数字(如果去除一个数字导致多解,把这个数字放回)。<br />通过这种方法,肯定能够去掉尽量多的数字。至于美观问题,这个可以在找到一个初局以后,通过交换行列宫格来重新安排位置,这样就能够去除因为搜索顺序引起的美观被破坏问题。
2楼  mathe 2007-12-20 11:57发表 [回复]
BAD NEWS:
I lost the source code in machine rebuilt.
So 2.41 will be the last version. (Unless sometimes later to rewrite the code. )
1楼  blueraymond 2007-11-21 16:45发表 [回复] [引用] [举报]
发现2.41一个BUG,随机产生题,在乱填2个数,然后按着Ctrl+H一直提示下去,最后剩下几个数无法提示下去,此时按“显示结果”无法显示答案!按“重新开始”之后也无法点击候选数了。
Re:  mathe 2007-11-24 11:13发表 [回复]
最后没有提示不是BUG,而是因为无法提供提示了,你可以看一下状态条显示的提示信息。<br />由于计算机提供的是逻辑推导提示,到了某些状态可能无法提供逻辑推导提示的,比如:<br /> i)前面某些步骤用户填错了,所以到了一个本身无解的局面,计算机无法提供任何提示帮助了(这时可以按Shift+Z撤销用户的错误操作)<br /> ii)对于少数特殊局面(肯定是鬼灰级的),没有逻辑方法可用,所以计算机也无法提供提示,这时,可以使用尝试功能解决(比如按住Shift键然后选择一个候选数),使用尝试后,如果又遇到无解局面(说明尝试错误),这时可以按住Shift键,用鼠标右键点击上次尝试过的格子,可以取消尝试过程。<br />至于你说的按“显示结果”无法显示答案,按"重新开始"后无法点击候选数,我没有遇到这种情况,也无法重现这个问题。不知道是否你无意中进入了“历史浏览”状态,如果这样,按ESC键可以推出“历史浏览”状态。<br />还有,如果以后遇上BUG,最好能够把游戏的标题记录下来(或者将游戏局面记录下来),这样我有可能可以重现问题。
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值