using System.Collections.Generic; using Vector2I = Vector.Vector2I; using static IBoard; public abstract class AbstractBoard(int rows, int cols, int maxRecords = int.MaxValue, IBoardOn? on = null) : IBoard { private readonly int rows = rows; private readonly int cols = cols; protected readonly IPiece?[,] pieces = new IPiece[rows, cols]; protected readonly List moveRecords = []; protected readonly int MAX_RECORDS = maxRecords; public int Rows => rows; public int Cols => cols; protected IBoardOn? on = on; public virtual IBoardOn? On { get => on; set => on = value; } 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 is not null) piece.Pos = pos; // if (oldPiece != null) oldPiece.Pos = Vector2I.Zero; on?.OnSetPieceInteral(this, new IBoardOn.SetPieceEventArgs (oldPiece, piece, pos)); return oldPiece; } public virtual bool InsertPiece(IPiece piece, Vector2I pos) { if (GetPiece(pos) is not null && piece == null) { return false; } on?.OnInsert(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) is not null || piece is null) { return false; } on?.OnMove(this, new IBoardOn.MoveEventArgs(piece, from, to)); SetPiece(null, from); SetPiece(piece, to); return true; } public virtual IPiece? RemovePiece(Vector2I pos) { IPiece? piece = GetPiece(pos); if (piece is null) return null; on?.OnRemove(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); on?.OnAddRecord(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 is not null) { MovePiece(record.ToPos, record.FromPos); } // 恢复旧位置的棋子 if (record.To is not null) { InsertPiece(record.To, record.ToPos); } on?.OnUndoRecord(this, record); } }