ZZY e16f76e11f refactor(重构): 重构了事件驱动的代码体系,使用全新命名和版本,以及测试套件的初试
- 移除了.csproj文件
- 更新了.gitignore,添加了.editorconfig
- 重构了IBoard和IPiece接口,引入了新的事件处理机制
- 优化了CCBoard、CCPiece等类的实现,使用新的事件驱动模型
- 删除了冗余代码,提高了代码的可读性和可维护性
2024-11-24 15:42:30 +08:00

123 lines
3.0 KiB
C#

using System;
using System.Collections;
using Vector2I = Vector.Vector2I;
namespace ChineseChess;
using static IBoard.IBoardOn;
public class Player {
private readonly CCBoard board;
private readonly SelectedPiece selectedNode;
public EventHandler<MoveEventArgs>? OnMove;
public bool CanMove { get; set; } = true;
public enum PlayerType {
Human,
AI
}
public Player(CCBoard board, PlayerType type = PlayerType.Human) {
this.board = board;
this.selectedNode = new SelectedPiece(board);
}
public void HandleBoardPosClick(Vector2I clickPos) {
if (board.IsPosOutOfRange(clickPos)) return;
// Console.WriteLine($"VirtualBoard {clickPos} clicked");
IPiece? clickChess = board.GetPiece(clickPos);
if (!selectedNode.HasSelected()) {
// Select piece
if (clickChess == null) {
// selectedNode.Clear();
return;
}
selectedNode.SetPos(clickPos);
} else if (clickChess == selectedNode.GetPiece()) {
// Unselect piece
selectedNode.Clear();
} else {
// Move piece
// GD.Print("default MoveFunc Move: ", selectedNode.GetPos(), "->", clickPos);
if (CanMove) MoveAndRecord(clickPos, selectedNode.GetPos());
}
}
public void MoveAndRecord(Vector2I toPos, Vector2I fromPos) {
// GD.Print($"{fromPos} move to {toPos}");
IPiece? toChess = board.GetPiece(toPos);
IPiece? fromChess = board.GetPiece(fromPos);
if (fromChess != null) fromChess.IsSelected = false;
else return;
selectedNode.Clear();
if (!fromChess.CanMove(toPos)) {
return;
}
// MUST BE THERE !!! 防止删除节点后在启动回调导致错误
OnMove?.Invoke(this, new MoveEventArgs
(fromChess, fromPos, toPos));
if (toChess != null) {
board.RemovePiece(toPos);
}
board.MovePiece(fromPos, toPos);
selectedNode.Clear();
}
public void SelectedClear() {
selectedNode.Clear();
}
public void SetAllowedPieces(ArrayList allowedPieces) {
selectedNode.allowedPieces = allowedPieces;
}
private class SelectedPiece {
// Called when the node enters the scene tree for the first time.
private Vector2I selectedNodePos = Vector2I.MaxValue;
private IPiece? piece = null;
private readonly CCBoard board;
public ArrayList? allowedPieces = null;
public SelectedPiece(CCBoard board) {
this.board = board;
}
public void Clear() {
if (selectedNodePos != Vector2I.MaxValue) {
selectedNodePos = Vector2I.MaxValue;
if (piece != null)
piece.IsSelected = false;
}
// Console.WriteLine("SelectedPiece.Clear {0}", piece);
}
public void SetPos(Vector2I pos) {
piece = board.GetPiece(pos);
if (allowedPieces != null && allowedPieces.Contains(piece) == false) {
return;
}
selectedNodePos = pos;
if (piece == null)
return;
piece.IsSelected = true;
Console.WriteLine("SelectedPiece.SetPos {0}", piece);
}
public IPiece? GetPiece() {
return piece;
}
public Vector2I GetPos() {
return selectedNodePos;
}
public bool HasSelected() {
return selectedNodePos != Vector2I.MaxValue;
}
}
}