c2fbdf929c
git-svn-id: svn://kolibrios.org@1805 a494cfbc-eb01-0410-851d-a64ba20cac60
424 lines
6.9 KiB
ObjectPascal
424 lines
6.9 KiB
ObjectPascal
;unit SudokuSolve;
|
|
|
|
;interface
|
|
|
|
;type
|
|
; TSudokuBoard=array[0..8,0..8] of byte;//òèï ïîëå äëÿ èãðû
|
|
|
|
; function CheckSudoku(var Map: TSudokuBoard): boolean;
|
|
; //âîçâðàùàåò true åñëè ïîëå ñîñòàâëåíî ïðàâèëüíî
|
|
|
|
; function Solve(var Map: TSudokuBoard): integer;
|
|
; //ðåøàåò Ñóäîêó
|
|
; //Result = 1; - ðåøåíèå íàéäåíî
|
|
; //Result = -1; - òóïèêëâàÿ êîìáèíàöèÿ
|
|
|
|
; procedure CopyArray(var Dst: TSudokuBoard;Src: TSudokuBoard);
|
|
|
|
;implementation
|
|
|
|
;type
|
|
; TSudokuPt=record //òèï òî÷êà ñ ìèíèìàëüíûì ÷èñëîì êàíäèäàòîâ
|
|
; mini,minj,variances: byte;
|
|
; end;
|
|
|
|
;var
|
|
; TempMap: TSudokuBoard;//ïîëÿ
|
|
; Pt: TSudokuPt; //òî÷êà
|
|
; i,j: byte; //ñ÷åò÷èêè
|
|
|
|
|
|
|
|
align 4
|
|
CheckSudoku:
|
|
pushad
|
|
;function CheckSudoku(var Map: TSudokuBoard): boolean; ;êàðòà â esi!
|
|
;var
|
|
; i,j,x,y: byte;
|
|
; Zap: set of byte;
|
|
;begin
|
|
|
|
;//ïðîâåðÿåì ñòîëáöû
|
|
; for i:=0 to 8 do
|
|
; begin
|
|
; Zap:=[];
|
|
; for j:=0 to 8 do
|
|
; if Map[i,j]<>0 then
|
|
; if Map[i,j] in Zap then
|
|
; begin
|
|
; Result:=false;
|
|
; Exit;
|
|
; end else
|
|
; Zap:=Zap+[Map[i,j]];
|
|
; end;
|
|
xor ecx,ecx
|
|
xor eax,eax
|
|
xor edx,edx
|
|
mov bx,0x0909
|
|
.1: mov al, byte [esi+ecx]
|
|
test al,al
|
|
jz @f
|
|
btc dx,ax
|
|
jc .ret_false
|
|
@@:
|
|
add cl,9
|
|
dec bl
|
|
jnz .1
|
|
; test [flags],1 shl 15
|
|
; jz @f
|
|
; cmp edx,1022 ;1111111110b
|
|
; jne .ret_false
|
|
;@@:
|
|
bt [flags],15
|
|
jnc @f
|
|
cmp dx,1022 ;1111111110
|
|
jne .ret_false
|
|
@@:
|
|
sub cl,9*9-1
|
|
xor edx,edx
|
|
mov bl,9
|
|
dec bh
|
|
jnz .1
|
|
|
|
|
|
;//ïðîâåðÿåì ñòðîêè
|
|
; for j:=0 to 8 do
|
|
; begin
|
|
; Zap:=[];
|
|
; for i:=0 to 8 do
|
|
; if Map[i,j]<>0 then
|
|
; if Map[i,j] in Zap then
|
|
; begin
|
|
; Result:=false;
|
|
; Exit;
|
|
; end else
|
|
; Zap:=Zap+[Map[i,j]]
|
|
; end;
|
|
|
|
xor ecx,ecx
|
|
xor eax,eax
|
|
xor edx,edx
|
|
mov bx,0x0909
|
|
.2: mov al, byte [esi+ecx]
|
|
test al,al
|
|
jz @f
|
|
btc dx,ax
|
|
jc .ret_false
|
|
@@:
|
|
inc ecx
|
|
dec bl
|
|
jnz .2
|
|
bt [flags],15
|
|
jnc @f
|
|
cmp dx,1022 ;1111111110
|
|
jne .ret_false
|
|
@@:
|
|
xor edx,edx
|
|
mov bl,9
|
|
dec bh
|
|
jnz .2
|
|
|
|
;//ïðîâåðÿåì ñåêòîðà
|
|
;for i:=0 to 2 do
|
|
; for j:=0 to 2 do
|
|
; begin
|
|
; zap:=[];
|
|
; for x:=0 to 2 do
|
|
; for y:=0 to 2 do
|
|
; if map[i*3+y,j*3+x]<>0 then
|
|
; if map[i*3+y,j*3+x] in Zap then
|
|
; begin
|
|
; Result:=false;
|
|
; exit;
|
|
; end else
|
|
; Zap:=zap+[map[i*3+y,j*3+x]];
|
|
; end;
|
|
;Result:=true;
|
|
;end;
|
|
mov ecx,0x0303 ;ij
|
|
xor eax,eax
|
|
xor edx,edx
|
|
mov ebx,0x0303 ;xy
|
|
|
|
.3: movzx eax,ch
|
|
dec al
|
|
lea eax,[eax*2+eax]
|
|
add al,bl ;i*3+y
|
|
dec al
|
|
mov edi,eax
|
|
movzx eax,cl
|
|
dec al
|
|
lea eax,[eax*2+eax]
|
|
add al,bh ;j*3+x
|
|
dec al
|
|
xchg eax,edi
|
|
mov ah,9
|
|
mul ah
|
|
add eax,edi ;i*3+y,j*3+x
|
|
mov al,[esi+eax]
|
|
test al,al
|
|
jz @f
|
|
btc dx,ax
|
|
jc .ret_false
|
|
@@:
|
|
dec bl
|
|
jnz .3
|
|
mov bl,3
|
|
dec bh
|
|
jnz .3
|
|
bt [flags],15
|
|
jnc @f
|
|
cmp dx,1022 ;1111111110
|
|
jne .ret_false
|
|
@@:
|
|
mov bx,0x0303
|
|
xor edx,edx
|
|
dec cl
|
|
jnz .3
|
|
mov cl,3
|
|
dec ch
|
|
jnz .3
|
|
popad
|
|
clc
|
|
ret
|
|
.ret_false:
|
|
popad
|
|
stc
|
|
ret
|
|
|
|
_iRet dw ?
|
|
|
|
Pt:
|
|
.mini db ?
|
|
.minj db ?
|
|
.variances db ?
|
|
|
|
bFree db ?
|
|
nVariances db ?
|
|
nMinVariances db ?
|
|
|
|
align 4
|
|
FindMinPoint:
|
|
pushad
|
|
mov [bFree],0
|
|
mov [nMinVariances],10
|
|
mov cx,0x0909 ;ij
|
|
.1: movzx eax,ch
|
|
mov ah,9
|
|
dec al
|
|
mul ah
|
|
add al,cl
|
|
dec al
|
|
cmp byte [esi+eax],0
|
|
je @f
|
|
.11: dec cl
|
|
jnz .1
|
|
mov cl,9
|
|
dec ch
|
|
jnz .1
|
|
jmp .3
|
|
|
|
@@: mov [nVariances],0
|
|
mov [bFree],1
|
|
mov ebx,1
|
|
.2: mov [esi+eax],bl
|
|
call CheckSudoku
|
|
jc @f
|
|
inc [nVariances]
|
|
@@: inc ebx
|
|
cmp ebx,9
|
|
jbe .2
|
|
|
|
mov byte [esi+eax],0
|
|
mov dl,[nVariances]
|
|
cmp dl,0
|
|
je .11
|
|
cmp dl,[nMinVariances]
|
|
jnb .11
|
|
mov [Pt.mini],ch
|
|
mov [Pt.minj],cl
|
|
mov [Pt.variances],dl
|
|
mov [nMinVariances],dl
|
|
jmp .11
|
|
|
|
.3: cmp [bFree],1
|
|
jne @f
|
|
cmp [nMinVariances],10
|
|
jge @f
|
|
mov [_iRet],1
|
|
popad
|
|
ret
|
|
@@: cmp [bFree],1
|
|
jne @f
|
|
mov [_iRet],-1
|
|
popad
|
|
ret
|
|
@@: mov [_iRet],0
|
|
popad
|
|
ret
|
|
|
|
|
|
; //èùåò òî÷êó ñ ìèíèìàëüíûì ÷èñëîì êàíäèäàòîâ è çàïèñèâàåò ðåçóëüòàò â MinPt
|
|
; //Result = -1; - íàøëè, êóäà ìîæíî ïîñòàâèòü öèôðó
|
|
; //Result = 1; - ñâîáîäíîå ìåñòî åñòü íà ïîëå, íî ïîñòàâèòü íèêóäà íåëüçÿ
|
|
; //Result = 0; - íåò ñâîáîäíîãî ìåñòà
|
|
;function FindMinPoint(var MinPt: TSudokuPt;var Map: TSudokuBoard): integer;
|
|
;var
|
|
;nVariances,nMinVariances,variance: byte;
|
|
;bFree: boolean;
|
|
;begin
|
|
;bFree:= false;
|
|
;nMinVariances:=10;
|
|
;for i:=0 to 8 do
|
|
; for j:=0 to 8 do
|
|
; begin
|
|
; if Map[i,j]<>0 then continue;
|
|
; nVariances := 0;
|
|
; bFree := true;
|
|
; for variance:=1 to 9 do
|
|
; begin
|
|
; map[i,j]:=variance;
|
|
; if CheckSudoku(Map) then inc(nVariances);
|
|
; end;
|
|
; Map[i,j]:=0;
|
|
; if nVariances=0 then continue;
|
|
; if nVariances < nMinVariances then
|
|
; begin
|
|
; MinPt.mini:=i;
|
|
; MInPt.minj:=j;
|
|
; MinPt.variances:=nVariances;
|
|
; nMinVariances := nVariances;
|
|
; end;
|
|
; end;
|
|
;if (bFree) and (nMinVariances<10) then // íàøëè, êóäà ìîæíî ïîñòàâèòü öèôðó
|
|
; begin
|
|
; Result:=1;
|
|
; Exit;
|
|
; end;
|
|
;if bFree then // ñâîáîäíîå ìåñòî åñòü íà ïîëå, íî ïîñòàâèòü íèêóäà íåëüçÿ
|
|
; begin
|
|
; Result:=-1;
|
|
; exit;
|
|
; end;
|
|
;result:=0; // íåò ñâîáîäíîãî ìåñòà
|
|
;end;
|
|
|
|
|
|
|
|
;procedure CopyArray(var Dst: TSudokuBoard;Src: TSudokuBoard);
|
|
;begin
|
|
;for i:=0 to 8 do
|
|
; for j:=0 to 8 do
|
|
; Dst[i,j]:=Src[i,j];
|
|
;end;
|
|
|
|
CopyArray:
|
|
push ecx eax
|
|
xor ecx,ecx
|
|
@@: mov al,[esi+ecx]
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
cmp ecx,9*9
|
|
jb @b
|
|
pop eax ecx
|
|
ret
|
|
|
|
|
|
|
|
align 4
|
|
Solve:
|
|
pushad
|
|
if DEBUG
|
|
dbg_dec esp
|
|
dbg_dec ecx
|
|
mcall 5,1
|
|
endf
|
|
call FindMinPoint
|
|
cmp [_iRet],0
|
|
jne @f
|
|
mov [_iRet],1
|
|
popad
|
|
ret
|
|
@@:
|
|
cmp [_iRet],-1
|
|
jne @f
|
|
popad
|
|
ret
|
|
@@:
|
|
push esi edi
|
|
mov edi,TempMap
|
|
call CopyArray
|
|
pop edi esi
|
|
mov ecx,1
|
|
movzx eax, byte [Pt.mini]
|
|
dec al
|
|
mov ah,9
|
|
mul ah
|
|
add al,byte [Pt.minj]
|
|
dec al
|
|
.1: mov byte [esi+eax],cl
|
|
call CheckSudoku
|
|
jnc @f
|
|
.2: inc ecx
|
|
cmp ecx,9
|
|
jbe .1
|
|
; jmp .1
|
|
@@: call Solve
|
|
cmp [_iRet],-1
|
|
jne @f
|
|
push esi edi
|
|
mov edi,TempMap
|
|
xchg esi,edi
|
|
call CopyArray
|
|
pop edi esi
|
|
popad
|
|
ret
|
|
@@: cmp [_iRet],1
|
|
jne .3
|
|
popad
|
|
ret
|
|
.3: mov [_iRet],0
|
|
popad
|
|
ret
|
|
|
|
;function Solve(var Map: TSudokuBoard): integer;
|
|
;var
|
|
; variance: byte;
|
|
; iRet: integer;
|
|
;begin
|
|
;// èùåì êëåòêó ñ íàèìåíüøèì ÷èñëîì êàíäèäàòîâ:
|
|
;iRet:=FindMinPoint(Pt,Map);
|
|
;if (iRet = 0) then
|
|
; begin
|
|
; result:=1;// ðåøåíèå íàéäåíî
|
|
; exit;
|
|
; end else
|
|
;if (iRet = -1) then // òóïèêîâàÿ êîìáèíàöèÿ
|
|
; begin
|
|
; result:=-1;
|
|
; exit;
|
|
; end;
|
|
|
|
;CopyArray(TempMap,Map); // ñîõðàíÿåì òî, ÷òî åñòü
|
|
;for variance:=1 to 9 do
|
|
;begin
|
|
; Map[pt.mini,pt.minj]:=variance; // ïûòàåìñÿ ñòàâèòü íà íàéäåííóþ êëåòêó öèôðû îò 1 äî 9
|
|
; if not CheckSudoku(Map) then continue; // òàêóþ öèôðó ïîñòàâèòü íåëüçÿ. Áåð¸ì ñëåäóþùóþ.
|
|
; iRet:=Solve(Map); // çàïóñêàåì ôóíêöèþ ðåêóðñèâíî
|
|
; if iRet=-1 then // òóïèêîâàÿ êîìáèíàöèÿ
|
|
; begin
|
|
; CopyArray(Map,tempmap); // âîññòàíàâëèâàåì ìàññèâ è áåð¸ì ñëåäóþùóþ öèôðó íà òî æå ìåñòî
|
|
; continue;
|
|
; end;
|
|
;if iRet=1 then // ðåøåíèå íàéäåíî
|
|
; begin
|
|
; Result:=1;
|
|
; exit;
|
|
; end;
|
|
;end;
|
|
;Result:=0;
|
|
;end;
|
|
|
|
;end.
|
|
|