📄 xqsystem.pas
字号:
///////////////////////////////////////////////////////////////////////////////
//
// XQStduio Source Code (http://www.qipaile.net/xqstudio)
//
// Copyright (c) 1998-2008, DONG Shiwei (董世伟 or 过河象)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1) Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2) Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// 3) Neither the name of the XQStudio nor the names of its contributors
// may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
//
// Note: Some characters of this file are Simplified Chinese characters
// encoded with GB2312/GB18030 standard
//
unit XQSystem;
//-------------------------------------------------------------------------
//
//.........................................................................
interface
//-------------------------------------------------------------------------
//
//.........................................................................
uses
Windows, SysUtils, Classes, Graphics, Forms, Controls, Menus,
StdCtrls, Dialogs, Buttons, Messages, ExtCtrls, ComCtrls, StdActns,
ActnList, ToolWin, ImgList, dDelphiS, XQDataT, XQPNode, XQRecLBX;
//-------------------------------------------------------------------------
// 类型定义
//.........................................................................
type
//-----------------------------------------------------------------------
// 定义象棋子类
//.......................................................................
dTXQZ = class
Index : dTINT32; // 棋子索引
Name : String[16]; // 棋子名称
Picture : TPicture; // 棋子图像
Arms : 1..7; // 兵种,依次为:车马象士将炮兵
XYStart : dTBYTE; // 棋子的开局位置(指原始位置)
XY : dTBYTE; // 棋子的位置(指棋子在棋盘上当前的位置)
public
constructor Create(iIdx:dTINT32; sName:String; pic:TPicture;
iArms:dTBYTE; bXYStart:dTBYTE);
end;
//-----------------------------------------------------------------------
// 定义象棋计时钟
//.......................................................................
dTXQCLOCK = class
Name : String[16];
public
constructor Create;
destructor Destroy; override;
end;
//-----------------------------------------------------------------------
// 定义象棋类
//.......................................................................
dTXiangQi = class
public
BoardImage : TImage; // 象棋盘图像
BoardXY : dTXQPXY; // 棋盘9x10个交叉点
QiziMoveImg : TImage; // 移动中棋子的图像
// 用来处理移动
Qizi : array [1..32] of dTXQZ; // 32个象棋子
QiziMove : dTXQZ; // 被拿起移动的棋子
MovePosFrom : TImage; // 最后移动过的棋子的位置
MovePosTo : TImage; // 用来显示走棋指示
Clock : dTXQCLOCK; // 计时钟
RedPlayer : String[32]; // 红方棋手
BlkPlayer : String[32]; // 黑方棋手
RecListBox : TListBox; // 棋谱记录列表框
VarListBox : TListBox; // 变着记录列表框
isAddVarStep: dTBoolean; // 是否是加入变着状态
RecMemo : TMemo; // 注解备注
isMemoEdit : dTBoolean;
PlayStepNo : dTINT32; // 当前行棋的总步数
DispStepNo : dTINT32; // 当前显示的屏幕是第几步棋
PlayNode : dTXQPlayNode; // 当前最后一步棋的节点
DispNode : dTXQPlayNode; // 当前棋盘显示的棋的节点
WhoPlay : dTWHOPLAY; // 轮到谁下
ReverseH : Boolean; // 左右对换标志
PlayRec : array [0..dCMaxRecNo] of dTXQPlayNode; // 行棋记录(棋谱)
PlayVar : array [0..dCMaxVarNo] of dTXQPlayNode;
PlayTree : dTXQPlayNode; // 对弈树
PlayRecHook : procedure;
RefreshHook : procedure;
//XQRecLBX : dTXQRecListBox;
private
function sGetFMTRecStr(PN: dTXQPlayNode): string;
public
constructor Create(imgBoard: TImage; imgXY: dTXQPXY; imgQZMove: TImage;
imgMovePosF, imgMovePosT:TImage; picQZ:dTXQZPIC;
lbxRec,lbxOther:TListBox; memRec: TMemo); overload;
constructor Create(imgBoard:TImage;imgXY:dTXQPXY;imgQZMove:TImage;
imgMovePosF, imgMovePosT:TImage;picQZ:dTXQZPIC;
lbxRec,lbxOther:TListBox;
memRec:TMemo;XQZXY:dTXQZXY); overload;
destructor Destroy; override;
procedure dStartMoveFromXY(XY:dTBYTE); // 从XY处开始移动棋子
procedure dStopMoveAtXY(XY:dTBYTE); // 移动停止到XY处
function isMoveToValid(XY:dTBYTE; var sPlayRec:String):dTBOOLEAN;
// 判断移动是否合乎规则, sPlayRec 记录本步棋谱
// function GetPlayRecStr(qzXY:dTXQZXY; WP:dTWhoPlay;
// XYf,XYt:dTBYTE):string;
procedure dUndoMove; // 取消移动
function iQiziIndexAtXY(XY:dTBYTE):dTINT32;// 取XY处的棋子索引号
function isPlayOneStepOK(XYf, XYt: dTBYTE): dTBOOLEAN;
// 判断从XYf移动到XYt是否合乎规则, 若合乎规则,真正执行
procedure dEnablePlayer(WP:dTWHOPLAY); overload; // 允许一方走棋
procedure dEnablePlayer(PN:dTXQPlayNode); overload;
procedure dDeleteOnePlayRec(bRefresh: Boolean=True); // 删除最后一步对局记录
procedure dDeleteOnePlayNode; // 删除刚刚走过的一步棋的节点
procedure dDeletePlayVar(PN:dTXQPlayNode);
procedure dRefreshBoard(ReStart:Boolean);
// 刷新当前棋局, Restart = True 表示从第0步开始(复位)
procedure dDispQiziAtRecNo(iRec: dTINT32); // 显示iRec步的棋局
procedure dMoveMemoToRecNo(iRec:dTINT32); // 将注解移入对局记录
procedure dLoadMemoFromRecNo(iRec:dTINT32); // 将记录中的注解显示出来
function isHighlightVarStepActive: Boolean;
procedure dMovePlayVarUp;
procedure dMovePlayVarDown;
procedure dDispVarStepAtRecNo(iRec:dTInt32);
procedure dLoadAllRecForPlayNode(PN:dTXQPlayNode);
procedure dAddPlayNodeIntoPlayRec(PN:dTXQPlayNode);
procedure dOnRecListBoxClick; // 响应单击棋局记录事件
procedure dOnVarListBoxDblClick;
procedure dOnRecMemoChange;
procedure dRefreshRecStr;
// procedure dReverseBoard; // 棋盘倒转180度
end;
const
dCXqzXY: dTXQZXY = (80,70,60,50,40,30,20,10,00,72,12,83,63,43,23,03,
09,19,29,39,49,59,69,79,89,17,77,06,26,46,66,86);
var
IsAutoPlaying: Boolean = False;
///////////////////////////////////////////////////////////////////////////
implementation
//-------------------------------------------------------------------------
//
//.........................................................................
constructor dTXQZ.Create(iIdx:dTINT32; sName:String; pic:TPicture;
iArms:dTBYTE; bXYStart:dTBYTE);
begin
Name := sName; Picture := pic; Arms := iArms; XYStart := bXYStart;
end;
//-------------------------------------------------------------------------
//
//.........................................................................
constructor dTXQCLOCK.Create;
begin
ShowMessage('XQCLOCK Create');
end;
destructor dTXQCLOCK.Destroy;
begin
end;
//-------------------------------------------------------------------------
// 象棋类的构造函数
//.........................................................................
constructor dTXIANGQI.Create(imgBoard:TImage;imgXY:dTXQPXY;imgQZMove:TImage;
imgMovePosF,imgMovePosT:TImage;picQZ:dTXQZPIC;
lbxRec,lbxOther:TListBox;
memRec:TMemo; XQZXY:dTXQZXY);
var
i, j: dTINT32;
begin
BoardImage := imgBoard; // 棋盘图片
for i:=0 to 8 do for j:=0 to 9 do // 创建象棋盘中的'兵站'
begin
BoardXY[i,j] := imgXY[i, j];
BoardXY[i,j].Tag := i*10 + j; // Tag 中存有'兵站'坐标
BoardXY[i,j].Picture := nil;
end;
QiziMoveImg := imgQZMove; // 拿起移动的棋子的图片
QiziMove := nil; // 正在移动的棋子
MovePosFrom := imgMovePosF;
MovePosTo := imgMovePosT; // 最后移动的棋子的指示
MovePosTo.Visible := False; // 关掉棋子指示
MovePosFrom.Visible := False;
// 创建32个象棋子(需要QiziPic数组)
QiZi[ 1] := dTXQZ.Create( 1, '车', picQZ[ 1], 1, 80); // Red
QiZi[ 2] := dTXQZ.Create( 2, '马', picQZ[ 2], 2, 70);
QiZi[ 3] := dTXQZ.Create( 3, '相', picQZ[ 3], 3, 60);
QiZi[ 4] := dTXQZ.Create( 4, '士', picQZ[ 4], 4, 50);
QiZi[ 5] := dTXQZ.Create( 5, '帅', picQZ[ 5], 5, 40);
QiZi[ 6] := dTXQZ.Create( 6, '士', picQZ[ 4], 4, 30);
QiZi[ 7] := dTXQZ.Create( 7, '相', picQZ[ 3], 3, 20);
QiZi[ 8] := dTXQZ.Create( 8, '马', picQZ[ 2], 2, 10);
QiZi[ 9] := dTXQZ.Create( 9, '车', picQZ[ 1], 1, 00);
QiZi[10] := dTXQZ.Create(10, '炮', picQZ[ 6], 6, 72);
QiZi[11] := dTXQZ.Create(11, '炮', picQZ[ 6], 6, 12);
QiZi[12] := dTXQZ.Create(12, '兵', picQZ[ 7], 7, 83);
QiZi[13] := dTXQZ.Create(13, '兵', picQZ[ 7], 7, 63);
QiZi[14] := dTXQZ.Create(14, '兵', picQZ[ 7], 7, 43);
QiZi[15] := dTXQZ.Create(15, '兵', picQZ[ 7], 7, 23);
QiZi[16] := dTXQZ.Create(16, '兵', picQZ[ 7], 7, 03);
QiZi[17] := dTXQZ.Create(17, '车', picQZ[ 8], 1, 09); // Blk
QiZi[18] := dTXQZ.Create(18, '马', picQZ[ 9], 2, 19);
QiZi[19] := dTXQZ.Create(19, '象', picQZ[10], 3, 29);
QiZi[20] := dTXQZ.Create(20, '士', picQZ[11], 4, 39);
QiZi[21] := dTXQZ.Create(21, '将', picQZ[12], 5, 49);
QiZi[22] := dTXQZ.Create(22, '士', picQZ[11], 4, 59);
QiZi[23] := dTXQZ.Create(23, '象', picQZ[10], 3, 69);
QiZi[24] := dTXQZ.Create(24, '马', picQZ[ 9], 2, 79);
QiZi[25] := dTXQZ.Create(25, '车', picQZ[ 8], 1, 89);
QiZi[26] := dTXQZ.Create(26, '炮', picQZ[13], 6, 17);
QiZi[27] := dTXQZ.Create(27, '炮', picQZ[13], 6, 77);
QiZi[28] := dTXQZ.Create(28, '卒', picQZ[14], 7, 06);
QiZi[29] := dTXQZ.Create(29, '卒', picQZ[14], 7, 26);
QiZi[30] := dTXQZ.Create(30, '卒', picQZ[14], 7, 46);
QiZi[31] := dTXQZ.Create(31, '卒', picQZ[14], 7, 66);
QiZi[32] := dTXQZ.Create(32, '卒', picQZ[14], 7, 86);
PlayTree := dTXQPlayNode.Create(0,'========= ',0,0,XQZXY,nil,nil,nil,nil);
PlayNode := PlayTree;
// 32个棋子的当前位置
for i:=1 to 32 do
begin
Qizi[i].XY := $FF; // 棋子均不在棋盘上
PlayTree.QiziXY[i] := XQZXY[i];
end;
PlayRec[0] := PlayTree;
RecListBox := lbxRec;
VarListBox := lbxOther;
RecMemo := memRec;
RecListBox.Items.Add(' ============ ');
// Clock : dTXQCLOCK; // 计时钟
RedPlayer := 'RedPlayer';
BlkPlayer := 'BlkPlayer';
PlayStepNo:= 0; // 当前行棋的总步数
PlayRecHook := nil;
RefreshHook := nil;
ReverseH := False;
dDispQiziAtRecNo(0);
dEnablePlayer(PlayTree);
end;
constructor dTXIANGQI.Create(imgBoard:TImage;imgXY:dTXQPXY;imgQZMove:TImage;
imgMovePosF,imgMovePosT:TImage;picQZ:dTXQZPIC;
lbxRec,lbxOther:TListBox;memRec:TMemo);
begin
Create(imgBoard,imgXY,imgQZMove,imgMovePosF,imgMovePosT,picQZ,
lbxRec,lbxOther,memRec,dCXQZXY);
end;
destructor dTXIANGQI.Destroy;
var
i: dTINT32;
begin
for i:=1 to 32 do Qizi[i].Destroy;
//XQRecLBX.Free;
PlayTree.Free;
inherited Destroy;
end;
function dTXiangQi.sGetFMTRecStr(PN: dTXQPlayNode):string;
var
s : string;
begin
sGetFMTRecStr := '';
if (PN=nil) then Exit;
case PN.StepNo mod 2 of
1:
begin
s := IntToStr((PN.StepNo + 1) div 2);
case Length(s) of
1: s := ' ' + s;
2: s := ' ' + s;
end;
s := s + '. ' + PN.StrRec + ' ';
end;
0:
begin
s := ' ' + PN.StrRec + ' ';
end;
end;
if (PN=PlayTree) then s := ' ============ ';
if ((PN.LParent<>nil)or(PN.RChild<>nil)) then s := s + 'm';
if PN.Remark <> nil then s := s + '*';
sGetFMTRecStr := s;
end;
//-------------------------------------------------------------------------
//
//.........................................................................
procedure dTXIANGQI.dStartMoveFromXY(XY:dTBYTE);
var
iIdx, X, Y: dTINT32;
begin
QiziMove := nil; X := XY div 10; Y := XY mod 10;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -