我来解数独(附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时间的秒数转换成日期时间格 ...
随机推荐
- codeforces 441B. Valera and Fruits 解题报告
题目链接:http://codeforces.com/problemset/problem/441/B 题目意思:有 n 棵fruit trees,每课水果树有两个参数描述:水果成熟的时间和这棵树上水 ...
- [置顶] SQL Server 2005 双机热备的实现
[置顶] SQL Server 2005 双机热备的实现 分类: SQLSERVER2011-08-24 21:25 901人阅读 评论(0) 收藏 举报 sql servermicrosoftsql ...
- No tests found with test runner 'JUnit 3'
报异常:No tests found with test runner 'JUnit 3' 解决方案: 主要因为你当前建的JUnit类是3的版本,将该类备份,重新创建一个类. 1.右键目录New--O ...
- I.MX6 u-boot 2009 lvds hdmi lcd 补丁
/************************************************************************* * I.MX6 u-boot 2009 lvds ...
- CodeForces19D:Points(线段树+set(动态查找每个点右上方的点))
Pete and Bob invented a new interesting game. Bob takes a sheet of paper and locates a Cartesian coo ...
- web.xml配置之<context-param>
<context-param>的作用和用法: 1.<context-param>配置是是一组键值对,比如: <context-param> <p ...
- div 加滚动条的方法
div 加滚动条的方法: <div style="position:absolute; height:400px; overflow:auto"></div> ...
- [msf]CentOS VPS创建pptpd 并搭建msf
安装pptpd服务 vps下 下载 centos 6 一键安装包 wget --no-check-certificate https://raw.githubusercontent.com/teddy ...
- VS代码中常用 正则表达式
1. #define ABC 1 修改为 enum 样式: #define (.+?)\s+(.+?)$ $1 = $2 ,
- 7天学完Java基础之5/7
接口 接口就是一种公共的规范标准 是一种引用数据类型 定义格式 public interface 接口名称{} java7 中接口可以包含常量,抽象方法:Java8 还可以额外包含默认方法,静态方法: ...