- 抽象出 ChessCore 类,包含游戏初始化、行棋逻辑、悔棋等功能 - 重构 Player 类,优化行棋和记录逻辑 - 更新 ChessBoard 和 ChessPiece 类,适应新逻辑 - 移除冗余代码,提高代码可读性和可维护性
154 lines
4.9 KiB
C#
154 lines
4.9 KiB
C#
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();
|
|
}
|
|
} |