数独完全解生成-分组轮转算法

数独(日语:数独すうどく)是一种源自18世纪末的瑞士,后在美国发展、并在日本得以发扬光大的数学智力拼图游戏。拼图是九宫格(即3格宽×3格高)的正方形状,每一格又细分为一个九宫格。在每一个小九宫格中,分别填上1至9的数字,让整个大九宫格每一列、每一行的数字都不重复。数独的玩法逻辑简单,数字排列方式千变万化。不少教育者认为数独是锻炼脑筋的好方法。

在数独出现之前,最流行的游戏有:魔方(Rubik'scubes)、俄罗斯方块(Tetris),甚至是超级玛丽(Mario)。但是这些都是风靡一时但又转瞬即逝的游戏。数独游戏的渊源比较久远,数独是一种源自18世纪末的瑞士,后在美国发展并在日本得以发扬光大的数学智力拼图游戏。

早在数千年前,中国人就发明了九宫图:在9个方格中,横行和竖行的数字总和是相同的。“数独”也不是什么新生事物,已经存在了数百年。18世纪,瑞士数学家莱昂哈德·欧勒发明了“拉丁方块”,但并没有受到人们的重视。直到20世纪70年代,美国杂志才以“数字拼图”的名称将它重新推出。日本随后接受并推广了这种游戏,并且将它改名为“数独”,大致的意思是“独个的数字”或“只出现一次的数字”。

现今流行的数独于1984年由日本游戏杂志《パズル通信ニコリ》发表并得了现时的名称。数独本是“独立的数字”的省略,因为每一个方格都填上一个非零的个位数。数独冲出日本成为英国当下的流行游戏,得归功于曾任香港高等法院法官的高乐德(Wayne Gould)。2004年,他在日本旅行的时候,发现杂志上介绍的这款游戏,便带回伦敦向《泰晤士报》推介并获得接纳。英国《每日邮报》也于三日后开始连载,使数独在英国正式掀起热潮。数独不仅是报章增加销量的法宝,脑筋动得快的《泰晤士报》还做起手机族的生意,花4.5英镑就能下载10则数独游戏到手机上玩。渐渐,其他国家和地区受其影响也开始风靡数独。

同类似的填字游戏不同,数独受欢迎的原因之一是它既不需要丰富的百科知识,也不要掌握大量的词汇,这使其能迅速为孩子和初学者所接受。根据游戏开始时的方格中已有的数字和位置,数独难易程度不同,有些复杂的甚至令数学家也不能完成。据著名的动游戏开发商Astraware Ltd.预计,移动数独游戏的版本多达几十种,Palm和Windows Mobile设备版本的数独游戏就各有20种左右。Sudokumo推出的移动数独游戏,能够下载到大多数手机中。这家位于英国的游戏软件公司表示,已经在全球卖出了7500套数独游戏,而且来自用户的兴趣还在增加。

数独游戏的界面如下图所示,其中红色线框圈起的部分为游戏区域,我们可以看到如图在游戏区域部分是由九个九宫格组成,如图所示。

数独完全解生成-分组轮转算法_第1张图片
数独完全解生成-分组轮转算法_第2张图片

这样整个游戏区域也就是九九八十一个单元格,我们要做的就是在1-9中选取一个数填入某单元格,而使得在横行、竖行以及该单元格所在的九宫格没有与之重复的数字。如图所示:当我们选中M格时,那么在M中填入的数字需要与R横行,C竖行以及G九宫格里面的数字不重复。

数独完全解生成-分组轮转算法_第3张图片

我们说到的分组轮转题面生成算法即是首先生成一个满格的满足数独要求的数字序列,然后通各种变换如旋转、换行等操作,再经过“挖洞”(挖去已有数独题面上面的数字),然后通过验证唯一性等方法来生成一个数独的游戏题面。

数独完全解生成-分组轮转算法_第4张图片

如图所示我们先将单元格进行扩展,如上图所示也就是在游戏区域的左侧添加上六列单元格。然后使用分组轮转算法来实现题面的快速生成。首先我们使用随机数来对1-9九个数字进行分组,九个数分成三组,每组3个数。我们分组时采用随机数从1-9中取出3个数作为第一组,然后取第二组的3个数,最后留下的3个数作为第三组。分组完成后,就可以开始进行轮转变换来产生81个数字序列。如上图所示,我们将产生的三组数分别填入数独矩阵的第一行中。如图我们对不同组的数字进行了颜色区分标记,相同颜色的为同一组数列。然后开始进行轮转,也就是将数独矩阵的第一行的数字序列向左移动一组(即3个单元格)的距离,把移动的结果填入到数独矩阵的第二行,这样我们在上图可以看到之前在第一行的第一组数据已经移到了游戏区的外面,进入到我们的扩展空间,而我们移动后填入第二行的数据的后面空出了一组的数据空间,这时我们将移出去的那一组填入到第二行后面空出的那一组中。就这样第二行数据产生完成,我们仔细看看数独矩阵第一行、第二行的数据,发现并没有违反数独游戏的规则。然后继续轮转,即把数独矩阵的二行数字序列向左移动一组(3个单元格)的距离,使用同样的方法,那么我们将移出的部分数列组添加到空出的空间。可见经过三次轮转,我们很快就产生了整个游戏三分之一的数据,即如图数独矩阵中A、B、C三行的数据。

在接下来的过程中,我们将之前分组得到的各个分组的三个数字进行轮转。在通过随机数分组完成后,如上图例,我们分别得到了第一次的分组数据,第一组:2、4、5,第二组:6、1、7,第三组:9、3、8这三组的数据。现在我们分别对这三组数据中的数字进行轮转,也就产生了第二次的分组数据:第一组:4、5、2,第二组:1、7、6,第三组:3、8、9。这时我们对第二次得到的分组数据,使用上述的分组轮转方法,即可得到数独矩阵中D、E、F三行的数据。最后再对第二次的分组数据进行轮转,就得到了第三次的分组数据,第一组:5、2、4,第二组:7、6、1,第三组:8、9、3。然后同理,再对这三组数据进行分组轮转,就可得到数独矩阵中G、H、I三行的数据。经过上述步骤一步步实现,我们最后产生了一组满足数独游戏规则的数字序列。由于算法使用了随机数进行分组,这样每次产生的数独游戏题面基本都会不一样,通过分组轮转算法在理论上可以产生的数独游戏体面个数为:362880个,这是最基本的个数,我们如果再对产生的基本题面进行各种变换,那么游戏题面的个数又会进一步翻倍。如图所示为一种题面产生结果:

数独完全解生成-分组轮转算法_第5张图片

对于使用该方法优点在于可以在几到几十毫秒内产生一组数独题面数据,其运行效率和时间相较于回溯法要高出很多,分组轮转产生题面的时间短,占用的空间少。但是这种方法同样有它不足的地方,首先它产生的数独题面数量只有36万左右还只是一小部分,没有回溯方法产生的多。也就是它产生的数据如果我们仔细观察,会发现这些数据有一定的规律性,回溯产生的话,题面的随机性要好很多。如果我们就只通过轮转算法来产生一组数据的话,然后不对数据做任何操作,直接开始进行挖洞来产生数独的游戏题面,这样其实产生的题面质量不怎么高,你会发现资深或是有过数独经验的玩家可以很快找到其中的规律,这样他们基本不用考虑很久就可以解开整个游戏题面,不过这种题面对于初级或是小白类的玩家还是可以忽悠一段时间的。所以我们要产生高质量的的题面,那必须提高数据的随机性,即题面不能展现出太强的规律性。为了避免这些问题,在经过分组轮转产生题面数据后,我们要对题面数据进行一定变换操作,以此来削弱整个题面的规律性,从而产生更高质量的数独题面。

本次算法介绍到此结束,具体的代码实现我在此就不献丑贴出来了,大家可以根据算法描述自己去尝试实现一下。有问题可以给我留言。有兴趣的朋友可以继续探究这个问题,后续问题我们再讨论!

你可能感兴趣的:(数独完全解生成-分组轮转算法)