Обход конем шахматной доски 8х8

06.05.png

Существует много способов обойти доску конем, задача представленная здесь использует правило Варнсдорфа которое гласит что "На каждом ходу надо ставить коня на такое поле, из которого можно совершить наименьшее число ходов на еще не пройденные поля. Если таких полей несколько, разрешается выбирать любое из них."

Подробнее о методе смотрите здесь.

unit Unit1; 
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    PaintBox1: TPaintBox;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end; 
 
var i,j,k,l,s,z :integer;
 
var A_x,A_y,A_nx,A_ny,A_kol :integer;  //А - начальная позиция коня 
var B_x,B_y,B_nx,B_ny,B_kol :integer;  //В - возможная позиция коня (с помощью В мы будим делать всевозможные ходы из А и проверять их на количество возможных ходов из них, 
                                             позиция из которой будит минимальное количество ходов станет позицией А то есть мы перейдем на эту позицию и занесем её в массив посещенных 
                                             клеток)
 
var R_x,R_y :integer;
var str :String;
 
var 
    mov1: Array[1..8] of integer;//-
                                 // |-D алгоритм   
    mov2: Array[1..8] of integer;//-
 
    mov3: Array[0..1000,0..1000] of integer; //массив для уже пройденных ходов
 
  Form1: TForm1; 
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
//---------------Отрисовка доски-----------------------------------
 for i:=1 to 4 do
 begin
 
for j:=1 to 4 do
  begin
 
  PaintBox1.Canvas.Brush.Color:=clBlack;
 PaintBox1.Canvas.Rectangle(0+l,0+k,80+l,80+k);
 l:=l+80;
  PaintBox1.Canvas.Brush.Color:=clWhite;
 PaintBox1.Canvas.Rectangle(0+l,0+k,80+l,80+k);
 l:=l+80;
  end;
  l:=0;
  k:=k+80;
 for j:=1 to 4 do
  begin
 
 PaintBox1.Canvas.Brush.Color:=clWhite;
 PaintBox1.Canvas.Rectangle(0+l,0+k,80+l,80+k);
 l:=l+80;
 PaintBox1.Canvas.Brush.Color:=clBlack;
 PaintBox1.Canvas.Rectangle(0+l,0+k,80+l,80+k);
 l:=l+80;
  end;
  l:=0;
  k:=k+80;
 end;
//------------------------------D алгоритм -------В него заносятся всевозможные ходы коня из клетки их всего 8 но в определенном порядке При наличии нескольких допустимых(одинаковых) ходов условимся выбирать тот из них, который сформирован с помощью самого левого столбца D для разрешения  массив 1 это координаты по Х массив 2 по Y----------------------------
 
  mov1[1]:=2;  mov1[2]:=1;  mov1[3]:=2; mov1[4]:=-2; mov1[5]:=-1; mov1[6]:=-1; mov1[7]:=1; mov1[8]:=-2
  mov2[1]:=-1; mov2[2]:=-2; mov2[3]:=1; mov2[4]:=1;  mov2[5]:=-2; mov2[6]:=2;  mov2[7]:=2; mov2[8]:=-1;
 
//---------------------------------------------------------------------------
  l:=0;k:=1;i:=0;j:=1; //переобозначение после отрисовки доски (чтобы не вводить новые переменные)
 
    A_kol:=8; B_kol:=8;//количество возможных ходов в начале обозначается максимальным числом ходов коня из клетки то есть 8
 
    A_x:=40; A_y:=40; // координаты начальной клетки
 
    mov3[A_x][A_y]:=1; //заносим начальное положение коня кок посещенное
 
//--------------------------Обозначение положения коня на доске и пройденные им клетки--------------------------------------------------
PaintBox1.Canvas.Brush.Color:=clred;
PaintBox1.Canvas.Ellipse(A_x-4,A_y-4,A_x+4,A_y+4);
str:= IntToStr(k);
PaintBox1.Canvas.TextOut(A_x+6,A_y+6,str);
PaintBox1.Canvas.Brush.Color:=clwhite;
 
//----------------------------------------------------------------------------
  Timer1.Enabled:=True
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 
 k:=k+1;
   for i:=1 to 63 do //цикл определяющий общее количество необходимых ходов для обхода доски 8*8=64 всего 64 но -1(начальное положение) всего 63
 begin
     for s:=1 to 8 do //цикл проверяющий на возможный ход коня  из А
  begin
       if (A_x+mov1[s]*80>= 40)and(A_y+mov2[s]*80 >= 40)and(A_x+mov1[s]*80 <= 600)and(A_y+mov2[s]*80 <= 600)and(mov3[A_x+mov1[s]*80][A_y+mov2[s]*80]=0) //число не должно выходить за рамки доски и присутствовать в массиве посещенных ходов.
 
       then
         begin
         A_kol:= 0;
         A_nx := A_x + mov1[s]*80;
         A_ny := A_y + mov2[s]*80;
 
  for z:=1 to 8 do //цикл подсчитывающий количество возможных ходов из предполагаемого хода
          begin
            if (A_nx+mov1[z]*80>=40)and(A_ny+mov2[z]*80>=40)and(A_nx+mov1[z]*80<=600)and(A_ny+mov2[z]*80<=600)and(mov3[A_nx+mov1[z]*80][A_ny+mov2[z]*80]=0)
            then
 
              A_kol:=A_kol+1;
 
          end;
 
         end;
 
       if B_kol>A_kol then 
         begin
         B_x:=A_nx;
         B_y:=A_ny;
         B_kol:=A_kol;
        end;
 
  end;
 
     {
     PaintBox1.Canvas.pen.Color:=clred;
     PaintBox1.Canvas.Pen.Width:=5;
     PaintBox1.Canvas.MoveTo(A_x,A_y);
     PaintBox1.Canvas.LineTo(B_x,B_y);
     PaintBox1.Canvas.Brush.Color:=clwhite;
     }
A_x:=B_x;
A_y:=B_y;
A_nx:=0;
A_ny:=0;
A_kol:=8;
B_kol:=8;
mov3[A_x][A_y]:=1;
 
//--------------------------Обозначение положения коня на доске и пройденные им клетки--------------------------------------------------
PaintBox1.Canvas.Brush.Color:=clred;
PaintBox1.Canvas.Ellipse(A_x-4,A_y-4,A_x+4,A_y+4);
 
str:= IntToStr(k);
PaintBox1.Canvas.TextOut(A_x+6,A_y+6,str);
PaintBox1.Canvas.Brush.Color:=clwhite;
 
end;
   j:=j+1;
    if j=64 then
        begin
         Timer1.Enabled:=False;
        end;
 
end;
 
end.

Ключевые слова: 
Конь, шахматная доска, Delphi
ВложениеРазмер
Konj.rar2.57 Мб