feat(重构): 重构棋盘和棋子的逻辑

- 重构了 ChessBoard 和 ChessPiece 类的逻辑
- 添加了新版本的 ChineseChess 库
- 删除了旧版本的 VirtualBoard 和 VirtualPiece 类
- 更新了相关的场景和脚本
This commit is contained in:
ZZY
2024-11-22 20:01:40 +08:00
parent 8ee9732a6f
commit 9c619784af
28 changed files with 1068 additions and 455 deletions

View File

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using Vector2I = Vector.Vector2I;
using static IBoard;
public abstract class AbstractBoard : IBoard {
private readonly int rows;
private readonly int cols;
protected readonly IPiece[,] pieces;
protected readonly List<MoveRecord> moveRecords = new();
protected readonly int MAX_RECORDS;
public int Rows => rows;
public int Cols => cols;
public event EventHandler<SetPieceEventArgs> OnSetPiece;
public event EventHandler<IPiece> OnInsert;
public event EventHandler<IPiece> OnRemove;
public event EventHandler<MoveEventArgs> OnMove;
public event EventHandler<MoveRecord> OnAddRecord;
public event EventHandler<MoveRecord> OnUndoRecord;
public AbstractBoard(int rows, int cols, int maxRecords = int.MaxValue) {
this.rows = rows;
this.cols = cols;
pieces = new IPiece[rows, cols];
MAX_RECORDS = maxRecords;
}
public virtual bool IsPosOutOfRange(Vector2I arrayPos) {
return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols;
}
public virtual IPiece GetPiece(Vector2I arrayPos) {
if (IsPosOutOfRange(arrayPos)) return null;
return pieces[arrayPos.X, arrayPos.Y];
}
public virtual IPiece SetPiece(IPiece piece, Vector2I pos) {
if (IsPosOutOfRange(pos)) return null;
IPiece oldPiece = pieces[pos.X, pos.Y];
pieces[pos.X, pos.Y] = piece;
if (piece != null) piece.Pos = pos;
// if (oldPiece != null) oldPiece.Pos = Vector2I.Zero;
OnSetPiece?.Invoke(this, new SetPieceEventArgs { OldPiece = oldPiece, NewPiece = piece, Pos = pos });
return oldPiece;
}
public virtual bool InsertPiece(IPiece piece, Vector2I pos) {
if (GetPiece(pos) != null && piece == null) {
return false;
}
OnInsert?.Invoke(this, piece);
SetPiece(piece, pos);
return true;
}
public virtual bool MovePiece(Vector2I from, Vector2I to) {
if (IsPosOutOfRange(to) || IsPosOutOfRange(from)) {
return false;
}
IPiece piece = GetPiece(from);
if (GetPiece(to) != null && piece == null) {
return false;
}
OnMove?.Invoke(this, new MoveEventArgs { From = from, To = to, Piece = piece });
SetPiece(null, from);
SetPiece(piece, to);
return true;
}
public virtual IPiece RemovePiece(Vector2I pos) {
IPiece piece = GetPiece(pos);
OnRemove?.Invoke(this, piece);
return SetPiece(null, pos);
}
public virtual void Clear() { Clear(true); }
public virtual void Clear(bool clearRecords) {
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
RemovePiece(new Vector2I(i, j));
}
}
if (clearRecords) ClearRecords();
}
public virtual void ClearRecords() {
moveRecords.Clear();
}
public virtual void AddRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
if (moveRecords.Count >= MAX_RECORDS) {
moveRecords.RemoveAt(0);
}
MoveRecord record = new(From, To, FromPos, ToPos);
OnAddRecord?.Invoke(this, record);
moveRecords.Add(record);
}
public virtual void UndoRecord() {
if (moveRecords.Count == 0) return;
MoveRecord record = moveRecords[^1];
moveRecords.RemoveAt(moveRecords.Count - 1);
// 恢复新位置的棋子order is very inmportant
if (record.From != null) {
MovePiece(record.ToPos, record.FromPos);
}
// 恢复旧位置的棋子
if (record.To != null) {
InsertPiece(record.To, record.ToPos);
}
OnUndoRecord?.Invoke(this, record);
}
public class MoveRecord {
public IPiece From { get; }
public IPiece To { get; }
public Vector2I FromPos { get; }
public Vector2I ToPos { get; }
public MoveRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
this.From = From;
this.To = To;
this.ToPos = ToPos;
this.FromPos = FromPos;
}
}
}