📄 gameboard.pas
字号:
unit GameBoard;
interface
uses
Dialogs, ComCtrls;
const
BoardWidth = 15;
BoardHeight = 15;
// 边的类型的个数:11
EdgeTypeNum = 11;
MaxScore = 900000;
type
TChessType = (Edge, None, Black, White);
TBoard = array[0..BoardWidth + 1, 0..BoardHeight + 1] of TChessType;
TDirection = (Left, UpperLeft, Up, UpperRight);
TEnum = (eNo, eDead2, eLive2LooseEdge, eLive2Loose, eLive2Packed, eDead3, eLive3LooseEdge, eLive3Loose, eLive3Packed, eDead4, eLive4, eFive);
const
No = shortint(eNo);
Dead2 = shortint(eDead2);
Live2Loose = shortint(eLive2Loose);
Live2LooseEdge = shortint(eLive2LooseEdge);
Live2Packed = shortint(eLive2Packed);
Dead3 = shortint(eDead3);
Live3LooseEdge = shortint(eLive3LooseEdge);
Live3Loose = shortint(eLive3Loose);
Live3Packed = shortint(eLive3Packed);
Dead4 = shortint(eDead4);
Live4 = shortint(eLive4);
Five = shortint(eFive);
type // Dead4和 Live4Loose 合并为 Dead4
// ( No, Dead1, Live1, Dead2, Live2Loose, Live2Packed, Dead3, Live3Loose, Live3Packed, Dead4, Live4, Five);
// 为负代表端点
TEdgeEnum = -Five..Five;
TEdgeImage = array[1..5] of TEdgeEnum;
TEdgeModel = record
EdgeImage: byte;
Edgetypes: TEdgeImage;
end;
TEdgeEnumPos = record
Edge: TEdgeEnum;
end;
TEdgeType = record
case integer of
0: (int: integer);
1: (TypeNum: array[Left..UpperRight] of TEdgeEnumPos);
end;
TEdgeTypeBoard = array[1..BoardWidth, 1..BoardHeight] of TEdgeType;
{ TPoint = record
Score: real;
Score1: real;
case integer of
0: (int: integer);
1: (dx, dy: smallInt);
end;
}
TEdgeBoard = array[Black..White] of TEdgeTypeBoard;
TGameBoard = class
private
Board: TBoard;
{一共有10种 '边’:
活1,死1,两种活2,死2,两种活3,死3,两种活4
}
EdgeBoard: TEdgeBoard;
public
constructor Create;
destructor Destroy; override;
procedure Reset;
function GetXY(x, y: integer): TChessType; // 得到棋盘x, y处的值
function GetTypeString(TypeOfChess: TChessType): string;
function WinPlace(x, y: integer; TypeOfChess: TChessType; var Score: real): boolean;
function GetType(TypeChess: TChessType; x, y: integer; dir: TDirection; var Pos: integer): TEdgeEnum;
function GetEdgeImage(image: byte; Nurmber: integer; Closed: boolean): TEdgeImage;
procedure UpdateDir(dir: TDirection; x, y: integer);
procedure UpdateEdgeBoard(x, y: integer);
function SetXY(x, y: integer; TypeOfChess: TChessType): boolean; // 设置棋盘x, y处的值
procedure GetNextStep(TypeOfChess: TChessType; var x, y: integer);
procedure GetNextStepWithDepth(TypeOfChess: TChessType; var x, y: integer; depth: integer); // 递归产生下一步
end;
const
ModelLimit: array[0..4] of integer = (0, 5, 10, 10, 5);
Live2Model: array[1..5] of TEdgeModel = (
(EdgeImage: $10 {10000}; EdgeTypes: (Live2Packed, Live2Packed, Live2Loose, Live2LooseEdge, Live2LooseEdge)),
(EdgeImage: $08 {01000}; EdgeTypes: (Live2Packed, Live2Packed, Live2Packed, Live2Loose, Live2LooseEdge)),
(EdgeImage: $04 {00100}; EdgeTypes: (Live2Loose, Live2Packed, Live2Packed, Live2Packed, Live2Loose)),
(EdgeImage: $02 {00010}; EdgeTypes: (Live2LooseEdge, Live2Loose, Live2Packed, Live2Packed, Live2Packed)),
(EdgeImage: $01 {00001}; EdgeTypes: (Live2LooseEdge, Live2LooseEdge, Live2Loose, Live2Packed, Live2Packed))
);
Live3Model: array[1..10] of TEdgeModel = (
(EdgeImage: $0C {01100}; EdgeTypes: (Live3Packed, Live3Packed, Live3Packed, Live3Packed, Live3Loose)),
(EdgeImage: $0A {01010}; EdgeTypes: (Live3Loose, Live3Packed, Live3Packed, Live3Packed, Live3Loose)),
(EdgeImage: $18 {11000}; EdgeTypes: (Live3Packed, Live3Packed, Live3Packed, Live3Loose, Live3LooseEdge)),
(EdgeImage: $14 {10100}; EdgeTypes: (Live3Packed, Live3Packed, Live3Packed, Live3Loose, Live3LooseEdge)),
(EdgeImage: $12 {10010}; EdgeTypes: (Live3Loose, Live3Loose, Live3Loose, Live3Loose, Live3LooseEdge)),
(EdgeImage: $11 {10001}; EdgeTypes: (Live3LooseEdge, Live3LooseEdge, Live3LooseEdge, Live3LooseEdge, Live3LooseEdge)),
(EdgeImage: $06 {00110}; EdgeTypes: (Live3Loose, Live3Packed, Live3Packed, Live3Packed, Live3Packed)),
(EdgeImage: $03 {00011}; EdgeTypes: (Live3LooseEdge, Live3Loose, Live3Packed, Live3Packed, Live3Packed)),
(EdgeImage: $05 {00101}; EdgeTypes: (Live3LooseEdge, Live3Loose, Live3Packed, Live3Packed, Live3Packed)),
(EdgeImage: $09 {01001}; EdgeTypes: (Live3LooseEdge, Live3Loose, Live3Loose, Live3Loose, Live3Loose))
);
Live4Model: array[1..10] of TEdgeModel = (
(EdgeImage: $0E {01110}; EdgeTypes: (Live4, Live4, Live4, Live4, Live4)),
(EdgeImage: $16 {10110}; EdgeTypes: (Live4, Live4, Live4, Live4, Dead4)),
(EdgeImage: $15 {10101}; EdgeTypes: (Dead4, Dead4, Dead4, Dead4, Dead4)),
(EdgeImage: $1A {11010}; EdgeTypes: (Live4, Live4, Live4, Live4, Dead4)),
(EdgeImage: $19 {11001}; EdgeTypes: (Dead4, Dead4, Dead4, Dead4, Dead4)),
(EdgeImage: $1C {11100}; EdgeTypes: (Live4, Live4, Live4, Live4, Dead4)),
(EdgeImage: $0D {01101}; EdgeTypes: (Dead4, Live4, Live4, Live4, Live4)),
(EdgeImage: $0B {01011}; EdgeTypes: (Dead4, Live4, Live4, Live4, Live4)),
(EdgeImage: $13 {10011}; EdgeTypes: (Dead4, Dead4, Dead4, Dead4, Dead4)),
(EdgeImage: $07 {00111}; EdgeTypes: (Dead4, Live4, Live4, Live4, Live4))
);
Live5Model: array[1..5] of TEdgeModel = (
(EdgeImage: $0F {01111}; EdgeTypes: (Five, Five, Five, Five, Five)),
(EdgeImage: $17 {10111}; EdgeTypes: (Five, Five, Five, Five, Five)),
(EdgeImage: $1B {11011}; EdgeTypes: (Five, Five, Five, Five, Five)),
(EdgeImage: $1D {11101}; EdgeTypes: (Five, Five, Five, Five, Five)),
(EdgeImage: $1E {11110}; EdgeTypes: (Five, Five, Five, Five, Five))
);
var
// ConstScore : array [ No .. Five ] of real = (0, 2, 40, 90, 95, 30, 120, 175, 185, 190, 1000, 9000);//(0, 1, 40, 90, 95, 50, 220, 275, 300, 320, 1000, 9000);
ConstScore: array[No..Five] of real = (0, 1, 5, 8, 10, 6, 170, 255, 285, 290, 3000, 8000);
Win: boolean = False;
implementation
uses MainForm, SysUtils;
function InBound(x, Min, Max: integer): boolean;
begin
Result := (x >= Min) and (x <= Max);
end;
function ReverseType(TypeOfChess: TChessType): TChessType;
begin
Result := Black;
if TypeOfChess = Black then
Result := White;
if ((TypeOfChess = None) or (TypeOfChess = Edge)) then
Showmessage(' Type Error! ');
end;
{
function GetLevel(theType : TEdgeEnum): integer;
begin
Result := 1;
if theType >= Live2Loose then
Result := 2;
if theType >= Live3Loose then
Result := 3;
if theType >= Dead4 then
Result := 4;
if theType = Five then
Result := 5;
end;
}
procedure GetDirDelta(Dir: TDirection; var deltaX, deltaY: integer);
begin
case Dir of
Left: begin
deltaX := 1;
deltaY := 0;
end;
UpperLeft: begin
deltaX := 1;
deltaY := 1;
end;
Up: begin
deltaX := 0;
deltaY := 1;
end;
UpperRight: begin
deltaX := -1;
deltaY := 1;
end;
end; // case
end;
constructor TGameBoard.Create;
begin
inherited Create;
Reset;
end;
destructor TGameBoard.Destroy;
begin
inherited Destroy;
end;
// 重置棋盘
procedure TGameBoard.Reset;
var i, j: integer;
begin
for i := 0 to BoardWidth + 1 do
for j := 0 to BoardHeight + 1 do
Board[i, j] := Edge;
for i := 1 to BoardWidth do
for j := 1 to BoardHeight do
Board[i, j] := None;
for i := 1 to BoardWidth do
for j := 1 to BoardHeight do
begin
EdgeBoard[Black][i, j].int := 0;
EdgeBoard[White][i, j].int := 0;
end;
end;
function TGameBoard.GetTypeString(TypeOfChess: TChessType): string;
begin
if TypeOfChess = Black then
Result := 'Black'
else
Result := 'White';
end;
// 得到棋盘x, y处的值
function TGameBoard.GetXY(x, y: integer): TChessType;
begin
Result := None;
if (inbound(x, 1, BoardWidth) and inBound(y, 1, BoardHeight)) then
Result := Board[x, y];
end;
function TGameBoard.GetType(TypeChess: TChessType; x, y: integer; dir: TDirection; var Pos: integer): TEdgeEnum;
begin
Result := EdgeBoard[TypeChess][x, y].TypeNum[dir].Edge;
end;
function TGameBoard.GetEdgeImage(image: byte; Nurmber: integer; Closed: boolean): TEdgeImage;
var NextType: TEdgeEnum;
i: integer;
Mach: boolean;
begin
Mach := False;
if Closed then
begin
NextType := No;
case Nurmber of
1: NextType := Dead2;
2: NextType := Dead3;
3: NextType := Dead4;
4: NextType := Five;
end; // case
for i := 1 to 5 do
Result[i] := NextType;
exit;
end;
case Nurmber of
1:
begin
for i := 1 to ModelLimit[1] do
begin
if Live2Model[i].EdgeImage = image then
begin
Result := Live2Model[i].Edgetypes;
Mach := True;
break;
end;
end;
end;
2:
begin
for i := 1 to ModelLimit[2] do
if Live3Model[i].EdgeImage = image then
begin
Result := Live3Model[i].Edgetypes;
Mach := True;
break;
end;
end;
3:
begin
for i := 1 to ModelLimit[3] do
if Live4Model[i].EdgeImage = image then
begin
Result := Live4Model[i].Edgetypes;
Mach := True;
break;
end;
end;
4:
begin
Mach := True;
for i := 1 to 5 do
begin
Result[i] := Five;
end;
end;
end; // case
if not Mach then
Form1.StatusBar1.Panels[4].Text := 'Mach error!' + inttostr(integer(Nurmber));
end;
procedure TGameBoard.UpdateDir(dir: TDirection; x, y: integer);
const TypeArrayMax = 9;
var dirx, diry: integer;
i, j: integer;
image: byte;
Sum: integer;
NoNeed: boolean;
ChessType, OtherType: TChessType;
ResultImage: TEdgeImage;
TypeImage: array[-TypeArrayMax..TypeArrayMax] of TChessType;
begin
GetDirDelta(dir, dirx, diry);
for i := -TypeArrayMax to TypeArrayMax do
TypeImage[i] := Edge;
for i := 0 to TypeArrayMax do
if Board[x + i * dirx, y + i * diry] <> Edge then
TypeImage[i] := Board[x + i * dirx, y + i * diry]
else
break;
for i := -1 downto -TypeArrayMax do
if Board[x + i * dirx, y + i * diry] <> Edge then
TypeImage[i] := Board[x + i * dirx, y + i * diry]
else
break;
// Elimate Older
for ChessType := Black to White do
begin
for i := 0 to 5 do
if TypeImage[i] = Edge then
break
else
begin
EdgeBoard[ChessType][x + i * dirx, y + i * diry].TypeNum[dir].Edge := No;
end;
for i := -1 downto -5 do
if TypeImage[i] = Edge then
break
else
begin
EdgeBoard[ChessType][x + i * dirx, y + i * diry].TypeNum[dir].Edge := No;
end;
end;
// Try to Update
for i := -8 to 4 do
begin
if (TypeImage[i] = Edge) then continue;
for ChessType := Black to White do
begin
Sum := 0;
image := 0;
NoNeed := False;
OtherType := ReverseType(ChessType);
for j := i to i + 4 do
begin
if TypeImage[j] = ChessType then
begin
inc(Sum);
image := image or (1 shl (4 - (j - i)));
end else
if ((TypeImage[j] = OtherType) or (TypeImage[j] = Edge)) then
begin
NoNeed := True;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -