数独的规则

1、数字 1-9 在每一行只能出现一次。

2、数字 1-9 在每一列只能出现一次。

3、数字 1-9 在每一个 3x3 宫内只能出现一次。3x3 的宫内为A1-C3,A4-C6,A7-C9,D1-F3,D4-F6,D7-F9…

数独题目示例

大致思路

1、数独我们使用一个二维列表存储,没有值的位置我们使用’'空字符窜占位。(二维数组)

2、得到每一个3*3的宫内,每一行,每一列已有的数据,然后存放起来。3、得到所有的空缺位置,再遍历空缺位置,尝试放置数据,然后进行判断,如果满足条件安继续放置下一个。以此类推,在途中有不满足条件的情况,就进行回溯,返回上一次满足条件的情况,在进行另一次尝试。

演示环境

  • 操作系统:windows10
  • python版本:python 3.7
  • 代码编辑器:pycharm 2018.2

具体代码

1、首选我们创建一个类SudoKu。编写构造函数。

学习python中有什么不懂的地方,小编这里推荐加小编的python学习群:895 817 687
有任何不懂的都可以在里面交流,还有很好的视频教程pdf学习资料,大家一起学习交流!class SudoKu():def __init__(self,sudo_ku_data):# 判断传入的数独是否满足格式if not isinstance(sudo_ku_data,list):raise TypeError(f'sudo_ku_data params must a list, but {sudo_ku_data} is a {type(sudo_ku_data)}')if len(sudo_ku_data) != 9 or len(sudo_ku_data[0]) != 9:raise TypeError(f'sudo_ku_data params must a 9*9 list, but {sudo_ku_data} is a {len(sudo_ku_data)}*{len(sudo_ku_data[0])} list')self.sudo_ku = sudo_ku_data# 存放每一行已有的数据self.every_row_data = {}# 每一列已有的数字self.every_column_data = {}# 每一个3*3宫内有的数字self.every_three_to_three_data = {}# 每一个空缺的位置self.vacant_position = []# 每一个空缺位置尝试了的数字self.every_vacant_position_tried_values = {}

2、编写添加每一行,每一列,每一宫方法,方便我们后面调用

def _add_row_data(self,row,value):'''添加数据到self.every_row_data中,即对每一行已有的数据进行添加:param row::param value::return:'''# 如果当前行不存在,就以当前行为key,初始化值为set()(空的集合)if row not in self.every_row_data:self.every_row_data[row] = set()# 如果这个值已经出现过在这一行了,说明传入的不是一个正确的数独if value in self.every_row_data[row]:raise TypeError(f'params {self.sudo_ku} is a invalid SudoKu')self.every_row_data[row].add(value)def _add_column_data(self,column,value):'''添加数据到self.every_column_data中,上面的函数思路一样:param column::param value::return:'''if column not in self.every_column_data:self.every_column_data[column] = set()if value in self.every_column_data[column]:raise TypeError(f'params {self.sudo_ku} is a invalid SudoKu')self.every_column_data[column].add(value)def _get_three_to_three_key(self,row,column):'''得到该位置在哪一个3*3的宫内:param row::param column::return:'''if row in [0,1,2]:if column in [0,1,2]:key = 1elif column in [3,4,5]:key = 2else:key = 3elif row in [3,4,5]:if column in [0,1,2]:key = 4elif column in [3,4,5]:key = 5else:key = 6else:if column in [0,1,2]:key = 7elif column in [3,4,5]:key = 8else:key = 9return keydef _add_three_to_three_data(self,row,column,value):'''添加数据到self.every_three_to_three_data中:param row::param column::param value::return:'''# 首先得到在哪一个3*3的宫内key = self._get_three_to_three_key(row,column)# 然后也和上面添加行,列的思路一样if key not in self.every_three_to_three_data:self.every_three_to_three_data[key] = set()if value in self.every_three_to_three_data[key]:raise TypeError(f'params {self.sudo_ku} is a invalid SudoKu')self.every_three_to_three_data[key].add(value)

