feat(chinese-chess): 实现中国象棋核心逻辑和基本功能
- 抽象出 ChessCore 类,包含游戏初始化、行棋逻辑、悔棋等功能 - 重构 Player 类,优化行棋和记录逻辑 - 更新 ChessBoard 和 ChessPiece 类,适应新逻辑 - 移除冗余代码,提高代码可读性和可维护性
This commit is contained in:
@ -0,0 +1,154 @@
|
||||
using Vector2 = Godot.Vector2;
|
||||
using System;
|
||||
using System.Collections;
|
||||
namespace ChineseChess;
|
||||
|
||||
class ChessCore {
|
||||
public enum Mode {
|
||||
SingleMode,
|
||||
MultiMode,
|
||||
DebugMode,
|
||||
};
|
||||
|
||||
public enum TurnsSideType {
|
||||
Red,
|
||||
Black,
|
||||
};
|
||||
|
||||
public enum PlayerSideType {
|
||||
Self,
|
||||
Opponent,
|
||||
Any,
|
||||
};
|
||||
|
||||
private TurnsSideType sideType = TurnsSideType.Red;
|
||||
private readonly TurnsSideType selfSide;
|
||||
public readonly VirtualBoard board = new(9, 10);
|
||||
private readonly Player playerSelf;
|
||||
private readonly Player playerOpponent;
|
||||
private readonly MoveRecords<VirtualPiece> moveRecords;
|
||||
public EventHandler<VirtualBoard.MoveEventArgs> OnMove;
|
||||
|
||||
public ChessCore(Mode mode, TurnsSideType selfSide) {
|
||||
this.selfSide = selfSide;
|
||||
|
||||
playerSelf = new(board, Player.PlayerType.Human);
|
||||
playerOpponent = new(board, Player.PlayerType.Human);
|
||||
|
||||
playerSelf.OnMove += (sender, args) => {
|
||||
moveRecords.AddRecord(board.GetPiece(args.To), board.GetPiece(args.From),
|
||||
args.To, args.From);
|
||||
};
|
||||
playerOpponent.OnMove += (sender, args) => {
|
||||
moveRecords.AddRecord(board.GetPiece(args.To), board.GetPiece(args.From),
|
||||
args.To, args.From);
|
||||
};
|
||||
|
||||
moveRecords = new MoveRecords<VirtualPiece>(
|
||||
onAddRecordCallback: (newNode, oldNode, newPos, oldPos) => {
|
||||
playerSelf.SelectedClear();
|
||||
playerOpponent.SelectedClear();
|
||||
},
|
||||
onUndoRecordCallback: (newNode, oldNode, newPos, oldPos) => {
|
||||
// GD.Print("Undo: ", newNode, "->", oldNode, ":", newPos, "->", oldPos);
|
||||
VirtualPiece newPiece = newNode;
|
||||
VirtualPiece oldPiece = oldNode;
|
||||
board.MovePiece(newPos, oldPos);
|
||||
if (newPiece != null) {
|
||||
board.InsertPiece(newPiece, newPos);
|
||||
}
|
||||
});
|
||||
|
||||
switch (mode) {
|
||||
case Mode.SingleMode:
|
||||
break;
|
||||
case Mode.MultiMode:
|
||||
break;
|
||||
default:
|
||||
case Mode.DebugMode:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void InitGame() {
|
||||
ArrayList blackPart = InitOnePartPieces(TurnsSideType.Black, new[] {
|
||||
("车", 0, 0), ("马", 1, 0), ("象", 2, 0),
|
||||
("士", 3, 0), ("将", 4, 0), ("士", 5, 0),
|
||||
("象", 6, 0), ("马", 7, 0), ("车", 8, 0),
|
||||
("炮", 1, 2), ("炮", 7, 2),
|
||||
("卒", 0, 3), ("卒", 2, 3), ("卒", 4, 3), ("卒", 6, 3), ("卒", 8, 3)
|
||||
});
|
||||
|
||||
ArrayList redPart = InitOnePartPieces(TurnsSideType.Red, new[] {
|
||||
("车", 0, -0), ("马", 1, -0), ("象", 2, -0),
|
||||
("士", 3, -0), ("将", 4, -0), ("士", 5, -0),
|
||||
("象", 6, -0), ("马", 7, -0), ("车", 8, -0),
|
||||
("炮", 1, -2), ("炮", 7, -2),
|
||||
("卒", 0, -3), ("卒", 2, -3), ("卒", 4, -3), ("卒", 6, -3), ("卒", 8, -3)
|
||||
});
|
||||
if (selfSide == TurnsSideType.Red) {
|
||||
playerSelf.SetAllowedPieces(redPart);
|
||||
playerOpponent.SetAllowedPieces(blackPart);
|
||||
} else {
|
||||
playerSelf.SetAllowedPieces(blackPart);
|
||||
playerOpponent.SetAllowedPieces(redPart);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList InitOnePartPieces(TurnsSideType side, (string label, int x, int y)[] positions) {
|
||||
ArrayList list = new();
|
||||
foreach (var (label, x, y) in positions) {
|
||||
// FIXME: use a better way to initialize pieces
|
||||
Vector2 pos = new(x, y + (TurnsSideType.Red == side ? 9 : 0));
|
||||
VirtualPiece piece = new(label, pos);
|
||||
list.Add(piece);
|
||||
board.InsertPiece(piece, pos);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void OnPosClicked(Vector2 pos, PlayerSideType clickedSide = PlayerSideType.Any) {
|
||||
if (sideType == selfSide) {
|
||||
playerSelf.CanMove = true;
|
||||
playerOpponent.CanMove = false;
|
||||
} else {
|
||||
playerSelf.CanMove = false;
|
||||
playerOpponent.CanMove = true;
|
||||
}
|
||||
|
||||
switch (clickedSide) {
|
||||
case PlayerSideType.Any:
|
||||
playerSelf.HandleBoardPosClick(pos);
|
||||
playerOpponent.HandleBoardPosClick(pos);
|
||||
break;
|
||||
case PlayerSideType.Self:
|
||||
playerSelf.HandleBoardPosClick(pos);
|
||||
break;
|
||||
case PlayerSideType.Opponent:
|
||||
playerOpponent.HandleBoardPosClick(pos);
|
||||
break;
|
||||
}
|
||||
|
||||
sideType = moveRecords.Count() % 2 == 0 ? TurnsSideType.Red : TurnsSideType.Black;
|
||||
}
|
||||
|
||||
public TurnsSideType GetTurnsType() {
|
||||
sideType = moveRecords.Count() % 2 == 0 ? TurnsSideType.Red : TurnsSideType.Black;
|
||||
return sideType;
|
||||
}
|
||||
|
||||
public void Undo() {
|
||||
playerSelf.SelectedClear();
|
||||
playerOpponent.SelectedClear();
|
||||
moveRecords.Undo();
|
||||
}
|
||||
|
||||
public void ReInit() {
|
||||
playerSelf.SelectedClear();
|
||||
playerOpponent.SelectedClear();
|
||||
moveRecords.Clear();
|
||||
board.Clear();
|
||||
InitGame();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user