用Python解数独的方法示例


Posted in Python onOctober 24, 2019

芬兰数学家因卡拉花费3个月时间设计出的世界上迄今难度最大的数独。数独是 9 横 9 竖共有 81 个格子,同时又分为 9 个九宫格。规则很简单:每个空格填入 1~9 任意一个数字,需要保证每个横排和竖排以及九宫格内无相同数字。

用Python解数独的方法示例

解数独是一个可有可无的爱好,知道这个益智游戏,但是不很上心。但是前两天,由于自己的学生装了一个 ubuntu 18.04 的系统,上面有一些数独游戏,偶然间,让我看见了,为了更好的显摆自己的 Python 知识,决定用 Python 写一个程序,所以就有了下面的文字。

1、将待解的数独转换成 Python 矩阵

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

就是这么简单,将待填写的空白格用 0 来代替。

2、寻找第一个空格位置

def start_pos(m:"数独矩阵"):
 """ 功能:返回第一个空白格的位置坐标"""
 for x in range(9):
  for y in range(9):
   if m[x][y] == 0:
    return x, y
 return False, False # 若数独已完成,则返回 False, False

找到 Python 矩阵中第一个是 0 的元素的位置坐标。

3、寻找下一个空格位置

def get_next(m:"数独矩阵", x:"空白格行数", y:"空白格列数"):
 """ 功能:获得下一个空白格在数独中的坐标。  
 """
 for next_y in range(y+1, 9): # 下一个空白格和当前格在一行的情况
  if m[x][next_y] == 0:
   return x, next_y
 for next_x in range(x+1, 9): # 下一个空白格和当前格不在一行的情况
  for next_y in range(0, 9):
   if m[next_x][next_y] == 0:
    return next_x, next_y
 return -1, -1    # 若不存在下一个空白格,则返回 -1,-1

找到 Python 矩阵中下一个是 0 的元素的位置坐标。详细内容看注释。

4、寻找适合当前空格的数字的集合

def value(m:"数独矩阵", x:"空白格行数", y:"空白格列数"):
 """ 功能:返回符合"每个横排和竖排以及
    九宫格内无相同数字"这个条件的有效值。
 """ 
 i, j = x//3, y//3
 grid = [m[i*3+r][j*3+c] for r in range(3) for c in range(3)]
 v = set([x for x in range(1,10)]) - set(grid) - set(m[x]) - \
  set(list(zip(*m))[y])
 return list(v)

每个空格可以填入 1~9 中的任意一个数字,但要符合规则:每个空格填入 1~9 任意一个数字,需要保证每个横排和竖排以及九宫格内无相同数字。下面的代码中的 grid 变量,保存的是当前位置所处的九宫格。v 变量是通过集合运算,将 1~9 这个数字集合中,与行的数字集合、列的数字集合以及九宫格的数字集合重叠的部分去除掉。剩余的部分就是符合条件的数字的集合。

5、使用递归尝试解数独(Sudoku)

def try_sudoku(m:"数独矩阵", x:"空白格行数", y:"空白格列数"):
 """ 功能:试着填写数独 """
 for v in value(m, x, y):
  m[x][y] = v
  next_x, next_y = get_next(m, x, y)
  if next_y == -1: # 如果无下一个空白格
   return True
  else:
   end = try_sudoku(m, next_x, next_y) # 递归
   if end: # 数独解完之后,此处的 end 会是 True
    return True
   m[x][y] = 0 # 在递归的过程中,如果数独没有解开,
      # 则回溯到上一个空白格

详细内容看注释。

6、代码展示

import random 
import sys 
sys.setrecursionlimit(100000) # 发现python默认的递归深度是很有限的
        #(默认是1000),因此当递归深度超过999的
        # 样子,就会引发这样的一个异常。


def get_next(m:"数独矩阵", x:"空白格行数", y:"空白格列数"):
 """ 功能:获得下一个空白格在数独中的坐标。  
 """
 for next_y in range(y+1, 9): # 下一个空白格和当前格在一行的情况
  if m[x][next_y] == 0:
   return x, next_y
 for next_x in range(x+1, 9): # 下一个空白格和当前格不在一行的情况
  for next_y in range(0, 9):
   if m[next_x][next_y] == 0:
    return next_x, next_y
 return -1, -1    # 若不存在下一个空白格,则返回 -1,-1
  
def value(m:"数独矩阵", x:"空白格行数", y:"空白格列数"):
 """ 功能:返回符合"每个横排和竖排以及
    九宫格内无相同数字"这个条件的有效值。
 """ 
 i, j = x//3, y//3
 grid = [m[i*3+r][j*3+c] for r in range(3) for c in range(3)]
 v = set([x for x in range(1,10)]) - set(grid) - set(m[x]) - \
  set(list(zip(*m))[y]) 
 return list(v)

def start_pos(m:"数独矩阵"):
 """ 功能:返回第一个空白格的位置坐标"""
 for x in range(9):
  for y in range(9):
   if m[x][y] == 0:
    return x, y
 return False, False # 若数独已完成,则返回 False, False

def try_sudoku(m:"数独矩阵", x:"空白格行数", y:"空白格列数"):
 """ 功能:试着填写数独 """
 for v in value(m, x, y):
  m[x][y] = v
  next_x, next_y = get_next(m, x, y)
  if next_y == -1: # 如果无下一个空白格
   return True
  else:
   end = try_sudoku(m, next_x, next_y) # 递归
   if end:
    return True
   m[x][y] = 0 # 在递归的过程中,如果数独没有解开,
      # 则回溯到上一个空白格

