我来解数独(附delphi源码)
前段时间看到“69岁农民3天破解世界最难数独游戏”,然后在看了那个号称世界最难的数独题目之后,就打算抽空编程解决。今晚抽出一个晚上,大约四五个小时的时间,中间还间歇在clash of clans上造兵和进攻(好吧我承认这不是一个好习惯)。最终,很好地解决了。下面贴出源代码。
unit uSudoku; interface uses
Classes, sysutils, forms, windows, dialogs; type
TMapArray = array[.., ..] of Integer;
TSudokuMap = class(TObject)
private
FMap_init: TMapArray;
FMap: TMapArray;
iAnswer: integer;
function checknow(x,y: Integer): boolean;
function get_next_x_y(var xx, yy: Integer): Boolean;
public
ssResults: TStrings;
constructor Create;
destructor Destroy; override;
procedure init(ss: tstrings);
function map_output: string;
procedure onDone();
function go(x,y: Integer): boolean;
end; implementation { TSudokuMap } // 检查当前坐标处的数字是否合法
function TSudokuMap.checknow(x, y: Integer): boolean;
var
i: integer;
ix, iy, xx0, yy0: integer;
begin
result := true; // 检查横向冲突情况
if result then
begin
for i := to do
if (i<>x) and (FMap[i,y]=FMap[x,y]) then
begin
result := false;
break;
end;
end; // 检查竖向冲突情况
if result then
begin
for i := to do
if (i<>y) and (FMap[x,i]=FMap[x,y]) then
begin
result := false;
break;
end;
end; // 检查自己所在9宫格冲突情况
if result then
begin
xx0 := (x-) div * ;
yy0 := (y-) div * ;
for ix := to do
for iy := to do
if ((ix+xx0<>x) or (iy+yy0<>y)) and (FMap[ix+xx0,iy+yy0]=FMap[x,y]) then
begin
result := false;
break;
end;
end;
end; constructor TSudokuMap.Create;
begin
inherited;
iAnswer := ;
ssResults := TStringList.Create;
end; destructor TSudokuMap.Destroy;
begin
FreeAndNil(ssResults);
inherited;
end; function TSudokuMap.get_next_x_y(var xx, yy: Integer): Boolean;
begin
if yy< then
yy := yy+
else
begin
yy := ;
xx := xx+;
end; result := xx<=;
end; // 求解,结果放于ssResults中
function TSudokuMap.go(x, y: Integer): boolean;
var
i: integer;
xx, yy: integer;
begin
if FMap_init[x,y]> then
begin
result := checknow(x,y);
if Result then
begin
xx := x; yy := y;
if get_next_x_y(xx, yy) then
result := go(xx, yy);
end;
end
else
begin
for i := to do
begin
FMap[x,y] := i;
result := checknow(x,y);
if Result then
begin
xx := x; yy := y;
if get_next_x_y(xx, yy) then
begin
result := go(xx, yy);
//if result then break;
end
else
break;
end;
end;
end; if (x=) and (y=) and Result then
onDone(); // 如果本次遍历从1到9均不成功,则将FMap[x,y]复原,以免影响后续计算
if (not Result) then FMap[x,y] := FMap_init[x,y];
end; {-------------------------------------------------------------------------------
主要用于生成数独初始map。输入参数形如:
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700
-------------------------------------------------------------------------------}
procedure TSudokuMap.init(ss: tstrings);
var
s: string;
x, y: integer;
begin
for x := to do
begin
s := ss[x-];
for y := to do
begin
FMap[x,y] := strtoint(s[y]);
FMap_init[x,y] := FMap[x,y];
end;
end;
end; {-------------------------------------------------------------------------------
将FMap以如下形式输出:
. . 5 3 . . . . .
8 . . . . . . 2 .
. 7 . . 1 . 5 . .
...
-------------------------------------------------------------------------------}
function TSudokuMap.map_output: string;
const CR=##;
var
x, y: integer;
s: string;
ch: string;
begin
s := '';
for x := to do
begin
for y := to do
begin
ch := inttostr(FMap[x,y]);
if ch='' then ch:='.';
s := s+ch+' ';
end;
s := s + CR;
end;
Result := s;
end; procedure TSudokuMap.onDone;
var
filename: string;
begin
Inc(iAnswer);
ssResults.Add(IntToStr(iAnswer));
ssResults.Add(map_output);
end; end.
调用代码:
procedure TForm1.go(memo1: TMemo);
var
Sudoku: TSudokuMap;
begin
Sudoku := TSudokuMap.create;
Sudoku.init(Memo1.lines);
mmo1.Text := sudoku.map_output;
sudoku.go(,);
Caption := 'OK! '+datetimetostr(now);
mmo4.Lines.Assign(Sudoku.ssResults);
end; procedure TForm1.btn3Click(Sender: TObject);
begin
go(mmo3);
end;

对于这道题目,程序瞬间解出答案。为了精确计算,我重复了1000次,耗时27秒。
本来还希望能找出一种以上的解,结果只有一解:
1 4 5 3 2 7 6 9 8
8 3 9 6 5 4 1 2 7
6 7 2 9 1 8 5 4 3
4 9 6 1 8 5 3 7 2
2 1 8 4 7 3 9 5 6
7 5 3 2 9 6 4 8 1
3 6 7 5 4 2 8 1 9
9 8 4 7 6 1 2 3 5
5 2 1 8 3 9 7 6 4
===========================
另外,新闻稿上老人解的那道题 http://news.qq.com/a/20130526/005425.htm

