16. Der Sudoku-Assistent
Es wird wieder einmal Zeit für ein praktisches Beispiel. Als Anwendung für den Datentyp Array wollen wir ein Programm schreiben, das uns beim Lösen von Sudokus hilft.
Mit jedem Klick auf die Taste "Lösen" sollen der Reihe nach alle Felder geprüft werden und diejenigen, deren Lösung eindeutig ist, eingetragen werden.
Die Zahlen des Sudokus werden intern in einem zweidimensionalen Array x gehalten. Für leere Felder enthält das Array eine Null.
Ein zweites Array vorhanden dient dazu festzuhalten, welche Zahlen in der aktuellen Zeile, der aktuellen Spalte und dem aktuellen Sektor bereits vorhanden sind.
Die beiden Arrays werden im Interface-Teil deklariert. im Implementation-Teil schreiben wir zwei Prozeduren, die die Zahlen aus dem Array x in das Stringgrid kopieren und umgekehrt.
unit Unit1; interface ... var Form1: TForm1; x: array[1..9,1..9] of integer; vorhanden: array[1..9] of boolean; |
procedure anzeigen;
var z,s:integer;
begin
with Form1.StringGrid1 do
for z:=1 to 10 do
for s:= 1 to 10 do
if x[z,s]>0 then
Cells[s-1,z-1]:=IntToStr(x[z,s])
else
Cells[s-1,z-1]:= '';
end; {procedure}
|
procedure einlesen;
var z,s:integer;
begin
With Form1.StringGrid1 do
for z:=1 to 10 do
for s:= 1 to 10 do
if Trim(Cells[s-1,z-1])<>'' then
x[z,s]:=StrToInt(Cells[s-1,z-1])
else
x[z,s]:= 0;
end; {procedure}
|
procedure TForm1.BtnLoesenClick(Sender: TObject);
var z,s,i,j,i0,j0,anzahl_fehlt,ziffer:integer;
begin
einlesen;
for z:=1 to 9 do
for s:= 1 to 9 do
if x[z,s]=0 then
begin
for ziffer:=1 to 9 do vorhanden[ziffer]:= false;
{zeile prüfen}
for i:=1 to 9 do
if x[i,s]>0 then vorhanden[x[i,s]]:= true;
{spalte prüfen}
for j:=1 to 9 do
if x[z,j]>0 then vorhanden[x[z,j]]:= true;
{sektor prüfen}
i0:= 3*((z-1) div 3)+1;
j0:= 3*((s-1) div 3)+1;
for i:= i0 to i0+2 do
for j:= j0 to j0+2 do
if x[i,j]>0 then vorhanden[x[i,j]]:= true;
{eindeutige Lösung?}
anzahl_fehlt:= 0;
for ziffer:=1 to 9 do
if vorhanden[ziffer]=false then
begin
Inc(anzahl_fehlt);
x[z,s]:= ziffer;
end;
if anzahl_fehlt<>1 then x[z,s]:= 0;
end; {if}
anzeigen;
end; {procedure}
|
Um die Trennlinien zwischen den Sektoren zu zeichnen, klinken wir uns in das DrawCell-Ereignis des Stringrids ein
und zeichnen am rechten Rand der dritten und sechsten Spalte und am unteren Rand der dritten und sechsten Zeile
eine Linie mit der Strichstärke 2.
procedure TForm1.StringGrid1DrawCell(Sender:TObject;
ACol,ARow:Integer; Rect:TRect; State:TGridDrawState);
begin
with (sender as TStringGrid).Canvas do
begin
Pen.Color:= clBlack;
Pen.Width:= 2;
Pen.Style:= psSolid;
if (Arow = 2) or (Arow=5) then
begin
MoveTo( rect.left-1, rect.bottom );
Lineto( rect.right, rect.bottom );
end;
if (Acol=2) or (Acol=5) then
begin
MoveTo( rect.right, rect.top );
Lineto( rect.right, rect.bottom );
end;
end;
end; {procedure}
|
Aufgaben :
» LösungTäglich neue Sudokus gibt es unter sudoku.zeit.de |
![]() |
|
|
© 2008 : Bernd Schultheiss
|
||
Einführung in das Programmieren mit DELPHI