def sudoku(m):  
 x, y = start_pos(m)
 try_sudoku(m, x, y)
 print(m)  
 
  

     
if __name__ == "__main__":
 m = [
  [6, 0, 0, 1, 0, 0, 7, 0, 8],
  [0, 0, 0, 8, 0, 0, 2, 0, 0],
  [2, 3, 8, 0, 5, 0, 1, 0, 0],
  [0, 0, 0, 0, 4, 0, 0, 9, 2],
  [0, 0, 4, 3, 0, 8, 6, 0, 0],
  [3, 7, 0, 0, 1, 0, 0, 0, 0],
  [0, 0, 3, 0, 7, 0, 5, 2, 6],
  [0, 0, 2, 0, 0, 4, 0, 0, 0],
  [9, 0, 7, 0, 0, 6, 0, 0, 4]
 ]

 sudoku(m)
 
""" 数独结果如下:
[
 [6, 9, 5, 1, 2, 3, 7, 4, 8], 
 [7, 4, 1, 8, 6, 9, 2, 5, 3], 
 [2, 3, 8, 4, 5, 7, 1, 6, 9], 
 [8, 1, 6, 7, 4, 5, 3, 9, 2], 
 [5, 2, 4, 3, 9, 8, 6, 7, 1], 
 [3, 7, 9, 6, 1, 2, 4, 8, 5], 
 [4, 8, 3, 9, 7, 1, 5, 2, 6], 
 [1, 6, 2, 5, 8, 4, 9, 3, 7], 
 [9, 5, 7, 2, 3, 6, 8, 1, 4]
]
"""

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python3 正在毁灭 Python的原因分析
Nov 28 Python
Python中对列表排序实例
Jan 04 Python
使用C语言扩展Python程序的简单入门指引
Apr 14 Python
Python正则表达式实现截取成对括号的方法
Jan 06 Python
Python利用Beautiful Soup模块修改内容方法示例
Mar 27 Python
django rest framework之请求与响应(详解)
Nov 06 Python
Python实现的爬取百度文库功能示例
Feb 16 Python
python 并发编程 多路复用IO模型详解
Aug 20 Python
Tensorflow限制CPU个数实例
Feb 06 Python
使用Puppeteer爬取微信文章的实现
Feb 11 Python
Python序列化pickle模块使用详解
Mar 05 Python
分享python函数常见关键字
Apr 26 Python
Python3 sys.argv[ ]用法详解
Oct 24 #Python
window7下的python2.7版本和python3.5版本的opencv-python安装过程
Oct 24 #Python
原生python实现knn分类算法
Oct 24 #Python
python KNN算法实现鸢尾花数据集分类
Oct 24 #Python
python爬虫爬取幽默笑话网站
Oct 24 #Python
python栈的基本定义与使用方法示例【初始化、赋值、入栈、出栈等】
Oct 24 #Python
python 队列基本定义与使用方法【初始化、赋值、判断等】
Oct 24 #Python
You might like
PHP 字符串操作入门教程
2006/12/06 PHP
MySQL修改密码方法总结
2008/03/25 PHP
PHP7.0版本备注
2015/07/23 PHP
php文件操作之文件写入字符串、数组的方法分析
2019/04/15 PHP
jquery提示 "object expected"的解决方法
2009/12/13 Javascript
javascript生成随机颜色示例代码
2014/05/05 Javascript
JQuery插件jcarousellite的参数中文说明
2015/05/11 Javascript
基于jQuery实现在线选座之高铁版
2015/08/24 Javascript
JavaScript事件类型中UI事件详解
2016/01/14 Javascript
详解XMLHttpRequest(二)响应属性、二进制数据、监测上传下载进度
2016/09/14 Javascript
禁用backspace网页回退功能的实现代码
2016/11/15 Javascript
jquery插件锦集【推荐】
2016/12/16 Javascript
JS封装通过className获取元素的函数示例
2016/12/20 Javascript
微信小程序之picker日期和时间选择器
2017/02/09 Javascript
ionic+AngularJs实现获取验证码倒计时按钮
2017/04/22 Javascript
详解Angular 4.x NgTemplateOutlet
2017/05/24 Javascript
nodejs简单访问及操作mysql数据库的方法示例
2018/03/15 NodeJs
Javascript 之封装(Package)
2018/09/14 Javascript
微信小程序返回箭头跳转到指定页面实例解析
2019/10/08 Javascript
[49:20]VG vs TNC Supermajor小组赛B组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
Python实现Linux下守护进程的编写方法
2014/08/22 Python
Python实现打印螺旋矩阵功能的方法
2017/11/21 Python
python发送邮件脚本
2018/05/22 Python
pandas带有重复索引操作方法
2018/06/08 Python
python和shell监控linux服务器的详细代码
2018/06/22 Python
Django中的Model操作表的实现
2018/07/24 Python
详解centos7+django+python3+mysql+阿里云部署项目全流程
2019/11/15 Python
Python实现遗传算法(二进制编码)求函数最优值方式
2020/02/11 Python
解决pycharm安装第三方库失败的问题
2020/05/09 Python
新闻编辑专业毕业自荐书范文
2014/02/05 职场文书
《雨点》教学反思
2014/02/12 职场文书
2015年元旦文艺汇演主持词
2014/03/26 职场文书
学习实践科学发展观心得体会
2014/09/10 职场文书
学校总务处领导班子民主生活会对照检查材料思想汇报
2014/09/27 职场文书
2015年初三班主任工作总结
2015/05/21 职场文书
MySQL之高可用集群部署及故障切换实现
2021/04/22 MySQL