3、遍历数独,对每种数据进行初始化

def _init(self):'''根据传入的数独,初始化数据:return:'''for row,row_datas in enumerate(self.sudo_ku):for column,value in enumerate(row_datas):if value == '':# 添加空缺位置self.vacant_position.append( (row,column) )else:# 添加行数据self._add_row_data(row,value)# 添加列数据self._add_column_data(column,value)# 添加宫数据self._add_three_to_three_data(row,column,value)

4、编写判断某一个位置的值是否合法的函数

def _judge_value_is_legal(self,row,column,value):'''判断方放置的数据是否合法:param row::param column::param value::return:'''# value是否存在这一行数据中if value in self.every_row_data[row]:return False# value是否存在这一列数据中if value in self.every_column_data[column]:return False# value是否存在这个3*3的宫内key = self._get_three_to_three_key(row,column)if value in self.every_three_to_three_data[key]:return Falsereturn True

5、编写计算的函数,在当前位置循环 可以使用的额数据,确定可以是否可以放置这个值

def _calculate(self, vacant_position):'''计算,开始对数独进行放置值:param vacant_position::return:'''# 得到当前位置row,column = vacant_positionvalues = set(range(1,10))# 对当前为位置创建一个唯一key,用来存放当前位置已经尝试了的数据key = str(row) + str(column)# 如果这个key存在,就对values进行取差集,因为两个都是集合(set),直接使用-就行了if key in self.every_vacant_position_tried_values:values = values - self.every_vacant_position_tried_values[key]# 如果这个key不存在,就创建一个空的集合else:self.every_vacant_position_tried_values[key] = set()for value in values:# 对当前数据添加到当前位置尝试过的的数据中self.every_vacant_position_tried_values[key].add(value)# 如果当前value合法,可以放置if self._judge_value_is_legal(row,column,value):print(f'set {vacant_position} value is {value}')# 更新 判断数据合法时 需要使用到的数据self.every_column_data[column].add(value)self.every_row_data[row].add(value)key = self._get_three_to_three_key(row,column)self.every_three_to_three_data[key].add(value)# 修改这个位置的值为valueself.sudo_ku[row][column] = value# 返回True 和填充的 valuereturn True,valuereturn False,None

6、如果当前位置没有任何一个值可以放置,那么就回溯,返回上一次成功的位置,重新取值,所以我们编写一个回溯函数

def _backtrack(self,current_vacant_position,previous_vacant_position,previous_value):'''回溯:param current_vacant_position: 当前尝试失败的位置:param previous_vacant_position: 上一次成功的位置:param previous_value:上一次成功的值:return:'''print(f"run backtracking... value is {previous_value},vacant position is {previous_vacant_position}")row,column = previous_vacant_position# 对上一次成功的值从需要用到的判断的数据中移除self.every_column_data[column].remove(previous_value)self.every_row_data[row].remove(previous_value)key = self._get_three_to_three_key(row,column)self.every_three_to_three_data[key].remove(previous_value)# 并且上一次改变的的值变回去self.sudo_ku[row][column] = ''# 对当前尝试失败的位置已经城市失败的的值进行删除,因为回溯了,所以下一次进来需要重新判断值current_row,current_column = current_vacant_positionkey = str(current_row) + str(current_column)self.every_vacant_position_tried_values.pop(key)

7、到这里为止,我们所有的功能函数都写完了,然后我们编写一个函数,开始循环所有的空缺位置。然后进行计算。

