Vezérek elhelyezése a sakktáblán ütközésmentesítő
algoritmussal
Írjunk programot, mely az ütközésmentesítő algoritmus
segítségével ütésmentesen elhelyez 8 vezért a sakktáblán. Nem kell az összes
megoldást megkeresnie, ha talál egy jó megoldást, a program álljon le.
A program tesztelése közben kiderült, hogy a kettős
cserét alkalmazó algoritmus gyakran nem tudja befejezni eredményesen a
keresést, ezért a hármas cserét használót alkalmaztam. A biztonság kedvéért a
maximális próbálgatási lehetőséget 1000-re állítottam be. Tesztelés közben 772
volt a maximális menetszám. Az alaphelyzet, amiből a keresés indul, a vezérek
egy véletlen elhelyezése a táblán. A futtatási környezet a véletlen mutációt
alkalmazó programhoz hasonló. A keresés a Start gombra indul, Alap gombbal újra
kereshetünk. A program kiírja a lépések számát és az ütközésszámot.
A program futási képe a keresés előtt:
Majd
a keresés befejeztével (futási idő 1 másodpercnél kisebb úgy, hogy a képernyő
minden lépésben frissül):
A
program listája:
unit UUtkVez;
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls, Grids;
Const Max=8;
type
TfmUtkVez = class(TForm)
lbUtkVez: TLabel;
btKilepes: TButton;
sgTabla: TStringGrid;
sgUtkVez: TStringGrid;
btStart: TButton;
edN: TEdit;
btAlap: TButton;
edUtOSz: TEdit;
Procedure Kepernyore;
Procedure Tablara;
Function UTSz(O: Word): Word;
Procedure Utkozesek;
procedure btKilepesClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure sgTablaDrawCell(Sender: TObject; Col, Row: Integer;
Rect: TRect; State: TGridDrawState);
procedure btStartClick(Sender: TObject);
procedure btAlapClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmUtkVez: TfmUtkVez;
ACol, ARow: Integer;
MaxMenet, Menet, UtOSz: Word;
T, UTT: Array[1..Max] Of Word;
implementation
{$R *.dfm}
procedure TfmUtkVez.btKilepesClick(Sender: TObject);
begin
Close;
end;
procedure TfmUtkVez.sgTablaDrawCell(Sender: TObject; Col, Row: Integer;
Rect: TRect; State: TGridDrawState);
begin
With sgTabla.Canvas.Brush Do
Begin
{rögzített cellák}
If gdFixed In State Then Color:=clWhite;
{kiválasztott cella}
If gdSelected In State Then Color:= clSilver;
{a táblázat belseje}
If Not((gdSelected In State) Or (gdFixed In State)) Then
Begin
Case Odd(Col) XOr Odd(Row) Of
False: Color:= clWindow;
True: Color:= clSilver;
End;
End;
sgTabla.Canvas.Font.Size:= 17;
End;
sgTabla.Canvas.TextRect(Rect,Rect.Left+12,
Rect.Top+1,sgTabla.Cells[Col,Row]);
If gdFocused In State Then sgTabla.Canvas.DrawFocusRect(Rect);
end;
procedure TfmUtkVez.FormCreate(Sender: TObject);
Var I: Word;
Ch: Char;
begin
With sgUtkVez Do
Begin
For I:= 1 To Max Do Cells[I,0]:= Chr(96+I);
End;
With sgTabla Do
Begin
ColWidths[9]:= 0;
RowHeights[9]:= 0;
For I:= 1 To 8 Do Cells[0,I]:= IntToStr(9-I);
For Ch:= 'a' To 'h' Do Cells[Ord(Ch)-96,0]:= Ch;
Col:= 9; Row:= 9;
End;
Randomize;
btAlapClick(Sender);
MaxMenet:= 1000;
end;
procedure TfmUtkVez.btAlapClick(Sender: TObject);
Var I, J, A, B, P: Word;
begin
For I:= 1 To Max Do T[I]:= I;
For I:= 1 To 1000 Do
Begin
A:= Random(Max)+1; B:= Random(Max)+1;
P:= T[A]; T[A]:= T[B]; T[B]:= P;
End;
With sgUtkVez Do
Begin
For I:= 1 To ColCount-1 Do For J:= 1 To RowCount-1 Do Cells[I,J]:= '';
RowCount:= 5;
End;
Menet:= 1;
Kepernyore;
Tablara;
Utkozesek;
edUtOSz.Text:= IntToStr(UTOSz);
end;
Procedure TfmUtkVez.Kepernyore;
Var I: Word;
Begin
With sgUtkVez Do
Begin
If RowCount-1<Menet Then RowCount:= Menet+1;
Cells[0,Menet]:= IntToStr(Menet)+'.';
For I:= 1 To Max Do Cells[I,Menet]:= IntToStr(T[I]);
End;
End;
Procedure TfmUtkVez.Tablara;
Var I, J: Word;
Begin
With sgTabla Do
Begin
For I:= 1 To ColCount-1 Do For J:= 1 To RowCount-1 Do Cells[I,J]:= '';
For I:= 1 To Max Do Cells[I,Max-T[I]+1]:= 'V';
End;
End;
Function TfmUtkVez.UTSz(O: Word): Word;
Var I, U: Word;
Begin
U:= 0;
For I:= 1 To Max Do If I<>O Then
If Abs(T[O]-T[I])=Abs(O-I) Then Inc(U);
UTSz:= U;
End;
Procedure TfmUtkVez.Utkozesek;
Var I: Word;
Begin
UTOSz:= 0; For I:= 1 To Max Do
Begin UTT[I]:= UTSz(I); Inc(UTOSz,UTT[I]) End;
End;
procedure TfmUtkVez.btStartClick(Sender: TObject);
Var X1, X2, X3, P, A, B: Word;
begin
Menet:= 1;
While (UTOSz>0) And (Menet<MaxMenet) Do
Begin
Inc(Menet); Utkozesek; A:= UTOSz;
X1:= 1; While UTT[X1]=0 Do X1:= Random(Max)+1;
X2:= Random(Max)+1; X3:= Random(Max)+1;
P:= T[X1]; T[X1]:= T[X2]; T[X2]:= T[X3]; T[X3]:= P;
Utkozesek; B:= UTOSz;
If B>A Then
Begin P:= T[X3]; T[X3]:= T[X2]; T[X2]:= T[X1]; T[X1]:= P End;
Utkozesek;
edN.Text:= IntToStr(Menet);
edUtOSz.Text:= IntToStr(UTOSz);
Tablara;
Kepernyore;
RePaint;
End;
end;
end.