Program resolves sudoku in pascal

Delphi & Pascal (česká wiki)
Přejít na: navigace, hledání
Category: Source in Pascal
sudoku.pngProgram: Sudoku.pas
File exe: Sudoku.exe
File ubuntu: Sudoku
Example: Sudoku.dat

Program resolves sudoku in pascal. For moving use arrows. After press F5 program resolves sudoku. Example or resolve is save in file sudoku.dat.
{ SUDOKU.PAS                Copyright (c) TrSek alias Zdeno Sekerak }
{ Program na riesenie hry sudoku                                    }
{ Umoznuje zadat cisla a uchovava v subore aktualne riesenia.       }
{                                                                   }
{ Datum:20.7.2005                              http://www.trsek.com }
 
program sudoku;
uses crt;
 
const LEFT  = 14;
      UP    = 4;
      SPACE = ' ';
   DAT_FILE = 'sudoku.dat';
       COL1 = DARKGRAY;
       COL2 = LIGHTGRAY;
      COLBG = BLACK;
 
var   s: array[1..9,1..9,0..9] of byte;
    x,y: integer;
     ch: char;
 
 
procedure writexy(x,y:integer; s:string);
begin
  gotoxy(x,y);
  write(s);
end;
 
 
{ view plain of sudoku }
procedure ViewSudoku;
begin
  textcolor(COL1);
  writexy( LEFT, UP   ,  '+---+---+---+---+---+---+---+---+---+' );
  writexy( LEFT, UP+ 1,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+ 2,  '+---+---+---+---+---+---+---+---+---+' );
  writexy( LEFT, UP+ 3,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+ 4,  '+---+---+---+---+---+---+---+---+---+' );
  writexy( LEFT, UP+ 5,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+ 6,  '+===+===+===+===+===+===+===+===+===+' );
  writexy( LEFT, UP+ 7,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+ 8,  '+---+---+---+---+---+---+---+---+---+' );
  writexy( LEFT, UP+ 9,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+10,  '+---+---+---+---+---+---+---+---+---+' );
  writexy( LEFT, UP+11,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+12,  '+===+===+===+===+===+===+===+===+===+' );
  writexy( LEFT, UP+13,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+14,  '+---+---+---+---+---+---+---+---+---+' );
  writexy( LEFT, UP+15,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+16,  '+---+---+---+---+---+---+---+---+---+' );
  writexy( LEFT, UP+17,  '|   |   |   I   |   |   I   |   |   |' );
  writexy( LEFT, UP+18,  '+---+---+---+---+---+---+---+---+---+' );
  textcolor(COL2);
end;
 
 
procedure ViewHelp;
begin
  writexy(2, 2,'SuDoKu resolver ver.1.0             Software by Zdeno Sekerak, www.trsek.com');
  writexy(2, 5,'x=  y=');
  writexy(2, 7,'Choice=');
  writexy(2,24,'F1-Help F2-Save F3-Load F5-Resolve F8-Clear Arrows-Move ESC-Finish');
 
  writexy(54,19,'Venovane mojmu synovi');
  writexy(54,20,'  Zdenkovi Sekerakovi');
end;
 
 
{ view help of sudoku }
procedure Help;
begin
end;
 
 
{ move to position and write number }
{ write possible number for this }
procedure Kurzor(x,y,c:integer);
var xr,yr:integer;
    i:integer;
begin
  gotoxy(4,5); write(x);
  gotoxy(8,5); write(y);
 
  { view choice }
  gotoxy(2,8);
  for i:=1 to 9 do
    if( s[x,y,i]=0 )then
       write(SPACE)
    else
       write(i);
 
  { calc real position }
  xr:=LEFT + x*4 -2;
  yr:=UP + y*2 -1;
 
  gotoxy(xr,yr);
  textbackground(c);
 
  if( s[x,y,0]=0 )then
     write( SPACE )
  else
     write(s[x,y,0]);
 
  gotoxy(xr,yr);
end;
 
 
{ clear area }
procedure Clear;
var xc,yc,i: integer;
begin
  for xc:=1 to 9 do
    for yc:=1 to 9 do
    begin
      for i:=0 to 9 do
         s[xc,yc,i]:=i;
 
      Kurzor(xc,yc,COLBG);
    end;
end;
 
 
{ save to file }
procedure Save;
var f: file of byte;
    xc,yc: integer;
begin
  Assign(f, DAT_FILE);
  ReWrite(f);
 
  for xc:=1 to 9 do
    for yc:=1 to 9 do
      Write(f, s[xc,yc,0]);
 
  Close(f);
end;
 
 
{ load from file }
procedure Load;
var f: file of byte;
    xc,yc: integer;
begin
  Clear;
 
  {$I-}
  Assign(f, DAT_FILE);
  ReSet(f);
  {$I+}
 
  { if file exist }
  if( IOResult=0 )then
  begin
    for xc:=1 to 9 do
      for yc:=1 to 9 do
      begin
        Read(f, s[xc,yc,0]);
        Kurzor(xc,yc,COLBG);
      end;
    Close(f);
  end;
end;
 
 
{ if only one kind than it's a resolve }
function GetSingle(x,y: integer):byte;
var i: integer;
    w: integer;
begin
  w:=0;
 
  for i:=1 to 9 do
    if( s[x,y,i]<>0 ) then
    begin
      if( w=0 )then w:=i
               else w:=-1;
    end;
 
  { result }
  if( w>0 )then GetSingle:=w
           else GetSingle:=0;
end;
 
 
{ cross test of use some number }
function KrossTest(xc,yc:integer):byte;
var x,y: integer;
  xs,ys: integer;
      i: integer;
    poc: integer;
begin
  KrossTest:=0;
 
  for i:=1 to 9 do
    if( s[xc,yc,i]<>0 )then
    begin
      poc:=0;
 
      { left to right }
      for x:=1 to 9 do
        if(( s[x,yc,i]=i ) and (s[x,yc,0]=0 ))then
           inc(poc);
 
      { single? }
      if( poc=1 )then
          KrossTest:=i;
 
      poc:=0;
      { up to down }
      for y:=1 to 9 do
        if(( s[xc,y,i]=i ) and (s[xc,y,0]=0 ))then
           inc(poc);
 
      { single }
      if( poc=1 )then
          KrossTest:=i;
 
      { in square }
      poc:=0;
      xs:=(xc-1) div 3;
      ys:=(yc-1) div 3;
 
      for x:=1 to 3 do
        for y:=1 to 3 do
          if(( s[3*xs+x,3*ys+y,i]=i ) and (s[3*xs+x,3*ys+y,0]=0 ))then
               inc(poc);
 
      { single }
      if( poc=1 )then
          KrossTest:=i;
    end;
end;
 
 
{ make resolve }
function Resolve:boolean;
var xc,yc: integer;
    xs,ys: integer;
    xi,yi: integer;
      c,i: integer;
begin
  Resolve:=false;
 
  for xc:=1 to 9 do
    for yc:=1 to 9 do
      if( s[xc,yc,0]=0 )then
       begin
         { resolve this }
         c:=s[xc,yc,0];
 
         { x-axis }
         for i:=1 to 9 do
           s[xc,yc, s[i,yc,0]]:=0;
 
         { y-axis }
         for i:=1 to 9 do
           s[xc,yc, s[xc,i,0]]:=0;
 
         { do square }
         xs:=(xc-1) div 3;
         ys:=(yc-1) div 3;
 
         for xi:=1 to 3 do
           for yi:=1 to 3 do
             s[xc,yc, s[3*xs+xi,3*ys+yi,0]] := 0;
 
         { resolve of simply test }
         s[xc,yc,0]:=GetSingle(xc,yc);
 
         { simply test without result try cross test }
         if( s[xc,yc,0]=0 )then
             s[xc,yc,0]:=KrossTest(xc,yc);
 
         Kurzor(xc,yc,COLBG);
 
         { if find resolve }
         if( s[xc,yc,0]<>c )then
             Resolve:=true;
       end;
end;
 
 
BEGIN
  TextBackGround(COLBG);
  ClrScr;
 
  ViewSudoku;
  ViewHelp;
  Load;
 
  x:=1; y:=1;
 
  repeat
    { move kurzor }
    Kurzor(x,y,COLBG);
 
    { get char from keyb }
    ch:=readkey;
 
    if( ch=#0 )then
        ch:=readkey;
 
    { F1, F2, F3, F5, F8 keys }
    if( ch=#59 ) then Help;
    if( ch=#60 ) then Save;
    if( ch=#61 ) then Load;
    if( ch=#63 ) then while (Resolve) do;
    if( ch=#66 ) then Clear;
 
    { space as zero }
    if( ch=' ' )then ch:='0';
 
    { insert number }
    if( ch in ['0'..'9']) then
      begin
        s[x,y,0]:=ord(ch) - ord('0');
        Kurzor(x,y,COLBG);
        x:=x+1;
      end;
 
    { arrows }
    if( ch=#75 ) then x:=x-1;
    if( ch=#77 ) then x:=x+1;
    if( ch=#72 ) then y:=y-1;
    if( ch=#80 ) then y:=y+1;
 
    { home - end }
    if( ch=#71 ) then x:=1;
    if( ch=#79 ) then x:=9;
 
    { pageup - pagedown }
    if( ch=#73 ) then y:=1;
    if( ch=#81 ) then y:=9;
 
    { check position }
    if( x<1 ) then x:=9;
    if( x>9 ) then begin x:=1; y:=y+1; end;
    if( y<1 ) then y:=9;
    if( y>9 ) then y:=1;
 
  until (ch=#27);	{ ESC }
 
  { for safe }
  Save;
END.