数独计算器是怎么编出来的

空位用空格补齐(每用下划线)

可以文件输入(用编译好的程序打开文件),亦可键盘输入。

用打过CRT补丁的Turbo Pascal编译,或使用Free Pascal(这个不保证正常)

样例没有超时,但对于特殊数据可能超时(我还没有数据,自己写得太简单,但是,特殊数据基本不会不超过0.01s)

程序如下:

program sdjsq;{数独解算器}

{-------------调用库------------------------------------------------USES}

uses CRT,Dos;{使用CRT Dos库}

{-------------数据类型定义------------------------------------------TYPE}

type

sz=0..9;{数字,byte类型的子界占一byte}

sy=1..9;{same as sz}

sd=array [sy,sy] of sz;{数独,占8×8×1byte=81byte}

ss=set of sy;{数字的集合}

dot=

record

s:ss;

n,x,y:byte;

end;

{-------------变量定义-----------------------------------------------VAR}

var

a:sd;

x,y:byte;

list:record

num:byte;

dat:array [1..81] of dot;

end;

{=============打印边框============================================PRINTK}

procedure printk;

var

i, k : byte;

flag : boolean;

begin

gotoxy(1,1);textcolor(15);textbackground(0);

write(#218);for k:=1 to 8 do write(#196#194);writeln(#196#191);

for i := 1 to 9 do begin

write(#179);for k:=1 to 9 do begin

textbackground(1-ord(((i-1) div 3+(k-1) div 3) mod 2=0));

write(#32);textbackground(0);write(#179);

end;

writeln;

if i<>9 then begin

write(#195);for k:=1 to 8 do write(#196#197);writeln(#196#180);

end;

end;

write(#192);for k:=1 to 8 do write(#196#193);writeln(#196#217);

gotoxy(1,1);

end;

{=============可以填的数==============================================KY}

procedure ky(a:sd;x,y:byte;var s:ss);

var

i,j:byte;

begin

s:=[1,2,3,4,5,6,7,8,9];

for i:=1 to 9 do if i<>x then s:=s-[a[i,y]];

for i:=1 to 9 do if i<>y then s:=s-[a[x,i]];

for i:=1 to 3 do for j:=1 to 3 do

if ((x-1)div 3*3+i<>x) and ((y-1)div 3*3+j<>y)

then s:=s-[a[(x-1)div 3*3+i,(y-1)div 3*3+j]];

s:=s-[0];

end;

{=============打印数据=============================================PRINT}

procedure print(xn,yn,color:byte);

begin

gotoxy(2*xn,2*yn);

textcolor(color);

textbackground(5+ord(not ((x=xn)and(y=yn)))*(-4-ord(((xn-1) div 3+(yn-1) div 3) mod 2=0)));

if a[xn,yn]<>0 then write(a[xn,yn]) else write(#32);

gotoxy(1,1);

end;

{=============用键盘读入数据===========================INPUT BY KEYBOARD}

procedure inputbkb(var a:sd);

label 1;

var

xi,yi:byte;

c:char;

s:ss;i:byte;

begin

printk;

fillchar(a,sizeof(a),0);x:=1;y:=1;print(1,1,0);

textcolor(15);textbackground(0);

s:=[1..9];gotoxy(1,20);for i:=1 to 9 do write(i:2);

repeat

c:=readkey;

xi:=x;yi:=y;

case c of

(*#13{Enter}, #27{Esc}*)

#27:halt;

(*#72{Up}, #75{Left}, #77{Right}, #80{Down}*)

#0:begin

c:=readkey;

case c of

#75:if x<>1 then x:=x-1 else write('');

#72:if y<>1 then y:=y-1 else write('');

#80:if y<>9 then y:=y+1 else write('');

#77:if x<>9 then x:=x+1 else write('');

#83:a[x,y]:=0;

end;

end;

#48..#58:if (ord(c)-48 in s) or (c=#48)

then a[x,y]:=ord(c)-48 else write('');

end;

print(xi,yi,12);print(x,y,12);

ky(a,x,y,s);

gotoxy(1,20);

textcolor(15);textbackground(0);delline;

for i:=1 to 9 do if i in s then write(i:2);

until c=#13;

x:=0;y:=0;print(xi,yi,12);

end;

procedure noans;

begin

gotoxy(1,20);

textbackground(0);delline;textcolor(143);

write('No answer!');

readkey;

halt;

end;

{=============用文件读入数据===============================INPUT BY FILE}

procedure inputbf(var a:sd;const path:string);

function Exist(Path:string):boolean;

var

S: PathStr;

begin

S := FSearch(Path, GetEnv(''));

Exist := S <> '';

end;

var

x,y:byte;

c:char;

f:text;

begin

if not exist(path) then begin

inputbkb(a);

end else begin

assign(f,path);reset(f);printk;

for y:=1 to 9 do begin

for x:=1 to 9 do begin

read(f,c);

if not (c in [#48..#58,#32]) then begin

inputbkb(a);exit;

end;

if c=#32 then a[x,y]:=0 else a[x,y]:=ord(c)-48;print(x,y,12);

end;

readln(f);

end;

end;

end;

{=============填入固定数据============================================TC}

procedure tc;

var

x,y,i,t,n,f:byte;

s:ss;

function tct:byte;

var

i,j,k,l:byte;

s1,s2,s3:ss;

n1,n2,n3:array [1..9] of byte;

begin

tct:=0;

for i:=1 to 9 do begin

fillchar(n1,sizeof(n1),0);fillchar(n3,sizeof(n3),0);fillchar(n2,sizeof(n2),0);

for j:=1 to 9 do begin

ky(a,i,j,s);if a[i,j]<>0 then begin s:=[a[i,j]]; n1[a[i,j]]:=10; end;

for k:=1 to 9 do if k in s then if n1[k]=0 then n1[k]:=j else n1[k]:=10;

ky(a,j,i,s);if a[j,i]<>0 then begin s:=[a[j,i]]; n2[a[j,i]]:=10; end;

for k:=1 to 9 do if k in s then if n2[k]=0 then n2[k]:=j else n2[k]:=10;

ky(a,((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1),s);

if a[((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1)]<>0 then begin

s:=[a[((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1)]];

n3[a[((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1)]]:=10;

end;

for k:=1 to 9 do if k in s then if n3[k]=0 then n3[k]:=j else n3[k]:=10;

end;

for k:=1 to 9 do begin

j:=n1[k];

if j in [1..9] then begin

a[i,j]:=k;print(i,j,6);tct:=1;exit;

end;

end;

for k:=1 to 9 do begin

j:=n2[k];

if j in [1..9] then begin

a[j,i]:=k;print(j,i,6);tct:=1;exit;

end;

end;

for k:=1 to 9 do begin

j:=n3[k];

if j in [1..9] then begin

a[((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1)]:=k;

print(((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1),6);

tct:=1;exit;

end;

end;

end;

end;

procedure check;

var

i,j,k:byte;

s,s1,s2,s3:ss;

begin

for i:=1 to 9 do begin

s1:=[];s2:=[];s3:=[];

for j:=1 to 9 do begin

if a[i,j]=0 then begin ky(a,i,j,s);s1:=s1+s; end else s1:=s1+[a[i,j]];

if a[j,i]=0 then begin ky(a,j,i,s);s2:=s2+s; end else s2:=s2+[a[j,i]];

if a[((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1)]=0 then begin

ky(a,((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1),s);s3:=s3+s;

end else s3:=s3+[a[((i-1) mod 3)*3+((j-1) mod 3+1),((i-1) div 3)*3+((j-1) div 3+1)]];

end;

for j:=1 to 9 do begin

if not (j in s1) then noans;

if not (j in s2) then noans;

if not (j in s3) then noans;

end;

end;

end;

begin

repeat

f:=0;

for x:=1 to 9 do

for y:=1 to 9 do

if a[x,y]=0 then begin

ky(a,x,y,s);t:=0;

if s=[] then

noans;

for i:=1 to 9 do if i in s then begin

t:=t+1;n:=i;

end;

if t=1 then begin a[x,y]:=n;print(x,y,14);f:=f+1; end;

end;

f:=f+tct;check;

until f=0;

end;

{=============递归求解===============================================TRY}

function answer:boolean;

var

ans:boolean;

procedure try(num:byte);

var

i,j,n,x,y:byte;

s:ss;

begin

if keypressed then case readkey of #27:halt;#0:if readkey=#107 then halt; end;

if num<=list.num then begin

x:=list.dat[num].x;y:=list.dat[num].y;

ky(a,x,y,s);if s=[] then exit;

n:=random(8)+1;

for j:=n to n+8 do begin

i:=j mod 9+1;

if i in s then begin

a[x,y]:=i;print(x,y,10);

try(num+1);

a[x,y]:=0;print(x,y,0)

end

end

end else begin

gotoxy(1,20);textcolor(15);textbackground(0);delline;write('Complete!');answer:=true;ans:=true;

case readkey of #27:halt;#0:if readkey=#107 then halt; end;

textcolor(15);textbackground(0);gotoxy(1,20);delline;writeln('Trying...');

end;

end;

begin

answer:=false;ans:=false;

try(1)

end;

procedure crtinit;

var

OrigMode: Word;

begin

OrigMode:=LastMode; { Remember original video mode }

TextMode(Lo(LastMode)+Font8x8); { use 43 or 50 lines on EGA/VGA }

end;

procedure px;

var

l:array [1..9] of record

num:byte;

dat:array [1..81] of dot;

end;

i,j,k:byte;

d:dot;

begin

for i:=1 to 9 do l[i].num:=0;

for i:=1 to 9 do for j:=1 to 9 do if a[i,j]=0 then begin

d.x:=i;d.y:=j;ky(a,i,j,d.s);d.n:=0;for k:=1 to 9 do if k in d.s then inc(d.n);

inc(l[d.n].num);l[d.n].dat[l[d.n].num]:=d;

end;

list.num:=0;

for i:=1 to 9 do for j:=1 to l[i].num do begin

inc(list.num);list.dat[list.num]:=l[i].dat[j];

end;

end;

begin

randomize;

crtinit;

textbackground(0);clrscr;

if ParamCount=0 then inputbkb(a) else inputbf(a,ParamStr(1));

textcolor(15);textbackground(0);gotoxy(1,20);delline;writeln('Thinking...');tc;

textcolor(15);textbackground(0);gotoxy(1,20);delline;writeln('Checking...');px;

textcolor(15);textbackground(0);gotoxy(1,20);delline;writeln('Trying...');gotoxy(1,1);

if not answer then noans;

textcolor(15);textbackground(0);gotoxy(1,20);delline;writeln('That''s all!');readkey;

end.