📄 mainunit.pas
字号:
unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, jpeg, ExtCtrls, StdCtrls, Menus,thongtin;
Const
SIZE_X=9;
SIZE_Y=10;
BOARD_SIZE=SIZE_X*SIZE_Y;
MOVE_STACK=500;
HIST_STACK=50;
EMPTY=0;
RED=2;
DARK=1;
PAWN=1;
BISHOP=2;
ELEPHANT=3;
KNIGHT=4;
CANNON=5;
ROOK=6;
KING=7;
INFINITY=20000;
NORMAL=0;
SELECT=1;
NewPiece:Array[1..BOARD_SIZE] of byte=
(6,4,3,2,7,2,3,4,6,
0,0,0,0,0,0,0,0,0,
0,5,0,0,0,0,0,5,0,
1,0,1,0,1,0,1,0,1,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
1,0,1,0,1,0,1,0,1,
0,5,0,0,0,0,0,5,0,
0,0,0,0,0,0,0,0,0,
6,4,3,2,7,2,3,4,6);
NewPieceColor:Array[1..BOARD_SIZE] of byte=
(1,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,
0,1,0,0,0,0,0,1,0,
1,0,1,0,1,0,1,0,1,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
2,0,2,0,2,0,2,0,2,
0,2,0,0,0,0,0,2,0,
0,0,0,0,0,0,0,0,0,
2,2,2,2,2,2,2,2,2);
{ Khả năng di chuyển của từng quân}
Offset: Array[1..7, 1..8] of shortint =
( (-1, 1,13, 0, 0, 0, 0, 0), { PAWN (for DARK side only) }
(-12,-14,12,14,0,0,0,0), { BISHOP }
(-28,-24,24,28, 0, 0, 0, 0 ), { ELEPHAN }
(-11,-15,-25,-27,11,15,25,27), { KNIGHT }
(-1, 1,-13,13, 0, 0, 0, 0), { CANNON }
(-1, 1,-13,13, 0, 0, 0, 0), { ROOK }
(-1, 1,-13,13, 0, 0, 0, 0)); { KING }
{Khử trường hợp quân chạy ra khởi bàn cờ }
Mailbox182: array[1..182] of shortint =
(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,
-1,-1,10,11,12,13,14,15,16,17,18,-1,-1,
-1,-1,19,20,21,22,23,24,25,26,27,-1,-1,
-1,-1,28,29,30,31,32,33,34,35,36,-1,-1,
-1,-1,37,38,39,40,41,42,43,44,45,-1,-1,
-1,-1,46,47,48,49,50,51,52,53,54,-1,-1,
-1,-1,55,56,57,58,59,60,61,62,63,-1,-1,
-1,-1,64,65,66,67,68,69,70,71,72,-1,-1,
-1,-1,73,74,75,76,77,78,79,80,81,-1,-1,
-1,-1,82,83,84,85,86,87,88,89,90,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1);
{ Bẳng vị trí thực của quân trên bàn }
Mailbox90: array[1..90] of byte =
(29, 30, 31, 32, 33, 34, 35, 36, 37,
42, 43, 44, 45, 46, 47, 48, 49, 50,
55, 56, 57, 58, 59, 60, 61, 62, 63,
68, 69, 70, 71, 72, 73, 74, 75, 76,
81, 82, 83, 84, 85, 86, 87, 88, 89,
94, 95, 96, 97, 98, 99,100,101,102,
107,108,109,110,111,112,113,114,115,
120,121,122,123,124,125,126,127,128,
133,134,135,136,137,138,139,140,141,
146,147,148,149,150,151,152,153,154);
{ Mảng liểm tra vị téi hợp lệ của từng quân cờ }
LegalPosition: array[1..90] of byte =
(1, 1, 5, 3, 3, 3, 5, 1, 1,
1, 1, 1, 3, 3, 3, 1, 1, 1,
5, 1, 1, 3, 7, 3, 1, 1, 5,
1, 1, 1, 1, 1, 1, 1, 1, 1,
9, 1,13, 1, 9, 1,13, 1, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9);
MaskPiece: array[1..7] of byte = (8, 2, 4, 1, 1, 1, 2); { Kết họp để kiểm tra xem quân đi có đúng không }
KnightCheck: array[1..8] of shortint = (1,-1,-9,-9,-1,1,9,9);
ElephantCheck: array[1..8] of shortint = (-10,-8,8,10,0,0,0,0);
KingPalace: array[1..9] of byte = (4,5,6,13,14,15,22,23,24);
materialnumber: array[1..2, 1..7] of byte = ((5, 2, 2, 2, 2, 2, 1), (5, 2, 2, 2, 2, 2, 1));
type
Move=record
Source,Dest:byte;
end;
Gen_Rec=record
m:Move;
end;
Hist_rec=record
m:Move;
Capture:byte;
end;
ImagePointer=^TImage;
TMainForm = class(TForm)
imgBoard: TImage;
imgXeRed1: TImage;
imgMaRed1: TImage;
imgSiRed1: TImage;
imgTuongRed: TImage;
imgTinhRed2: TImage;
imgMaRed2: TImage;
imgXeRed2: TImage;
imgTinhRed1: TImage;
imgTotRed1: TImage;
imgPhaoRed1: TImage;
imgPhaoRed2: TImage;
imgTotRed2: TImage;
imgTotRed3: TImage;
imgTotRed4: TImage;
imgTotRed5: TImage;
imgSiRed2: TImage;
imgSiDen1: TImage;
imgSiDen2: TImage;
imgPhaoDen1: TImage;
imgPhaoDen2: TImage;
imgTuongDen: TImage;
imgXeDen1: TImage;
imgMaDen1: TImage;
imgXeDen2: TImage;
imgmaDen2: TImage;
imgTinhDen1: TImage;
imgTinhDen2: TImage;
imgTotDen2: TImage;
imgTotDen1: TImage;
imgTotDen3: TImage;
imgTotDen4: TImage;
imgTotDen5: TImage;
MainMenu1: TMainMenu;
File1: TMenuItem;
Btuchi1: TMenuItem;
hot1: TMenuItem;
rnh1: TMenuItem;
Level11: TMenuItem;
Level21: TMenuItem;
Level31: TMenuItem;
hngtintcgi1: TMenuItem;
M1: TMenuItem;
Ccthchikhng1: TMenuItem;
rungcuc1: TMenuItem;
VitNam1: TMenuItem;
Hard1: TMenuItem;
Hardest1: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure imgRedPieceMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure imgRedPieceMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure imgRedPieceMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure MainFormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
Procedure GetInBoardCoor(P1:TPoint;var P2:TPoint;var OK:boolean);
procedure hot1Click(Sender: TObject);
procedure Btuchi1Click(Sender: TObject);
procedure Level11Click(Sender: TObject);
procedure Level21Click(Sender: TObject);
procedure Level31Click(Sender: TObject);
procedure hngtintcgi1Click(Sender: TObject);
procedure imgTuongRedClick(Sender: TObject);
procedure M1Click(Sender: TObject);
procedure Hard1Click(Sender: TObject);
procedure Hardest1Click(Sender: TObject);
private
Board_Left,Board_Top:integer;
CrossPiece_Size:TPoint;
FirstPiece_Coor:TPoint;
OrinPiece_Coor:TPoint;
OrinInBoard_Coor:TPoint;
Piece_Pointer:array[1..10,1..9] of ImagePointer;
Function NumberPiecesBetween(Source,Dest:TPoint):byte;
Function KingFace(Source,Dest:Integer):Boolean;
Function CheckHumanMove(Source,Dest:TPoint):Boolean;
Function Eval:Integer;
Function AlphaBeta(Alpha,Beta:Integer;Depth:byte):integer;
Procedure ComputerThink;
Procedure NewGame;
{ Private declarations }
public
{ Public declarations }
end;
var
Piece:Array[1..BOARD_SIZE] of byte;
PieceColor:Array[1..BOARD_SIZE] of byte;
Ply,Side,XSide,ComputerSide:byte;
NewMove:move;
Gen_Dat:Array[0..MOVE_STACK] of Gen_Rec;
Gen_Begin,Gen_End:Array[0..HIST_STACK] of integer;
Hdp:Integer;
EvalCount:Longint;
MainForm: TMainForm;
RedPieceMouseDown:boolean=false;
EnableHumanMove:boolean=true;
RedMouseX,RedMouseY:integer;
MAX_FLY:byte=1;
HumanGo:boolean=true;
ComputerThinking:boolean;
implementation
Function TMainForm.NumberPiecesBetween(Source,Dest:TPoint):byte;
var i,k:byte;
begin
k:=0;
if dest.x=source.x then
begin
if dest.Y-source.y>=2 then
begin
for i:=source.Y+1 to dest.Y-1 do
if Piece[(i-1)*SIZE_X+source.X]<>0 then
k:=k+1
end
else
if source.Y-dest.y>=2 then
for i:=dest.Y+1 to source.Y-1 do
if Piece[(i-1)*SIZE_X+source.X]<>0 then
k:=k+1;
end
else
if dest.y=source.Y then
begin
if dest.X-source.x>=2 then
begin
for i:=source.X+1 to dest.X-1 do
if Piece[(source.Y-1)*SIZE_X+i]<>0 then
k:=k+1;
end
else
if source.X-dest.x>=2 then
for i:=dest.x+1 to source.X-1 do
if Piece[(source.Y-1)*SIZE_X+i]<>0 then k:=k+1;
end;
result:=k;
end;
procedure TMainForm.Btuchi1Click(Sender: TObject);
begin
NewGame;
end;
Function TMAinForm.CheckHumanMove(Source,Dest:TPoint):Boolean;
var RedPiece:byte;
i,k:byte;
d,s,h,tg:integer;
t:integer;
a,b:integer;
begin
Result:=false;
a:=(source.Y-1)*SIZE_X+source.X;
b:=(dest.Y-1)*SIZE_X+dest.x;
if KingFace(a,b) then exit;
if (PieceColor[a]=DARK) or (PieceColor[b]=RED) or
((Source.x=Dest.x) and (Source.y=Dest.y)) then exit;
RedPiece:=Piece[a];
if RedPiece in [CANNON,ROOK] then
begin
if (source.x<>dest.x) and (source.y<>dest.y) then exit;
Case RedPiece Of
CANNON:
begin
k:=NumberPiecesBetween(source,dest);
result:=((Piece[b]=0) and (k=0)) or ((Piece[b]<>0) and (k=1));
end;
ROOK:
result:=((source.x=dest.X) or (source.y=dest.Y)) and (NumberPiecesBetween(source,dest)=0);
end;
end
else
begin
tg:=Source.x+(source.y-1)*9;
s:=MailBox90[91-tg];
d:=MailBox90[91-(dest.x+(dest.y-1)*9)];
h:=d-s;
i:=1;
while (i<=8) and (Offset[RedPiece,i]<>h) do
i:=i+1;
if i<=8 then
case RedPiece of
KNIGHT:if Piece[tg-KnightCheck[i]]<>EMPTY then exit;
ELEPHANT:if Piece[tg-ElephantCheck[i]]<>EMPTY then exit;
end;
if i>8 then exit;
t:=MailBox182[d];
if (LegalPosition[t] and MaskPiece[RedPiece])=0 then exit;
Result:=true;
end;
end;
Procedure TMainform.GetInBoardCoor(P1:TPoint;var P2:TPoint;Var OK:boolean);
var k,l:integer;
a,b:integer;
s:string;
begin
k:=CrossPiece_Size.X div 3;
l:=CrossPiece_Size.Y div 3;
//P2.X:=-1;
//P2.Y:=-1;
a:=P1.X-FirstPiece_Coor.X;
b:=P1.Y-FirstPiece_Coor.Y;
OK:=true;
if (a>=-k) and (P1.X<=FirstPiece_Coor.X+8*CrossPiece_Size.X+k) and
(b>=-l) and (P1.Y<=FirstPiece_Coor.Y+9*CrossPiece_Size.Y+l) then
begin
P2.x:=(a div CrossPiece_Size.X) + 1;
P2.Y:=(b div CrossPiece_Size.Y) + 1;
if a>=0 then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -