- 更新了多个文件的代码结构和类型定义,提高了代码的健壮性和可维护性 - 优化了事件处理、棋子管理和移动逻辑,为后续功能扩展打下坚实基础 - 修复了一些潜在的空指针异常问题,提高了程序的稳定性 - 修复部分bug
142 lines
4.3 KiB
C#
142 lines
4.3 KiB
C#
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);
|
||
if (piece == null) return null;
|
||
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;
|
||
}
|
||
}
|
||
}
|