python实现解数独程序代码


Posted in Python onApril 12, 2017

偶然发现linux系统附带的一个数独游戏,打开玩了几把。无奈是个数独菜鸟,以前没玩过,根本就走不出几步就一团浆糊了。

于是就打算借助计算机的强大运算力来暴力解数独,还是很有乐趣的。

下面就记录一下我写解数独程序的一些思路和心得。

一.数独游戏的基本解决方法

编程笼统的来说,就是个方法论。不论什么程序,都必须将问题的解决过程分解成计算机可以实现的若干个简单方法。俗话说,大道至简。对于只能明白0和1的计算机来说,就更需要细分步骤,一步一步的解决问题了。

首先来思考一下解数独的基本概念。

数独横九竖九共八十一个格子,同时又分为9个九宫格。规则很简单——需要每一个格中的数字,都保证与其所在横排和竖排以及九宫格内无相同数字。

所以我们的大概思路就是,从第一个空格开始试着填数,从 1 开始填,如果 1 不满足横排竖排九宫格无重复的话,就再填入 2 ,以此类推,直到填入一个暂时满足规则的数,中断此格,移动到下一个空格重复这个过程。

如果到达某个空格发现已经无数可选了,说明前面某一格填错了,那就返回上一格,从上一格的中断处继续往 9 尝试,直到这样回朔到填错的那一格。

这样的话,我们就可以整理出重要的步骤了:

•寻找到下一个空格
•轮流填入格中数字 1 到 9
•递归判断填入数是否符合规则

二.程序

首先测试数独使用的是芬兰数学家因卡拉花费3个月时间设计出的世界上迄今难度最大的数独。如下

python实现解数独程序代码

将空格用 0 表示,同时将数独表示成嵌套的列表,这样每格的行数和列数就正好是列表中每个对应数的索引。

程序如下:

#coding=utf-8
 import datetime
 class solution(object):
   def __init__(self,board):
     self.b = board
     self.t = 0
 
   def check(self,x,y,value):#检查每行每列及每宫是否有相同项
     for row_item in self.b[x]:
       if row_item == value:
         return False
     for row_all in self.b:
       if row_all[y] == value:
         return False
     row,col=x/3*3,y/3*3
     row3col3=self.b[row][col:col+3]+self.b[row+1][col:col+3]+self.b[row+2][col:col+3]
     for row3col3_item in row3col3:
       if row3col3_item == value:
         return False
     return True
 
   def get_next(self,x,y):#得到下一个未填项
     for next_soulu in range(y+1,9):
       if self.b[x][next_soulu] == 0:
         return x,next_soulu
     for row_n in range(x+1,9):
       for col_n in range(0,9):
         if self.b[row_n][col_n] == 0:
           return row_n,col_n
     return -1,-1 #若无下一个未填项,返回-1
 
   def try_it(self,x,y):#主循环
     if self.b[x][y] == 0:
       for i in range(1,10):#从1到9尝试
         self.t+=1
         if self.check(x,y,i):#符合 行列宫均无条件 的
           self.b[x][y]=i #将符合条件的填入0格
           next_x,next_y=self.get_next(x,y)#得到下一个0格
           if next_x == -1: #如果无下一个0格
             return True #返回True
           else:    #如果有下一个0格,递归判断下一个0格直到填满数独
             end=self.try_it(next_x,next_y)
             if not end:  #在递归过程中存在不符合条件的,即 使try_it函数返回None的项
               self.b[x][y] = 0  #回朔到上一层继续
             else:
               return True
 
   def start(self):
     begin = datetime.datetime.now()
     if self.b[0][0] == 0:
       self.try_it(0,0)
     else:
       x,y=self.get_next(0,0)
       self.try_it(x,y)
     for i in self.b:
       print i
     end = datetime.datetime.now()
     print '\ncost time:', end - begin
     print 'times:',self.t
     return
 
 
 s=solution([[8,0,0,0,0,0,0,0,0],
     [0,0,3,6,0,0,0,0,0],
     [0,7,0,0,9,0,2,0,0],
     [0,5,0,0,0,7,0,0,0],
     [0,0,0,8,4,5,7,0,0],
     [0,0,0,1,0,0,0,3,0],
     [0,0,1,0,0,0,0,6,8],
     [0,0,8,5,0,0,0,1,0],
     [0,9,0,0,0,0,4,0,0]])
 73 s.start()

值得注意的是使用的递归判断能够很巧妙的在走错分支时回朔到上一层。具体实现是通过 for 循环来从 1 到 9 不断填入数字同时达到记录中断点的作用。通过下一层的返回值来确定是否回朔。

