refactor(重构): 重构了事件驱动的代码体系,使用全新命名和版本,以及测试套件的初试
- 移除了.csproj文件 - 更新了.gitignore,添加了.editorconfig - 重构了IBoard和IPiece接口,引入了新的事件处理机制 - 优化了CCBoard、CCPiece等类的实现,使用新的事件驱动模型 - 删除了冗余代码,提高了代码的可读性和可维护性
This commit is contained in:
parent
327c2df94d
commit
e16f76e11f
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,6 +25,7 @@ bin/
|
||||
*.sln
|
||||
*.error
|
||||
*.key*
|
||||
.editorconfig
|
||||
|
||||
# cs project files
|
||||
!*.csproj
|
||||
|
@ -1,8 +1,6 @@
|
||||
<Project Sdk="Godot.NET.Sdk/4.3.0">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>
|
||||
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
|
||||
<Nullable>enable</Nullable>
|
@ -1,3 +1,4 @@
|
||||
#nullable disable
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using ChineseChess;
|
||||
@ -39,15 +40,15 @@ public partial class ChessGame : Node2D {
|
||||
sideOpposite = ChessCore.TurnsSideType.Red;
|
||||
}
|
||||
|
||||
if (isSession) {
|
||||
Game = new(ChessCore.Mode.MultiMode, sideSelf);
|
||||
} else {
|
||||
Game = new(ChessCore.Mode.SingleMode, sideSelf);
|
||||
}
|
||||
board.LoadBoard(Game.board);
|
||||
// if (isSession) {
|
||||
// Game = new(ChessCore.Mode.MultiMode, sideSelf);
|
||||
// } else {
|
||||
// Game = new(ChessCore.Mode.SingleMode, sideSelf);
|
||||
// }
|
||||
Game = new(isSession ? ChessCore.Mode.MultiMode : ChessCore.Mode.SingleMode, sideSelf, board);
|
||||
Game.Init();
|
||||
|
||||
Game.board.OnStepsChanged += (sender, e) => {
|
||||
board.OnStepsChanged += (sender, e) => {
|
||||
turnSideEdit.Text = Game.GetTurnsType() == ChessCore.TurnsSideType.Red ? "red" : "black";
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#nullable disable
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
|
@ -4,12 +4,14 @@ using Godot;
|
||||
using ChineseChess;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class ChessBoard : Node2D {
|
||||
public event EventHandler<Vector2> OnMouseClicked;
|
||||
public event EventHandler<Vector2> OnPosClicked;
|
||||
using static IBoard;
|
||||
public partial class ChessBoard : Node2D, ICCBoardOn {
|
||||
public event EventHandler<Vector2>? OnMouseClicked;
|
||||
public event EventHandler<Vector2>? OnPosClicked;
|
||||
public event EventHandler<int>? OnStepsChanged;
|
||||
|
||||
public Vector2 from = Vector2.Inf, to = Vector2.Inf;
|
||||
public Array<Vector2> canMovePos = new();
|
||||
public Array<Vector2> canMovePos = [];
|
||||
|
||||
public override void _Ready() {
|
||||
}
|
||||
@ -19,29 +21,39 @@ public partial class ChessBoard : Node2D {
|
||||
QueueRedraw();
|
||||
}
|
||||
|
||||
public void LoadBoard(CCBoard board) {
|
||||
board.OnRemove += (sender, piece) => {
|
||||
if (piece?.Data.TryGetValue("Godot", out object node) ?? false) {
|
||||
RemoveChild(node as Node);
|
||||
}
|
||||
};
|
||||
void IBoardOn.OnInsert(object self, IPiece piece) {
|
||||
ChessPiece? node = piece.On as ChessPiece;
|
||||
// throw new InvalidOperationException();
|
||||
node ??= new ChessPiece((CCPiece)piece);
|
||||
node.ShowBehindParent = true;
|
||||
AddChild(node);
|
||||
|
||||
board.OnInsert += (sender, piece) => {
|
||||
ChessPiece chessPiece = null;
|
||||
if (piece.Data.TryGetValue("Godot", out object node)) {
|
||||
chessPiece = node as ChessPiece;
|
||||
} else {
|
||||
chessPiece = new((CCPiece)piece);
|
||||
}
|
||||
chessPiece.ShowBehindParent = true;
|
||||
AddChild(chessPiece);
|
||||
};
|
||||
// ChessPiece chessPiece = null;
|
||||
// if (piece.Data.TryGetValue("Godot", out object node)) {
|
||||
// chessPiece = node as ChessPiece;
|
||||
// } else {
|
||||
// chessPiece = new((CCPiece)piece);
|
||||
// }
|
||||
// chessPiece.ShowBehindParent = true;
|
||||
// AddChild(chessPiece);
|
||||
}
|
||||
|
||||
board.OnMove += (sender, vals) => {
|
||||
from = PosTrans.transArrToPix * new Vector2(vals.From.X, vals.From.Y);
|
||||
to = PosTrans.transArrToPix * new Vector2(vals.To.X, vals.To.Y);
|
||||
QueueRedraw();
|
||||
};
|
||||
void IBoardOn.OnRemove(object self, IPiece piece) {
|
||||
if (piece.On is not ChessPiece node) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
RemoveChild(node);
|
||||
}
|
||||
|
||||
void IBoardOn.OnMove(object self, IBoardOn.MoveEventArgs vals) {
|
||||
from = PosTrans.transArrToPix * new Vector2(vals.From.X, vals.From.Y);
|
||||
to = PosTrans.transArrToPix * new Vector2(vals.To.X, vals.To.Y);
|
||||
QueueRedraw();
|
||||
}
|
||||
|
||||
void ICCBoardOn.OnSteps(object _self, int oldSteps) {
|
||||
if (_self is not CCBoard self) return;
|
||||
OnStepsChanged?.Invoke(self, self.Steps);
|
||||
}
|
||||
|
||||
public override void _Draw() {
|
||||
|
@ -4,37 +4,31 @@ using ChineseChess;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
public partial class ChessPiece : Sprite2D {
|
||||
using static IPiece;
|
||||
public partial class ChessPiece : Sprite2D, IPieceOn {
|
||||
[Export]
|
||||
public string PieceLabel { get; set; } = null;
|
||||
public string? PieceLabel { get; set; } = null;
|
||||
// Text Color (Can Export for Editor Adjust)
|
||||
[Export]
|
||||
public Color LabelColor { get; set; } = new Color("white");
|
||||
private Vector2 textureSize;
|
||||
private Label? labelOfChessName;
|
||||
|
||||
private Label labelOfChessName;
|
||||
private readonly IPiece piece;
|
||||
|
||||
public IPiece GetVirtualPiece() {
|
||||
return piece;
|
||||
}
|
||||
|
||||
private void OnPos(object _self, Vector.Vector2I oldPos) {
|
||||
CCPiece self = (CCPiece)_self;
|
||||
void IPieceOn.OnPos(object _self, Vector.Vector2I oldPos) {
|
||||
if (_self is not CCPiece self) return;
|
||||
Position = ChessBoard.PosTrans.transArrToPix * new Vector2(self.Pos.X, self.Pos.Y);
|
||||
}
|
||||
|
||||
public void OnSelected(object _self, bool oldIsSelected) {
|
||||
CCPiece self = (CCPiece)_self;
|
||||
ChessBoard chessBoard = GetParent() as ChessBoard;
|
||||
void IPieceOn.OnSelected(object _self, bool oldIsSelected) {
|
||||
if (GetParent() is not ChessBoard chessBoard || _self is not CCPiece self) return;
|
||||
if (self.IsSelected) {
|
||||
GD.Print($"{piece.Pos} is selected");
|
||||
GD.Print($"{self.Pos} is selected");
|
||||
Transform *= transToSeleted;
|
||||
foreach (var item in self.CanMoveAllPos()) {
|
||||
chessBoard.canMovePos.Add(ChessBoard.PosTrans.transArrToPix * new Vector2(item.X, item.Y));
|
||||
}
|
||||
} else {
|
||||
GD.Print($"{piece.Pos} is deselected");
|
||||
GD.Print($"{self.Pos} is deselected");
|
||||
Transform *= transToSeleted.AffineInverse();
|
||||
foreach (var item in self.CanMoveAllPos()) {
|
||||
chessBoard.canMovePos.Remove(ChessBoard.PosTrans.transArrToPix * new Vector2(item.X, item.Y));
|
||||
@ -49,17 +43,15 @@ public partial class ChessPiece : Sprite2D {
|
||||
new Vector2(0, 0)
|
||||
);
|
||||
|
||||
public ChessPiece() : this(new CCPiece()){
|
||||
public ChessPiece() : this(new CCPiece()) {
|
||||
}
|
||||
|
||||
public ChessPiece(CCPiece piece) {
|
||||
PieceLabel = piece.CNName;
|
||||
this.piece = piece;
|
||||
LabelColor = piece.TurnsSide == ChessCore.TurnsSideType.Red ? new Color("red") : new Color("black");
|
||||
piece.OnPos += OnPos;
|
||||
piece.OnSelected += OnSelected;
|
||||
piece.On = this;
|
||||
// Must Be Call for init Pos
|
||||
OnPos(piece, piece.Pos);
|
||||
piece.On.OnPos(piece, piece.Pos);
|
||||
piece.Data.TryAdd("Godot", this);
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
#nullable disable
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using RPPackage;
|
||||
|
||||
public partial class Global : Node
|
||||
{
|
||||
public partial class Global : Node {
|
||||
public RPClientEDWS RPClient = new();
|
||||
public string sessionId;
|
||||
public Node CurrentScene { get; set; }
|
||||
public Theme GlobalTheme = null;
|
||||
|
||||
readonly GodotConfigManager GlobalConfig = new("user://config.cfg");
|
||||
readonly GodotConfigManager GlobalConfig = new("user://config.cfg");
|
||||
public Dictionary<string, Variant> GlobalConfigDict = new() {
|
||||
{"font_size", 20},
|
||||
{"server_url", "wss://game.zzyxyz.com/"},
|
||||
@ -21,8 +21,7 @@ public partial class Global : Node
|
||||
};
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
public override void _Ready() {
|
||||
if (OS.GetName() == "Android") {
|
||||
bool ret = OS.RequestPermissions();
|
||||
GD.Print($"RequestPermissions ret is {ret}");
|
||||
@ -37,41 +36,36 @@ public partial class Global : Node
|
||||
};
|
||||
|
||||
Viewport root = GetTree().Root;
|
||||
CurrentScene = root.GetChild(root.GetChildCount() - 1);
|
||||
CurrentScene = root.GetChild(root.GetChildCount() - 1);
|
||||
|
||||
GlobalConfig.LoadConfig("Global", GlobalConfigDict);
|
||||
SetProcess(false);
|
||||
}
|
||||
|
||||
public void ConfigFlush()
|
||||
{
|
||||
public void ConfigFlush() {
|
||||
int font_size = (int)GlobalConfigDict["font_size"];
|
||||
GlobalTheme.DefaultFontSize = font_size;
|
||||
// GlobalTheme?.SetFontSize("font_size", "Label", font_size);
|
||||
// GlobalTheme?.SetFontSize("font_size", "Button", font_size);
|
||||
// GlobalTheme?.SetFontSize("font_size", "TextEdit", font_size);
|
||||
// GlobalTheme?.SetFontSize("font_size", "LineEdit", font_size);
|
||||
// GlobalTheme?.SetFontSize("font_size", "Button", font_size);
|
||||
// GlobalTheme?.SetFontSize("font_size", "TextEdit", font_size);
|
||||
// GlobalTheme?.SetFontSize("font_size", "LineEdit", font_size);
|
||||
// CurrentScene.GetWindow().AddThemeFontSizeOverride("Control", (int)GlobalConfigDict["font_size"]);
|
||||
}
|
||||
|
||||
private void OnGotoScene()
|
||||
{
|
||||
private void OnGotoScene() {
|
||||
ConfigFlush();
|
||||
}
|
||||
|
||||
public void SaveConfig()
|
||||
{
|
||||
public void SaveConfig() {
|
||||
GlobalConfig.SaveConfig("Global", GlobalConfigDict);
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
public override void _Process(double delta) {
|
||||
RPClient.PollEx(delta);
|
||||
}
|
||||
|
||||
public override void _Notification(int what)
|
||||
{
|
||||
public override void _Notification(int what) {
|
||||
if (what == NotificationWMCloseRequest) {
|
||||
// SaveConfig();
|
||||
RPClient.Close();
|
||||
@ -81,8 +75,7 @@ public partial class Global : Node
|
||||
|
||||
public delegate void ChangeSceneCallback(Node newSence);
|
||||
private static ChangeSceneCallback changeSceneCallback = null;
|
||||
public void GotoScene(string path, ChangeSceneCallback callback = null)
|
||||
{
|
||||
public void GotoScene(string path, ChangeSceneCallback callback = null) {
|
||||
// This function will usually be called from a signal callback,
|
||||
// or some other function from the current scene.
|
||||
// Deleting the current scene at this point is
|
||||
@ -100,8 +93,7 @@ public partial class Global : Node
|
||||
changeSceneCallback = null;
|
||||
}
|
||||
|
||||
public void DeferredGotoScene(string path, Callable onLoaded)
|
||||
{
|
||||
public void DeferredGotoScene(string path, Callable onLoaded) {
|
||||
// It is now safe to remove the current scene.
|
||||
CurrentScene.Free();
|
||||
|
||||
|
@ -1,32 +1,20 @@
|
||||
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 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<MoveRecord> moveRecords = [];
|
||||
protected readonly int MAX_RECORDS = maxRecords;
|
||||
|
||||
public int Rows => rows;
|
||||
public int Cols => cols;
|
||||
protected IBoardOn? on = on;
|
||||
|
||||
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 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;
|
||||
@ -42,19 +30,20 @@ public abstract class AbstractBoard : IBoard {
|
||||
|
||||
IPiece? oldPiece = pieces[pos.X, pos.Y];
|
||||
pieces[pos.X, pos.Y] = piece;
|
||||
if (piece != null) piece.Pos = pos;
|
||||
if (piece is not null) piece.Pos = pos;
|
||||
// if (oldPiece != null) oldPiece.Pos = Vector2I.Zero;
|
||||
|
||||
OnSetPiece?.Invoke(this, new SetPieceEventArgs { OldPiece = oldPiece, NewPiece = piece, Pos = pos });
|
||||
on?.OnSetPieceInteral(this, new IBoardOn.SetPieceEventArgs
|
||||
(oldPiece, piece, pos));
|
||||
return oldPiece;
|
||||
}
|
||||
|
||||
public virtual bool InsertPiece(IPiece piece, Vector2I pos) {
|
||||
if (GetPiece(pos) != null && piece == null) {
|
||||
if (GetPiece(pos) is not null && piece == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OnInsert?.Invoke(this, piece);
|
||||
on?.OnInsert(this, piece);
|
||||
SetPiece(piece, pos);
|
||||
return true;
|
||||
}
|
||||
@ -65,11 +54,11 @@ public abstract class AbstractBoard : IBoard {
|
||||
}
|
||||
|
||||
IPiece? piece = GetPiece(from);
|
||||
if (GetPiece(to) != null || piece == null) {
|
||||
if (GetPiece(to) is not null || piece is null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OnMove?.Invoke(this, new MoveEventArgs { From = from, To = to, Piece = piece });
|
||||
on?.OnMove(this, new IBoardOn.MoveEventArgs(piece, from, to));
|
||||
SetPiece(null, from);
|
||||
SetPiece(piece, to);
|
||||
return true;
|
||||
@ -77,8 +66,9 @@ public abstract class AbstractBoard : IBoard {
|
||||
|
||||
public virtual IPiece? RemovePiece(Vector2I pos) {
|
||||
IPiece? piece = GetPiece(pos);
|
||||
if (piece == null) return null;
|
||||
OnRemove?.Invoke(this, piece);
|
||||
if (piece is null) return null;
|
||||
|
||||
on?.OnRemove(this, piece);
|
||||
return SetPiece(null, pos);
|
||||
}
|
||||
|
||||
@ -103,7 +93,7 @@ public abstract class AbstractBoard : IBoard {
|
||||
}
|
||||
MoveRecord record = new(From, To, FromPos, ToPos);
|
||||
|
||||
OnAddRecord?.Invoke(this, record);
|
||||
on?.OnAddRecord(this, record);
|
||||
moveRecords.Add(record);
|
||||
}
|
||||
|
||||
@ -113,29 +103,15 @@ public abstract class AbstractBoard : IBoard {
|
||||
moveRecords.RemoveAt(moveRecords.Count - 1);
|
||||
|
||||
// 恢复新位置的棋子,order is very inmportant
|
||||
if (record.From != null) {
|
||||
if (record.From is not null) {
|
||||
MovePiece(record.ToPos, record.FromPos);
|
||||
}
|
||||
|
||||
// 恢复旧位置的棋子
|
||||
if (record.To != null) {
|
||||
if (record.To is not 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;
|
||||
}
|
||||
on?.OnUndoRecord(this, record);
|
||||
}
|
||||
}
|
||||
|
@ -1,62 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Vector2I = Vector.Vector2I;
|
||||
|
||||
public abstract class AbstractPiece : IPiece {
|
||||
private Vector2I pos; // 注意这个坐标的非像素坐标而是棋盘坐标
|
||||
using static IPiece;
|
||||
public abstract class AbstractPiece(string name = "", Vector2I? pos = null,
|
||||
IPieceOn? on = null) : IPiece {
|
||||
private Vector2I pos = pos ?? new(); // 注意这个坐标的非像素坐标而是棋盘坐标
|
||||
private bool isSelected = false;
|
||||
protected string name;
|
||||
private Dictionary<string, object> data = new();
|
||||
protected string name = name;
|
||||
private Dictionary<string, object> data = [];
|
||||
protected IPieceOn? on = on;
|
||||
|
||||
public Vector2I Pos {
|
||||
public virtual IPieceOn? On { get => on; set => on = value; }
|
||||
|
||||
public virtual Vector2I Pos {
|
||||
get => pos;
|
||||
set {
|
||||
if (pos != value) {
|
||||
var oldPos = pos;
|
||||
pos = value;
|
||||
OnPos?.Invoke(this, oldPos);
|
||||
on?.OnPos(this, oldPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSelected {
|
||||
public virtual bool IsSelected {
|
||||
get => isSelected;
|
||||
set {
|
||||
if (isSelected != value) {
|
||||
var oldIsSelected = isSelected;
|
||||
isSelected = value;
|
||||
OnSelected?.Invoke(this, oldIsSelected);
|
||||
on?.OnSelected(this, oldIsSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Name {
|
||||
public virtual string Name {
|
||||
get => name;
|
||||
set {
|
||||
if (name != value) {
|
||||
var oldName = name;
|
||||
name = value;
|
||||
OnName?.Invoke(this, oldName);
|
||||
on?.OnName(this, oldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, object> Data {
|
||||
public virtual Dictionary<string, object> Data {
|
||||
get => data;
|
||||
set => data = value;
|
||||
}
|
||||
|
||||
public event EventHandler<Vector2I>? OnPos;
|
||||
public event EventHandler<Vector2I>? OnMove;
|
||||
public event EventHandler<bool>? OnSelected;
|
||||
public event EventHandler<string>? OnName;
|
||||
|
||||
public virtual bool Move(Vector2I pos) {
|
||||
if (!CanMove(pos)) {
|
||||
return false;
|
||||
}
|
||||
Pos = pos;
|
||||
OnMove?.Invoke(this, pos);
|
||||
on?.OnMove(this, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -65,9 +64,4 @@ public abstract class AbstractPiece : IPiece {
|
||||
public override string ToString() {
|
||||
return $"{Name} at {pos}";
|
||||
}
|
||||
|
||||
public AbstractPiece(string name = "", Vector2I? pos = null) {
|
||||
this.name = name;
|
||||
this.pos = pos ?? new();
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,29 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using static ChineseChess.ChessCore;
|
||||
using Vector2I = Vector.Vector2I;
|
||||
|
||||
namespace ChineseChess;
|
||||
public class CCBoard : AbstractBoard
|
||||
{
|
||||
public event EventHandler<int>? OnStepsChanged;
|
||||
public interface ICCBoardOn : IBoard.IBoardOn {
|
||||
void OnSteps(object self, int oldSteps) {}
|
||||
}
|
||||
|
||||
public class CCBoard(ICCBoardOn? on = null) : AbstractBoard(9, 10, on: on) {
|
||||
private int steps = 0;
|
||||
protected new ICCBoardOn? on = on;
|
||||
// public virtual IPieceOn? On { get => on; set => on = value; }
|
||||
public new ICCBoardOn? On { get => on; set {
|
||||
on = value; base.on = value;} }
|
||||
|
||||
public int Steps {
|
||||
get => steps;
|
||||
protected set {
|
||||
if (steps != value) {
|
||||
var oldSteps = steps;
|
||||
steps = value;
|
||||
OnStepsChanged?.Invoke(this, steps);
|
||||
on?.OnSteps(this, oldSteps);
|
||||
}
|
||||
}
|
||||
}
|
||||
public CCBoard() : base(9, 10) {
|
||||
}
|
||||
|
||||
public override void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
|
||||
base.AddRecord(From, To, FromPos, ToPos);
|
||||
@ -32,65 +37,49 @@ public class CCBoard : AbstractBoard
|
||||
|
||||
public (ArrayList, ArrayList) InitGame() {
|
||||
Steps = 0;
|
||||
// ArrayList blackPart = InitOnePartPieces(TurnsSideType.Black, new[] {
|
||||
// new CCChariot(TurnsSideType.Black, "black chariot 0", 0, 0),
|
||||
// ("车", 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 blackPart = InitOnePartPieces(TurnsSideType.Black, [
|
||||
new CCChariot (this, TurnsSideType.Black, new Vector2I( 4, 0)),
|
||||
new CCHorse (this, TurnsSideType.Black, new Vector2I( 3, 0)),
|
||||
new CCElephant(this, TurnsSideType.Black, new Vector2I( 2, 0)),
|
||||
new CCAdvisor (this, TurnsSideType.Black, new Vector2I( 1, 0)),
|
||||
new CCGeneral (this, TurnsSideType.Black, new Vector2I( 0, 0)),
|
||||
new CCAdvisor (this, TurnsSideType.Black, new Vector2I(-1, 0)),
|
||||
new CCElephant(this, TurnsSideType.Black, new Vector2I(-2, 0)),
|
||||
new CCHorse (this, TurnsSideType.Black, new Vector2I(-3, 0)),
|
||||
new CCChariot (this, TurnsSideType.Black, new Vector2I(-4, 0)),
|
||||
new CCCannon (this, TurnsSideType.Black, new Vector2I( 3, 2)),
|
||||
new CCCannon (this, TurnsSideType.Black, new Vector2I(-3, 2)),
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I(-4, 3)),
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I(-2, 3)),
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I( 0, 3)),
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I( 2, 3)),
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I( 4, 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)
|
||||
// });
|
||||
ArrayList blackPart = InitOnePartPieces(TurnsSideType.Black, new CCPiece[] {
|
||||
new CCChariot (this, TurnsSideType.Black, new Vector2I( 4, 0)), // 4,0
|
||||
new CCHorse (this, TurnsSideType.Black, new Vector2I( 3, 0)), // 3,0
|
||||
new CCElephant(this, TurnsSideType.Black, new Vector2I( 2, 0)), // 2,0
|
||||
new CCAdvisor (this, TurnsSideType.Black, new Vector2I( 1, 0)), // 1,0
|
||||
new CCGeneral (this, TurnsSideType.Black, new Vector2I( 0, 0)), // 0,0
|
||||
new CCAdvisor (this, TurnsSideType.Black, new Vector2I(-1, 0)), // -1,0
|
||||
new CCElephant(this, TurnsSideType.Black, new Vector2I(-2, 0)), // -2,0
|
||||
new CCHorse (this, TurnsSideType.Black, new Vector2I(-3, 0)), // -3,0
|
||||
new CCChariot (this, TurnsSideType.Black, new Vector2I(-4, 0)), // -4,0
|
||||
new CCCannon (this, TurnsSideType.Black, new Vector2I( 3, 2)), // 3,2
|
||||
new CCCannon (this, TurnsSideType.Black, new Vector2I(-3, 2)), // -3,2
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I(-4, 3)), // -4,3
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I(-2, 3)), // -2,3
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I( 0, 3)), // 0,3
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I( 2, 3)), // -4,3
|
||||
new CCPawn (this, TurnsSideType.Black, new Vector2I( 4, 3)) // 4,3
|
||||
});
|
||||
|
||||
ArrayList redPart = InitOnePartPieces(TurnsSideType.Red, new CCPiece[] {
|
||||
new CCChariot (this, TurnsSideType.Red, new Vector2I( 4, 0)), // 4,0
|
||||
new CCHorse (this, TurnsSideType.Red, new Vector2I( 3, 0)), // 3,0
|
||||
new CCElephant(this, TurnsSideType.Red, new Vector2I( 2, 0)), // 2,0
|
||||
new CCAdvisor (this, TurnsSideType.Red, new Vector2I( 1, 0)), // 1,0
|
||||
new CCGeneral (this, TurnsSideType.Red, new Vector2I( 0, 0)), // 0,0
|
||||
new CCAdvisor (this, TurnsSideType.Red, new Vector2I(-1, 0)), // -1,0
|
||||
new CCElephant(this, TurnsSideType.Red, new Vector2I(-2, 0)), // -2,0
|
||||
new CCHorse (this, TurnsSideType.Red, new Vector2I(-3, 0)), // -3,0
|
||||
new CCChariot (this, TurnsSideType.Red, new Vector2I(-4, 0)), // -4,0
|
||||
new CCCannon (this, TurnsSideType.Red, new Vector2I( 3, 2)), // 3,2
|
||||
new CCCannon (this, TurnsSideType.Red, new Vector2I(-3, 2)), // -3,2
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I(-4, 3)), // -4,3
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I(-2, 3)), // -2,3
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I( 0, 3)), // 0,3
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I( 2, 3)), // 2,3
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I( 4, 3)) // 4,3
|
||||
});
|
||||
ArrayList redPart = InitOnePartPieces(TurnsSideType.Red, [
|
||||
new CCChariot (this, TurnsSideType.Red, new Vector2I( 4, 0)),
|
||||
new CCHorse (this, TurnsSideType.Red, new Vector2I( 3, 0)),
|
||||
new CCElephant(this, TurnsSideType.Red, new Vector2I( 2, 0)),
|
||||
new CCAdvisor (this, TurnsSideType.Red, new Vector2I( 1, 0)),
|
||||
new CCGeneral (this, TurnsSideType.Red, new Vector2I( 0, 0)),
|
||||
new CCAdvisor (this, TurnsSideType.Red, new Vector2I(-1, 0)),
|
||||
new CCElephant(this, TurnsSideType.Red, new Vector2I(-2, 0)),
|
||||
new CCHorse (this, TurnsSideType.Red, new Vector2I(-3, 0)),
|
||||
new CCChariot (this, TurnsSideType.Red, new Vector2I(-4, 0)),
|
||||
new CCCannon (this, TurnsSideType.Red, new Vector2I( 3, 2)),
|
||||
new CCCannon (this, TurnsSideType.Red, new Vector2I(-3, 2)),
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I(-4, 3)),
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I(-2, 3)),
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I( 0, 3)),
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I( 2, 3)),
|
||||
new CCPawn (this, TurnsSideType.Red, new Vector2I( 4, 3)),
|
||||
]);
|
||||
|
||||
return (blackPart, redPart);
|
||||
}
|
||||
|
||||
private ArrayList InitOnePartPieces(TurnsSideType side, CCPiece[] pieces) {
|
||||
ArrayList list = new();
|
||||
ArrayList list = [];
|
||||
foreach (var piece in pieces) {
|
||||
list.Add(piece);
|
||||
InsertPiece(piece, piece.Pos);
|
||||
|
@ -1,6 +1,8 @@
|
||||
using Vector2 = Vector.Vector2I;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using static IBoard.IBoardOn;
|
||||
|
||||
namespace ChineseChess;
|
||||
|
||||
public class ChessCore {
|
||||
@ -23,17 +25,18 @@ public class ChessCore {
|
||||
|
||||
private TurnsSideType sideType = TurnsSideType.Red;
|
||||
private readonly TurnsSideType selfSide;
|
||||
public readonly CCBoard board = new();
|
||||
public readonly CCBoard board;
|
||||
private readonly Player playerSelf;
|
||||
private readonly Player playerOpponent;
|
||||
// public EventHandler<IBoard.MoveEventArgs> OnMove;
|
||||
public ChessCore(Mode mode, TurnsSideType selfSide) {
|
||||
public ChessCore(Mode mode, TurnsSideType selfSide, ICCBoardOn? boardOn = null) {
|
||||
this.selfSide = selfSide;
|
||||
board = new(boardOn);
|
||||
|
||||
playerSelf = new(board, Player.PlayerType.Human);
|
||||
playerOpponent = new(board, Player.PlayerType.Human);
|
||||
|
||||
void func(object? _self, IBoard.MoveEventArgs record) {
|
||||
void func(object? _self, MoveEventArgs record) {
|
||||
// 防止 Undo 时 Selected Clear 出现 Null Pointer Exception
|
||||
playerSelf.SelectedClear();
|
||||
playerOpponent.SelectedClear();
|
||||
|
@ -1,6 +1,5 @@
|
||||
namespace ChineseChess;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Vector;
|
||||
@ -20,11 +19,14 @@ public class CCPiece : AbstractPiece {
|
||||
string name = "", Vector2I? pos = null) : base(name) {
|
||||
this.board = board ?? new();
|
||||
TurnsSide = turnsSide;
|
||||
OnPos += (sender, args) => {
|
||||
localPos = Global2Local(Pos);
|
||||
};
|
||||
Pos = pos is not null ? Local2Global(pos) : Vector2I.Zero;
|
||||
localPos = Global2Local(Pos);
|
||||
}
|
||||
|
||||
public override Vector2I Pos {
|
||||
get => base.Pos; set {
|
||||
base.Pos = value;
|
||||
localPos = Global2Local(Pos);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanMove(Vector2I to) {
|
||||
@ -44,18 +46,18 @@ public class CCPiece : AbstractPiece {
|
||||
}
|
||||
|
||||
public virtual List<Vector2I> CanMoveAllPosSelf() {
|
||||
return new List<Vector2I>();
|
||||
return [];
|
||||
}
|
||||
|
||||
public IEnumerable<Vector2I> CanMoveAllPosLocal() {
|
||||
var self = CanMoveAllPosSelf().Select(item => item + localPos);// 转换局部坐标
|
||||
var self = CanMoveAllPosSelf().Select(item => item + localPos);
|
||||
var ret = self.Where(item => {
|
||||
CCPiece? piece = GetCCPieceLocal(item);
|
||||
bool ret = piece is null || piece.TurnsSide != TurnsSide;
|
||||
// Console.WriteLine($"{item} can move: {ret}");
|
||||
return ret;
|
||||
}); // 过滤无效位置
|
||||
|
||||
});
|
||||
|
||||
// Console.WriteLine("localPos: {0}", localPos);
|
||||
// Console.WriteLine("CanMoveAllPosSelf: {0}", string.Join(",", self));
|
||||
// Console.WriteLine("CanMoveAllPosLocal: {0}", string.Join(",", ret));
|
||||
@ -64,7 +66,7 @@ public class CCPiece : AbstractPiece {
|
||||
|
||||
public IEnumerable<Vector2I> CanMoveAllPos() {
|
||||
var ret = CanMoveAllPosLocal()
|
||||
.Select(item => Local2Global(item)); // 转换为全局坐标
|
||||
.Select(item => Local2Global(item));
|
||||
// Console.WriteLine("CanMoveAllPos: {0}", string.Join(",", ret));
|
||||
return ret;
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ 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<IBoard.MoveEventArgs>? OnMove;
|
||||
public EventHandler<MoveEventArgs>? OnMove;
|
||||
public bool CanMove { get; set; } = true;
|
||||
|
||||
public enum PlayerType {
|
||||
@ -15,8 +16,7 @@ public class Player {
|
||||
AI
|
||||
}
|
||||
|
||||
public Player(CCBoard board, PlayerType type = PlayerType.Human)
|
||||
{
|
||||
public Player(CCBoard board, PlayerType type = PlayerType.Human) {
|
||||
this.board = board;
|
||||
this.selectedNode = new SelectedPiece(board);
|
||||
}
|
||||
@ -56,9 +56,9 @@ public class Player {
|
||||
}
|
||||
|
||||
// MUST BE THERE !!! 防止删除节点后在启动回调导致错误
|
||||
OnMove?.Invoke(this, new IBoard.MoveEventArgs
|
||||
{ From = fromPos, To = toPos, Piece = fromChess });;
|
||||
|
||||
OnMove?.Invoke(this, new MoveEventArgs
|
||||
(fromChess, fromPos, toPos));
|
||||
|
||||
if (toChess != null) {
|
||||
board.RemovePiece(toPos);
|
||||
}
|
||||
|
@ -1,32 +1,33 @@
|
||||
using System;
|
||||
using Godot;
|
||||
using Vector2I = Vector.Vector2I;
|
||||
|
||||
|
||||
public interface IBoard {
|
||||
public interface IBoardOn {
|
||||
void OnInsert(object self, IPiece piece) {}
|
||||
void OnRemove(object self, IPiece piece) {}
|
||||
void OnMove(object self, MoveEventArgs args) {}
|
||||
|
||||
void OnAddRecord(object self, MoveRecord record) {}
|
||||
void OnUndoRecord(object self, MoveRecord record) {}
|
||||
void OnSetPieceInteral(object self, SetPieceEventArgs args) {}
|
||||
record SetPieceEventArgs(IPiece? OldPiece, IPiece? NewPiece, Vector2I Pos);
|
||||
record MoveEventArgs(IPiece? Piece, Vector2I From, Vector2I To);
|
||||
}
|
||||
|
||||
public IBoardOn? On { get; protected set; }
|
||||
public int Rows { get; }
|
||||
public int Cols { get; }
|
||||
|
||||
public class SetPieceEventArgs : EventArgs {
|
||||
public IPiece? OldPiece { get; set; }
|
||||
public IPiece? NewPiece { get; set; }
|
||||
public Vector2I Pos { get; set; } = new();
|
||||
}
|
||||
|
||||
public class MoveEventArgs : EventArgs {
|
||||
public IPiece? Piece { get; set; }
|
||||
public Vector2I From { get; set; } = new();
|
||||
public Vector2I To { get; set; } = new();
|
||||
}
|
||||
|
||||
event EventHandler<IPiece> OnInsert;
|
||||
event EventHandler<IPiece> OnRemove;
|
||||
event EventHandler<MoveEventArgs> OnMove;
|
||||
event EventHandler<SetPieceEventArgs> OnSetPiece;
|
||||
|
||||
bool IsPosOutOfRange(Vector2I pos);
|
||||
IPiece? GetPiece(Vector2I pos);
|
||||
IPiece? SetPiece(IPiece piece, Vector2I pos);
|
||||
IPiece? SetPiece(IPiece? piece, Vector2I pos);
|
||||
bool InsertPiece(IPiece piece, Vector2I pos);
|
||||
bool MovePiece(Vector2I from, Vector2I to);
|
||||
IPiece? RemovePiece(Vector2I pos);
|
||||
void Clear();
|
||||
void Clear(bool clearRecords);
|
||||
void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos);
|
||||
void UndoRecord();
|
||||
record MoveRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos);
|
||||
}
|
||||
|
@ -2,17 +2,21 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Vector2I = Vector.Vector2I;
|
||||
|
||||
|
||||
public interface IPiece {
|
||||
public interface IPieceOn {
|
||||
void OnPos(object self, Vector2I oldPos) {}
|
||||
void OnMove(object self, Vector2I oldPos) {}
|
||||
void OnSelected(object self, bool oldIsSelected) {}
|
||||
void OnName(object self, string oldName) {}
|
||||
}
|
||||
|
||||
IPieceOn? On { get; protected set; }
|
||||
Vector2I Pos { get; set; }
|
||||
string Name { get; set; }
|
||||
bool IsSelected { get; set; }
|
||||
Dictionary<string, object> Data { get; set; }
|
||||
|
||||
event EventHandler<Vector2I> OnPos;
|
||||
event EventHandler<Vector2I> OnMove;
|
||||
event EventHandler<bool> OnSelected;
|
||||
event EventHandler<string> OnName;
|
||||
|
||||
bool CanMove(Vector2I to);
|
||||
bool Move(Vector2I pos);
|
||||
}
|
||||
|
@ -21,11 +21,11 @@
|
||||
<Using Include="NUnit.Framework" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- <ItemGroup>
|
||||
<ProjectReference Include="..\Chinese_Chess.csproj" />
|
||||
</ItemGroup> -->
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Scripts\Src\*.cs" />
|
||||
<ProjectReference Include="..\*.csproj" />
|
||||
</ItemGroup>
|
||||
<!-- <ItemGroup>
|
||||
<Compile Include="..\Scripts\Src\*.cs" />
|
||||
</ItemGroup> -->
|
||||
|
||||
</Project>
|
||||
|
@ -1,21 +1,147 @@
|
||||
using Vector;
|
||||
namespace Test;
|
||||
public class TestsVector
|
||||
{
|
||||
namespace Test.Vector;
|
||||
public class TestsVector2I {
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
public void Setup() {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test1()
|
||||
{
|
||||
public void TestVector2I_Constructors() {
|
||||
// Arrange & Act
|
||||
var v1 = new Vector2I();
|
||||
var v2 = new Vector2I(1, 2);
|
||||
var v3 = new Vector2I(v2);
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(() => {
|
||||
Assert.That(v1.X, Is.EqualTo(0));
|
||||
Assert.That(v1.Y, Is.EqualTo(0));
|
||||
Assert.That(v2.X, Is.EqualTo(1));
|
||||
Assert.That(v2.Y, Is.EqualTo(2));
|
||||
Assert.That(v3.X, Is.EqualTo(1));
|
||||
Assert.That(v3.Y, Is.EqualTo(2));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_Operators() {
|
||||
// Arrange
|
||||
var v1 = new Vector2I(1, 2);
|
||||
var v2 = new Vector2I(3, 4);
|
||||
|
||||
// Act
|
||||
var v3 = v1 + v2;
|
||||
var v4 = v1 - v2;
|
||||
var v5 = v1 * v2;
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(() => {
|
||||
Assert.That(v3, Is.EqualTo(new Vector2I(4, 6)));
|
||||
Assert.That(v4, Is.EqualTo(new Vector2I(-2, -2)));
|
||||
Assert.That(v5, Is.EqualTo(new Vector2I(3, 8)));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_DotProduct() {
|
||||
// Arrange
|
||||
var v1 = new Vector2I(1, 2);
|
||||
var v2 = new Vector2I(3, 4);
|
||||
|
||||
// Act
|
||||
var dotProduct = v1.Dot(v2);
|
||||
|
||||
// Assert
|
||||
Assert.That(dotProduct, Is.EqualTo(11));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_ParameterModification() {
|
||||
// Arrange
|
||||
var v1 = new Vector2I(1, 2);
|
||||
var v2 = new Vector2I(3, 4);
|
||||
|
||||
// Act
|
||||
var v3 = v1 + v2;
|
||||
var v4 = v1 - v2;
|
||||
var v5 = v1 * v2;
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(() => {
|
||||
Assert.That(v1, Is.EqualTo(new Vector2I(1, 2)), "v1 should not be modified");
|
||||
Assert.That(v2, Is.EqualTo(new Vector2I(3, 4)), "v2 should not be modified");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_Equality() {
|
||||
// Arrange
|
||||
var v1 = new Vector2I(1, 2);
|
||||
var v2 = new Vector2I(1, 2);
|
||||
var v3 = new Vector2I(3, 4);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Multiple(() => {
|
||||
Assert.That(v1, Is.EqualTo(v2));
|
||||
Assert.That(v1, Is.Not.EqualTo(v3));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_HashCode() {
|
||||
// Arrange
|
||||
var v1 = new Vector2I(1, 2);
|
||||
var v2 = new Vector2I(1, 2);
|
||||
var v3 = new Vector2I(3, 4);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Multiple(() => {
|
||||
Assert.That(v1.GetHashCode(), Is.EqualTo(v2.GetHashCode()));
|
||||
Assert.That(v1.GetHashCode(), Is.Not.EqualTo(v3.GetHashCode()));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_BoundaryValues() {
|
||||
// Arrange
|
||||
var v1 = new Vector2I(0, 0);
|
||||
var v2 = new Vector2I(-1, -2);
|
||||
var v3 = new Vector2I(int.MaxValue, int.MaxValue);
|
||||
var v4 = new Vector2I(int.MinValue, int.MinValue);
|
||||
|
||||
// Act
|
||||
var v5 = v1 + v2;
|
||||
var v6 = v1 - v2;
|
||||
var v7 = v1 * v2;
|
||||
var v8 = v3 + v4;
|
||||
var v9 = v3 - v4;
|
||||
var v10 = v3 * v4;
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(() => {
|
||||
Assert.That(v5, Is.EqualTo(new Vector2I(-1, -2)));
|
||||
Assert.That(v6, Is.EqualTo(new Vector2I(1, 2)));
|
||||
Assert.That(v7, Is.EqualTo(new Vector2I(0, 0)));
|
||||
|
||||
Assert.That(v8, Is.EqualTo(new Vector2I(-1, -1)));
|
||||
// Assert.That(v9, Is.EqualTo(new Vector2I(2 * int.MaxValue - 1, 2 * int.MaxValue - 1)));
|
||||
// Assert.That(v10, Is.EqualTo(new Vector2I(int.MaxValue * int.MinValue, int.MaxValue * int.MinValue)));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class TestsTrans2DI {
|
||||
[SetUp]
|
||||
public void Setup() {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test1() {
|
||||
Assert.Pass();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_Constructors()
|
||||
{
|
||||
public void TestVector2I_Constructors() {
|
||||
// Arrange & Act
|
||||
var v1 = new Vector2I();
|
||||
var v2 = new Vector2I(1, 2);
|
||||
@ -31,8 +157,7 @@ public class TestsVector
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVector2I_Operators()
|
||||
{
|
||||
public void TestVector2I_Operators() {
|
||||
// Arrange
|
||||
var v1 = new Vector2I(1, 2);
|
||||
var v2 = new Vector2I(3, 4);
|
||||
@ -49,8 +174,7 @@ public class TestsVector
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTrans2DI_Constructors()
|
||||
{
|
||||
public void TestTrans2DI_Constructors() {
|
||||
// Arrange & Act
|
||||
var t1 = new Trans2DI();
|
||||
var t2 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(0, 0));
|
||||
@ -76,8 +200,7 @@ public class TestsVector
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTrans2DI_Operators()
|
||||
{
|
||||
public void TestTrans2DI_Operators() {
|
||||
// Arrange
|
||||
var t1 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(1, 2));
|
||||
var v1 = new Vector2I(3, 4);
|
||||
@ -90,4 +213,51 @@ public class TestsVector
|
||||
Assert.That(v2, Is.EqualTo(new Vector2I(4, 6)));
|
||||
Assert.That(v3, Is.EqualTo(new Vector2I(2, 2)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTrans2DI_BoundaryValues() {
|
||||
// Arrange
|
||||
var t1 = new Trans2DI(new Vector2I(int.MaxValue, 0), new Vector2I(0, int.MaxValue), new Vector2I(0, 0));
|
||||
var t2 = new Trans2DI(new Vector2I(int.MinValue, 0), new Vector2I(0, int.MinValue), new Vector2I(0, 0));
|
||||
var v1 = new Vector2I(1, 1);
|
||||
|
||||
// Act
|
||||
var v2 = t1 * v1;
|
||||
var v3 = t2 * v1;
|
||||
|
||||
// Assert
|
||||
Assert.That(v2, Is.EqualTo(new Vector2I(int.MaxValue, int.MaxValue)));
|
||||
Assert.That(v3, Is.EqualTo(new Vector2I(int.MinValue, int.MinValue)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTrans2DI_SpecialValues() {
|
||||
// Arrange
|
||||
var t1 = new Trans2DI(new Vector2I(0, 0), new Vector2I(0, 0), new Vector2I(0, 0));
|
||||
var t2 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(0, 0));
|
||||
var v1 = new Vector2I(1, 1);
|
||||
|
||||
// Act
|
||||
var v2 = t1 * v1;
|
||||
var v3 = t2 * v1;
|
||||
|
||||
// Assert
|
||||
Assert.That(v2, Is.EqualTo(new Vector2I(0, 0)));
|
||||
Assert.That(v3, Is.EqualTo(new Vector2I(1, 1)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTrans2DI_Multiplication() {
|
||||
// Arrange
|
||||
var t1 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(1, 2));
|
||||
var t2 = new Trans2DI(new Vector2I(2, 0), new Vector2I(0, 2), new Vector2I(3, 4));
|
||||
|
||||
// Act
|
||||
var t3 = t1 * t2;
|
||||
|
||||
// Assert
|
||||
Assert.That(t3.XAxis, Is.EqualTo(new Vector2I(2, 0)));
|
||||
Assert.That(t3.YAxis, Is.EqualTo(new Vector2I(0, 2)));
|
||||
Assert.That(t3.Origin, Is.EqualTo(new Vector2I(5, 8)));
|
||||
}
|
||||
}
|
@ -10,10 +10,11 @@ config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="Chinese_Chess"
|
||||
config/name="ChessGame"
|
||||
config/version="0.0.5"
|
||||
run/main_scene="res://Main.tscn"
|
||||
config/features=PackedStringArray("4.3", "C#", "Mobile")
|
||||
config/icon="res://icon.svg"
|
||||
config/icon="res://Asserts/icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
@ -28,7 +29,12 @@ window/handheld/orientation=1
|
||||
|
||||
[dotnet]
|
||||
|
||||
project/assembly_name="Chinese_Chess"
|
||||
project/assembly_name="ChessGame"
|
||||
|
||||
[navigation]
|
||||
|
||||
2d/name_localized={}
|
||||
2d/version="0.0."
|
||||
|
||||
[rendering]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user