前段时间看到“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源码)的更多相关文章

  1. SpringBoot学习入门之Hello项目的构建、单元测试和热部署等(配图文,配置信息详解,附案例源码)

    前言: 本文章主要是个人在学习SpringBoot框架时做的一些准备,参考老师讲解进行完善对SpringBoot构建简单项目的学习汇集成本篇文章,作为自己对SpringBoot框架的总结与笔记. 你将 ...

  2. 在WebBrowser中执行javascript脚本的几种方法整理(execScript/InvokeScript/NavigateScript) 附完整源码

    [实例简介] 涵盖了几种常用的 webBrowser执行javascript的方法,详见示例截图以及代码 [实例截图] [核心代码] execScript方式: 1 2 3 4 5 6 7 8 9 1 ...

  3. Asp.net MVC集成Google Calendar API(附Demo源码)

    Asp.net MVC集成Google Calendar API(附Demo源码) Google Calendar是非常方便的日程管理应用,很多人都非常熟悉.Google的应用在国内不稳定,但是在国外 ...

  4. winserver的consul部署实践与.net core客户端使用(附demo源码)

    winserver的consul部署实践与.net core客户端使用(附demo源码)   前言 随着微服务兴起,服务的管理显得极其重要.都知道微服务就是”拆“,把臃肿的单块应用,拆分成多个轻量级的 ...

  5. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  6. [源码]Delphi源码免杀之函数动态调用 实现免杀的下载者

    [免杀]Delphi源码免杀之函数动态调用 实现免杀的下载者 2013-12-30 23:44:21         来源:K8拉登哥哥's Blog   自己编译这份代码看看 过N多杀软  没什么技 ...

  7. QQ2008自动聊天精灵delphi源码

    QQ2008自动聊天精灵delphi源码   unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Grap ...

  8. C#代码生成器附百度云盘源码地址

    今晚闲着没事,写了个代码生成器,在这里只做个抛砖引玉,后面可以继续扩展功能,下方附百度云盘源码地址. 使用数据库:sqlserver 编译器:vs2015 废话不多说,上界面: 程序主界面: 数据库: ...

  9. 转换GMT秒数为日期时间格式-Delphi源码

    转换GMT秒数为日期时间格式-Delphi源码.收藏最近在写PE分析工具的时候,需要转换TimeDateStamp字段值为日期时间格式,这是Delphi的源码. //把GMT时间的秒数转换成日期时间格 ...

随机推荐

  1. 栏目抓取网站日kafka

    #!/usr/bin/python3#-*- coding:utf-8 -*-"""create 2018-02-27author zldesc: https://ind ...

  2. Oracle:sequence问题研究

    一直以来,以为sequence是不间断地持续增长的:但今天发现sequence是会跳号,这种情况发生在RAC环境下.在单实例环境下,应该不存在的. sequence截图如下: 数据库表中发生了跳号: ...

  3. 自写程序调用mount

    代码: int fd = open("/dev/fuse", O_RDWR); printf("fd=%d\n",fd); int res; res=mount ...

  4. virtualbox 复制虚拟机提示uuid is exists

    C:\Program Files\Oracle\VirtualBox>VBoxManage.exe internalcommands sethduuid D:毛毛草\virtual\ubuntu ...

  5. 使用masonry手写约束

    在iOS开发过程中,手写contraints是非常痛苦的一件事情,往往那么一丢丢功能要写大量的代码,非常容易发生错误,并且非常不方便调试.所以只有在不得以的情况下才采用手工方式写contraints, ...

  6. SQLite学习手册(开篇)

    一.简介: SQLite是目前最流行的开源嵌入式数据库,和很多其他嵌入式存储引擎相比(NoSQL),如BerkeleyDB.MemBASE等,SQLite可以很好的支持关系型数据库所具备的一些基本特征 ...

  7. Servlet3.0之九:web模块化

    一.使用web-fragment.xml 在Servlet 3.0中,可以使用标注来设置Servlet的相关信息.实际上,Web容器并不仅读取/WEB-INF/classes中的Servlet标注信息 ...

  8. 3、HTML的body内标签1

    一.特殊符号的表示   #代指空格 < #代指,< > #代指,> ...... #这玩意有很多,记也记不完,用的时候查一下即可: 二.p和br标签 <p>< ...

  9. 洛谷 - P1225 - 黑白棋游戏 - bfs

    神奇bug,没有记录pre就show了,找了1个小时. #include <bits/stdc++.h> using namespace std; #define ll long long ...

  10. 洛谷 - P2444 - 病毒 - AC自动机

    https://www.luogu.org/problemnew/show/P2444 有点恶心,不太明白fail的意义. #include<bits/stdc++.h> using na ...