def get_result(self):'''得到计算之后的数独:return:'''# 首先初始化一下数据self._init()# 空缺位置的长度length = len(self.vacant_position)# 空缺位置的下标index = 0# 存放已经尝试了的数据tried_values = []# 如果index小于length,说明还没有计算完while index < length:# 得到一个空缺位置vacant_position = self.vacant_position[index]# 计入计算函数,返回是否成功,如果成功,value为成功 的值,如果失败,value为Noneis_success,value = self._calculate(vacant_position)# 如果成功,将value放在tried_values列表里面,因为列表是有序的.# index+1 对下一个位置进行尝试if is_success:tried_values.append(value)index += 1# 失败,进行回溯,并且index-1,返回上一次的空缺位置,我们需要传入当前失败的位置 和 上一次成功的位置和值else:self._backtrack(vacant_position,self.vacant_position[index-1],tried_values.pop())index -= 1# 如果index<0 了 说明这个数独是无效的if index < 0:raise ValueError(f'{self.sudo_ku} is a invalid sudo ku')# 返回计算之后的数独return self.sudo_ku

效果展示
呼。。。终于干完代码,接下来我们呢可以"开始收获"了

if __name__ == '__main__':sudo_ku_data = [[5,3,'','',7,'','','',''],[6,'','',1,9,5,'','',''],['',9,8,'','','','',6,''],[8,'','','',6,'','','',3],[4,'','',8,'',3,'','',1],[7,'','','',2,'','','',6],['',6,'','','','',2,8,''],['','','',4,1,9,'','',5],['','','','',8,'','',7,9],]# 得到计算好的数独sudo_ku = SudoKu(sudo_ku_data).get_result()print(sudo_ku)################
#   结果显示    #
################
[5, 3, 4, 6, 7, 8, 9, 1, 2]
[6, 7, 2, 1, 9, 5, 3, 4, 8]
[1, 9, 8, 3, 4, 2, 5, 6, 7]
[8, 5, 9, 7, 6, 1, 4, 2, 3]
[4, 2, 6, 8, 5, 3, 7, 9, 1]
[7, 1, 3, 9, 2, 4, 8, 5, 6]
[9, 6, 1, 5, 3, 7, 2, 8, 4]
[2, 8, 7, 4, 1, 9, 6, 3, 5]
[3, 4, 5, 2, 8, 6, 1, 7, 9]

这效果就很完美啊,我们在来测试一个比较难得数独。

输入数独为:

[[8, '', '', '', '', '', '', '', 4],['', 2, '', '', '', '', '', 7, ''],['', '', 9, 1, '', 6, 5, '', ''],['', '', 6, 2, '', 8, 9, '', ''],['', 9, '', '', 3, '', '', 4, ''],['', '', 2, 4, '', 7, 8, '', ''],['', '', 7, 9, '', 5, 6, '', ''],['', 8, '', '', '', '', '', 2, ''],[6, '', '', '', '', '', '', '', 9],
]################
#   结果显示    #
################
[8, 6, 1, 5, 7, 2, 3, 9, 4]
[5, 2, 4, 3, 8, 9, 1, 7, 6]
[3, 7, 9, 1, 4, 6, 5, 8, 2]
[4, 3, 6, 2, 5, 8, 9, 1, 7]
[7, 9, 8, 6, 3, 1, 2, 4, 5]
[1, 5, 2, 4, 9, 7, 8, 6, 3]
[2, 4, 7, 9, 1, 5, 6, 3, 8]
[9, 8, 5, 7, 6, 3, 4, 2, 1]
[6, 1, 3, 8, 2, 4, 7, 5, 9]