这道题录入程序后,用了一秒钟得到唯一解:
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
而老人把第四行的5改为8后,花了3个月时间才解出来。按照他的改法,程序共发现了133种解法,老人给出的解法是我的第122解。希望老人知道了之后不要太伤心哦~

我来解数独(附delphi源码)的更多相关文章
- SpringBoot学习入门之Hello项目的构建、单元测试和热部署等(配图文,配置信息详解,附案例源码)
前言: 本文章主要是个人在学习SpringBoot框架时做的一些准备,参考老师讲解进行完善对SpringBoot构建简单项目的学习汇集成本篇文章,作为自己对SpringBoot框架的总结与笔记. 你将 ...
- 在WebBrowser中执行javascript脚本的几种方法整理(execScript/InvokeScript/NavigateScript) 附完整源码
[实例简介] 涵盖了几种常用的 webBrowser执行javascript的方法,详见示例截图以及代码 [实例截图] [核心代码] execScript方式: 1 2 3 4 5 6 7 8 9 1 ...
- Asp.net MVC集成Google Calendar API(附Demo源码)
Asp.net MVC集成Google Calendar API(附Demo源码) Google Calendar是非常方便的日程管理应用,很多人都非常熟悉.Google的应用在国内不稳定,但是在国外 ...
- winserver的consul部署实践与.net core客户端使用(附demo源码)
winserver的consul部署实践与.net core客户端使用(附demo源码) 前言 随着微服务兴起,服务的管理显得极其重要.都知道微服务就是”拆“,把臃肿的单块应用,拆分成多个轻量级的 ...
- spring事务详解(三)源码详解
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- [源码]Delphi源码免杀之函数动态调用 实现免杀的下载者
[免杀]Delphi源码免杀之函数动态调用 实现免杀的下载者 2013-12-30 23:44:21 来源:K8拉登哥哥's Blog 自己编译这份代码看看 过N多杀软 没什么技 ...
- QQ2008自动聊天精灵delphi源码
QQ2008自动聊天精灵delphi源码 unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Grap ...
- C#代码生成器附百度云盘源码地址
今晚闲着没事,写了个代码生成器,在这里只做个抛砖引玉,后面可以继续扩展功能,下方附百度云盘源码地址. 使用数据库:sqlserver 编译器:vs2015 废话不多说,上界面: 程序主界面: 数据库: ...
- 转换GMT秒数为日期时间格式-Delphi源码
转换GMT秒数为日期时间格式-Delphi源码.收藏最近在写PE分析工具的时候,需要转换TimeDateStamp字段值为日期时间格式,这是Delphi的源码. //把GMT时间的秒数转换成日期时间格 ...
随机推荐
- 一题多解 —— linux 日志文件(log)reload 重新载入
1. tail -F 等同于–follow=name –retry,根据文件名进行追踪,并保持重试,即该文件被删除或改名后,如果再次创建相同的文件名,会继续追踪 也即可以间接实现从日志文件末尾,不断载 ...
- 【前端】CentOS 7 系列教程之六: 安装 mysql 5.7
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/linux_6.html 进入/usr/local/src目录 cd /usr/local/src 下载mysql的 ...
- 使用lsyncd配置数据库备份多异地同步
lsyncd配置文件 settings { logfile = "/var/log/lsyncd.log", --日志路径 status = "/var/log/lsyn ...
- 让ubuntu16.04开机进入命令行模式
使用Ubuntu时,有时候我们不想开机进入桌面,想直接进入命令行,这样启动的比较快, 1.首先我们修改grub文件,改为如图所示: sudo gedit /etc/default/grub 改完之后 ...
- UVaLive 7455 Linear Ecosystem (Gaussi 消元)
题意:对一个k元向量, 每次左乘一个k*k的矩阵得到新的向量.问经过一定次数的左乘后,能否使得该向量不再变化. (同时要求此时向量非零). 析:设初始向量为A,矩阵为P.由于每次矩阵P都是左乘A, 那 ...
- NYOJ3——多边形重心问题
多边形重心问题 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述:在某个多边形上,取n个点,这n个点顺序给出,按照给出顺序将相邻的点用直线连接, (第一个和最后一个连接) ...
- ORACLE PL/SQL 实例精解之第三章 PL/SQL中的SQL
3.1 在PL/SQL中使用DML 在PL/SQL语块中,两种变量赋值a. := 初始化.b. select into语法,PL/SQL语块的声明部分被声明的变量,后期可以使用选择语句进行赋值. 3. ...
- React 从入门到进阶之路(八)
之前的文章我们介绍了 React中的组件.父子组件.React props父组件给子组件传值.子组件给父组件传值.父组件中通过refs获取子组件属性和方法.接下来我们将介绍 React propTyp ...
- 洛谷 - P1141 - 01迷宫 - dfs
https://www.luogu.org/problemnew/show/P1141 能互相到达的格子的答案自然是一样的,第一次dfs标记联通块,第二次dfs把cnt传递到整个联通卡并顺手消除vis ...
- Cg(C for Graphic)语言关键字(转)
摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 第三章从 GPU 运行原理和数据流程的角 ...