程序输出如下:

[8, 1, 2, 7, 5, 3, 6, 4, 9]
[9, 4, 3, 6, 8, 2, 1, 7, 5]
[6, 7, 5, 4, 9, 1, 2, 8, 3]
[1, 5, 4, 2, 3, 7, 8, 9, 6]
[3, 6, 9, 8, 4, 5, 7, 2, 1]
[2, 8, 7, 1, 6, 9, 5, 3, 4]
[5, 2, 1, 9, 7, 4, 3, 6, 8]
[4, 3, 8, 5, 2, 6, 9, 1, 7]
[7, 9, 6, 3, 1, 8, 4, 5, 2]

cost time: 0:00:00.060687
times: 45360

可以看到程序虽然运算次数比较多,但是速度还是很快的。

Python 相关文章推荐
PHP魔术方法__ISSET、__UNSET使用实例
Nov 25 Python
Python爬虫爬取美剧网站的实现代码
Sep 03 Python
Python使用Tkinter实现机器人走迷宫
Jan 22 Python
Pyinstaller将py打包成exe的实例
Mar 31 Python
Python列表生成式与生成器操作示例
Aug 01 Python
python实现点击按钮修改数据的方法
Jul 17 Python
python-Web-flask-视图内容和模板知识点西宁街
Aug 23 Python
python多环境切换及pyenv使用过程详解
Sep 27 Python
将python安装信息加入注册表的示例
Nov 20 Python
Python Selenium参数配置方法解析
Jan 19 Python
Python要求O(n)复杂度求无序列表中第K的大元素实例
Apr 02 Python
python属于解释型语言么
Jun 15 Python
python访问抓取网页常用命令总结
Apr 11 #Python
Python 登录网站详解及实例
Apr 11 #Python
python实现FTP服务器服务的方法
Apr 11 #Python
python读写json文件的简单实现
Apr 11 #Python
Python实现Mysql数据库连接池实例详解
Apr 11 #Python
详解Python中类的定义与使用
Apr 11 #Python
python获取指定时间差的时间实例详解
Apr 11 #Python
You might like
php中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
2012/01/16 PHP
PHP的switch判断语句的“高级”用法详解
2014/10/01 PHP
php简单实现多维数组排序的方法
2016/09/30 PHP
PHP全功能无变形图片裁剪操作类与用法示例
2017/01/10 PHP
php基于dom实现读取图书xml格式数据的方法
2017/02/03 PHP
YII2框架中使用yii.js实现的post请求
2017/04/09 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
搜索附近的人PHP实现代码
2018/02/11 PHP
PHP学习记录之常用的魔术常量详解
2019/12/12 PHP
PHP常用字符串输出方法分析(echo,print,printf及sprintf)
2021/03/09 PHP
jquery ajax提交整个表单元素的快捷办法
2013/03/27 Javascript
关于query Javascript CSS Selector engine
2013/04/12 Javascript
Angularjs制作简单的路由功能demo
2015/04/14 Javascript
JS实现的简单轮播图运动效果示例
2016/12/22 Javascript
JavaScript中日常收集常见的10种错误(推荐)
2017/01/08 Javascript
node.js的事件机制
2017/02/08 Javascript
Koa2微信公众号开发之消息管理
2018/05/16 Javascript
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
vue组件开发props验证的实现
2019/02/12 Javascript
Vue.js自定义指令学习使用详解
2019/10/19 Javascript
Vue-CLI与Vuex使用方法实例分析
2020/01/06 Javascript
Ajax获取node服务器数据的完整步骤
2020/09/20 Javascript
python简单实现计算过期时间的方法
2015/06/09 Python
Python中shapefile转换geojson的示例
2019/01/03 Python
python中@property的作用和getter setter的解释
2020/12/22 Python
Python操作Excel的学习笔记
2021/02/18 Python
CSS3 选择器 属性选择器介绍
2012/01/21 HTML / CSS
中东奢侈品市场:Coveti
2019/05/12 全球购物
init进程的作用
2012/04/12 面试题
校园学雷锋活动月总结
2014/03/09 职场文书
反邪教标语
2014/06/23 职场文书
教育合作协议范本
2014/10/17 职场文书
MySQL 逻辑备份与恢复测试的相关总结
2021/05/14 MySQL
剑指Offer之Java算法习题精讲二叉树的构造和遍历
2022/03/21 Java/Android
Python采集爬取京东商品信息和评论并存入MySQL
2022/04/12 Python
Android中的Launch Mode详情
2022/06/05 Java/Android