Python果然不得了,数独都能轻松解决?python秒解数独了解下?相关推荐

  1. python高效开发实战配套源文件_分享12个python使用技巧,助你轻松掌握Python高效开发...

    前言: 欢迎大家收看分享12个python使用技巧,助你轻松掌握Python高效开发!部分代码用图片的方式呈现出来,方便各位观看与收藏,要是喜欢的话,记得一定不要忘记点赞关注嗷! 内容如下: 1. 隐 ...

  2. 480集课程-打通Python开发的任督二脉 轻松掌握Python高级开发技术 Python超级学科课程

    480集课程-打通Python开发的任督二脉 轻松掌握Python高级开发技术 Python超级学科课程 ===============课程目录=============== ├─(1) 01-Pyt ...

  3. Python实现秒解数独

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

  4. python解析xml提交到hdfs_完美解决python针对hdfs上传和下载的问题

    当我们使用python的hdfs包进行上传和下载文件的时候,总会出现如下问题 requests.packages.urllib3.exceptions.NewConnectionError:: Fai ...

  5. python画图y轴在右侧_解决python中画图时x,y轴名称出现中文乱码的问题

    如下所示: #-*- coding:utf-8 -*- import numpy as np import matplotlib.pyplot as plt from matplotlib.font_ ...

  6. python数独游戏源代码100行_python实现解数独程序代码

    偶然发现linux系统附带的一个数独游戏,打开玩了几把.无奈是个数独菜鸟,以前没玩过,根本就走不出几步就一团浆糊了. 于是就打算借助计算机的强大运算力来暴力解数独,还是很有乐趣的. 下面就记录一下我写 ...

  7. python中文显示不出来_彻底解决Python里matplotlib不显示中文的问题

    在很长一段时间里用Python绘图,matplotlib都不能很好的显示中文,起初是认为我的pycharm里的设置问题,但是发现同样的问题在spyder里也同样的出现了,虽然有的地方可以用英文实在不行 ...

  8. python语言命名规则-一文轻松掌握python语言命名规范规则

    和C/C++.Java等语言一样,python在命名上也有一套约定俗成的规则,符合规范的命名可以让程序的可读性大大增加,从而使得代码的逻辑性增强,易于自己和其他协作者在以后的拓展中理解代码的意义,从而 ...

  9. python自然对数为底的指数函数_解决python中的幂函数、指数函数问题

    最近在调代码,碰到幂函数.指数函数,总是提示 ValueError: math domain error ValueError: negative number cannot be raised to ...

最新文章

  1. 荣发护肤护甲增强配方 Hair, Skin and Nails Plus 100 tablets
  2. troubleshoot之:分析OutOfMemoryError异常
  3. 苹果发布iOS 13.2测试版 iPhone 11拍照更牛了
  4. c 程序设计语言西电科大,西安电子科技大学
  5. exchange2003 SMTP连接器的应用案例
  6. Shell:运算命令和操作符
  7. dw向右滚动字幕HTML,[转载]DW添加滚动字幕[转]
  8. Windows 下使用 Mingw32-make 来执行 Makefile示例
  9. java类加载机制之类加载过程、类加载器及双亲委派模型详解
  10. 如何在阿里云注册域名-阿里云域名注册与域名解析完整教程
  11. npm install 报错 npm ERR! errno ETIMEDOUT
  12. vue图片连拼实现gif图效果
  13. php的implode函数的作用是,PHP函数implode介绍
  14. 装修后才知道的79件事
  15. syslinux 启动后显示SYSLINUX 5.01H. Peter Anvin et al
  16. ZJOI2018游记Round2
  17. tableau货架图制作_Tableau代写制作地图可视化和树形图、条形图
  18. raspberry pi到手,折腾成web服务器,加小小鄙视下网通
  19. GPS警用车辆3G视频监控系统方案
  20. ESD镜像文件转换成ISO镜像文件解决方案

热门文章

  1. lombok中的@Data注解与MyBatis的懒加载机制冲突解决
  2. Tomcat9URL不支持特殊字符解决方案
  3. input输入框自动消除空格
  4. python实验七答案_Python实验报告七
  5. pip——【Fatal error in launcher: Unable to create process using 】解决方案
  6. Vuex——命名空间导致错误[unknown action type:XXX]解决方案
  7. Maven——Maven概述
  8. 线性代数 matlab,实用大众线性代数(MATLAB版)
  9. JSP、EL和JSTL-学习笔记04【JSTL常用标签】
  10. vue中v-model原理