refactor(chess): 重构象棋程序基础结构,使用Nullable重构核心代码
- 更新了多个文件的代码结构和类型定义,提高了代码的健壮性和可维护性 - 优化了事件处理、棋子管理和移动逻辑,为后续功能扩展打下坚实基础 - 修复了一些潜在的空指针异常问题,提高了程序的稳定性 - 修复部分bug
This commit is contained in:
parent
9c619784af
commit
327c2df94d
7
.gitignore
vendored
7
.gitignore
vendored
@ -25,3 +25,10 @@ bin/
|
|||||||
*.sln
|
*.sln
|
||||||
*.error
|
*.error
|
||||||
*.key*
|
*.key*
|
||||||
|
|
||||||
|
# cs project files
|
||||||
|
!*.csproj
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
Test/bin
|
||||||
|
Test/obj
|
15
Chinese_Chess.csproj
Normal file
15
Chinese_Chess.csproj
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<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>
|
||||||
|
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||||
|
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<!-- <TreatWarningsAsErrors>true</TreatWarningsAsErrors> -->
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Test\**\*" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -4,21 +4,26 @@ using Godot.Collections;
|
|||||||
namespace RPPackage {
|
namespace RPPackage {
|
||||||
public partial class RPClientBaseEDWS : EventDrivenWebSocket {
|
public partial class RPClientBaseEDWS : EventDrivenWebSocket {
|
||||||
|
|
||||||
public delegate void RPClientEventHandler(string cmd, Dictionary data);
|
public delegate void RPClientEventHandler(string cmd, Dictionary? data);
|
||||||
public delegate void RPClientErrorHandler(string errCode, string type, string cmd, string errMsg);
|
public delegate void RPClientErrorHandler(string errCode, string type, string cmd, string errMsg);
|
||||||
|
|
||||||
public event RPClientEventHandler OnRPCUser;
|
public event RPClientEventHandler? OnRPCUser;
|
||||||
public event RPClientEventHandler OnRPCRegion;
|
public event RPClientEventHandler? OnRPCRegion;
|
||||||
public event RPClientEventHandler OnRPCSession;
|
public event RPClientEventHandler? OnRPCSession;
|
||||||
public event RPClientEventHandler OnRPCMsg;
|
public event RPClientEventHandler? OnRPCMsg;
|
||||||
public event RPClientErrorHandler OnRPCError;
|
public event RPClientErrorHandler? OnRPCError;
|
||||||
|
|
||||||
public RPClientBaseEDWS() : base() {
|
public RPClientBaseEDWS() : base() {
|
||||||
OnText += (text) => {
|
OnText += (text) => {
|
||||||
// GD.Print($"response: {text}");
|
// GD.Print($"response: {text}");
|
||||||
RPMessage msg = RPHelper.HandleIncomingMessage(text);
|
RPMessage? msg = RPHelper.HandleIncomingMessage(text);
|
||||||
|
if (msg == null) {
|
||||||
|
MakeRPCError("9999", "Unknown Msg", "Error", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (msg.Code != "0000") {
|
if (msg.Code != "0000") {
|
||||||
OnRPCError?.Invoke(msg.Code, msg.Type, msg.Cmd, msg.Data.ToString());
|
OnRPCError?.Invoke(msg.Code ?? "9999", msg.Type, msg.Cmd,
|
||||||
|
msg.Data?.ToString() ?? "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (msg.Type) {
|
switch (msg.Type) {
|
||||||
@ -35,32 +40,36 @@ public partial class RPClientBaseEDWS : EventDrivenWebSocket {
|
|||||||
OnRPCMsg?.Invoke(msg.Cmd, msg.Data);
|
OnRPCMsg?.Invoke(msg.Cmd, msg.Data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
OnRPCError?.Invoke(msg.Code, "unknown", msg.Cmd, msg.Data.ToString());
|
MakeRPCError(msg.Code, "unknown", msg.Cmd, msg.Data?.ToString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void MakeRPCError(string errCode, string type, string cmd, string errMsg) {
|
protected void MakeRPCError(string errCode, string type, string cmd, string? errMsg) {
|
||||||
this.OnRPCError?.Invoke(errCode, type, cmd, errMsg ?? "null");
|
OnRPCError?.Invoke(errCode, type, cmd, errMsg ?? "null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class RPClientEDWS : RPClientBaseEDWS {
|
public partial class RPClientEDWS : RPClientBaseEDWS {
|
||||||
string userName;
|
string? userName;
|
||||||
string userId;
|
string? userId;
|
||||||
string userToken;
|
string? userToken;
|
||||||
string regionId;
|
string? regionId;
|
||||||
|
|
||||||
public string GetUserId() { return userId; }
|
public string? GetUserId() { return userId; }
|
||||||
|
|
||||||
public delegate void SessionRecvHandle(Dictionary msg);
|
public delegate void SessionRecvHandle(Dictionary? msg);
|
||||||
public event SessionRecvHandle OnPRCSessionRecv;
|
public event SessionRecvHandle? OnPRCSessionRecv;
|
||||||
|
|
||||||
public event RPClientEventHandler OnPRCSessionExit;
|
public event RPClientEventHandler? OnPRCSessionExit;
|
||||||
|
|
||||||
public RPClientEDWS() : base() {
|
public RPClientEDWS() : base() {
|
||||||
OnRPCUser += (cmd, msg) => {
|
OnRPCUser += (cmd, msg) => {
|
||||||
|
if (msg == null) {
|
||||||
|
MakeRPCError("0000", "User", "unknown", "unknown");
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case "init":
|
case "init":
|
||||||
userId = msg["userId"].AsString();
|
userId = msg["userId"].AsString();
|
||||||
@ -113,7 +122,7 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
|
|||||||
OnRPCMsg += (cmd, msg) => {
|
OnRPCMsg += (cmd, msg) => {
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case "echo":
|
case "echo":
|
||||||
GD.Print(msg["_"].AsString());
|
GD.Print(msg?["_"].AsString());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -148,7 +157,7 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public delegate bool UserInitCallback();
|
public delegate bool UserInitCallback();
|
||||||
private UserInitCallback _userInitCallback;
|
private UserInitCallback? _userInitCallback;
|
||||||
public bool UserInit(string userName, string fingerPrint, UserInitCallback callback) {
|
public bool UserInit(string userName, string fingerPrint, UserInitCallback callback) {
|
||||||
if (this.GetIsConnected() == false) {
|
if (this.GetIsConnected() == false) {
|
||||||
return false;
|
return false;
|
||||||
@ -201,14 +210,14 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
|
|||||||
public delegate bool RegionInspectCallback(
|
public delegate bool RegionInspectCallback(
|
||||||
Array<Dictionary<string, string>> _
|
Array<Dictionary<string, string>> _
|
||||||
);
|
);
|
||||||
private RPClientEventHandler _regionRecvCallback;
|
private RPClientEventHandler? _regionRecvCallback;
|
||||||
public bool RegionInspect(string regionId, RegionInspectCallback callback) {
|
public bool RegionInspect(string regionId, RegionInspectCallback callback) {
|
||||||
if (this.GetIsConnected() == false || this.userId == null) {
|
if (this.GetIsConnected() == false || this.userId == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_regionRecvCallback = null;
|
_regionRecvCallback = null;
|
||||||
_regionRecvCallback += (cmd, msg) => {
|
_regionRecvCallback += (cmd, msg) => {
|
||||||
if (cmd != "inspect") {
|
if (cmd != "inspect" || msg == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callback(msg["_"].AsGodotArray<Dictionary<string, string>>());
|
callback(msg["_"].AsGodotArray<Dictionary<string, string>>());
|
||||||
@ -228,17 +237,18 @@ public partial class RPClientEDWS : RPClientBaseEDWS {
|
|||||||
public delegate bool SessionAckCreateCallback(
|
public delegate bool SessionAckCreateCallback(
|
||||||
string sessionId,
|
string sessionId,
|
||||||
bool res,
|
bool res,
|
||||||
string reqUserId,
|
string? reqUserId,
|
||||||
string reqUserName
|
string? reqUserName
|
||||||
);
|
);
|
||||||
private RPClientEventHandler _sessionAckCreateCallback;
|
private RPClientEventHandler? _sessionAckCreateCallback;
|
||||||
public void RegSessionAckCreateCallback(SessionAckCreateCallback recvCallback) {
|
public void RegSessionAckCreateCallback(SessionAckCreateCallback recvCallback) {
|
||||||
_sessionAckCreateCallback = null;
|
_sessionAckCreateCallback = null;
|
||||||
_sessionAckCreateCallback += (cmd, msg) => {
|
_sessionAckCreateCallback += (cmd, msg) => {
|
||||||
|
if (msg == null) return;
|
||||||
string sessionId = msg["sessionId"].AsString();
|
string sessionId = msg["sessionId"].AsString();
|
||||||
bool res = msg.ContainsKey("res") && msg["res"].AsBool();
|
bool res = msg.ContainsKey("res") && msg["res"].AsBool();
|
||||||
string reqUserId = msg.ContainsKey("reqUserId") ? msg["reqUserId"].AsString() : null;
|
string? reqUserId = msg.ContainsKey("reqUserId") ? msg["reqUserId"].AsString() : null;
|
||||||
string reqUserName = msg.ContainsKey("reqUserName") ? msg["reqUserName"].AsString() : null;
|
string? reqUserName = msg.ContainsKey("reqUserName") ? msg["reqUserName"].AsString() : null;
|
||||||
recvCallback(sessionId, res, reqUserId, reqUserName);
|
recvCallback(sessionId, res, reqUserId, reqUserName);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,14 @@ public static class RPHelper
|
|||||||
return message.ToDictionary();
|
return message.ToDictionary();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RPMessage DeserializeRPMessage(Dictionary data)
|
public static RPMessage? DeserializeRPMessage(Dictionary data)
|
||||||
{
|
{
|
||||||
return new RPMessage
|
if (!data.ContainsKey("type") || !data.ContainsKey("cmd")) {
|
||||||
{
|
return null;
|
||||||
Type = data.ContainsKey("type") ? (string)data["type"] : null,
|
}
|
||||||
Cmd = data.ContainsKey("cmd") ? (string)data["cmd"] : null,
|
return new RPMessage {
|
||||||
|
Type = (string)data["type"],
|
||||||
|
Cmd = (string)data["cmd"],
|
||||||
Code = data.ContainsKey("code") ? (string)data["code"] : null,
|
Code = data.ContainsKey("code") ? (string)data["code"] : null,
|
||||||
Uid = data.ContainsKey("uid") ? (string)data["uid"] : null,
|
Uid = data.ContainsKey("uid") ? (string)data["uid"] : null,
|
||||||
Token = data.ContainsKey("token") ? (string)data["token"] : null,
|
Token = data.ContainsKey("token") ? (string)data["token"] : null,
|
||||||
@ -28,7 +30,7 @@ public static class RPHelper
|
|||||||
ws.SendJsonEx(RPHelper.SerializeRPMessage(message));
|
ws.SendJsonEx(RPHelper.SerializeRPMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RPMessage HandleIncomingMessage(string jsonMessage)
|
public static RPMessage? HandleIncomingMessage(string jsonMessage)
|
||||||
{
|
{
|
||||||
var dataDict = Json.ParseString(jsonMessage).AsGodotDictionary();
|
var dataDict = Json.ParseString(jsonMessage).AsGodotDictionary();
|
||||||
if (dataDict != null)
|
if (dataDict != null)
|
||||||
|
@ -4,20 +4,21 @@ using Godot.Collections;
|
|||||||
namespace RPPackage {
|
namespace RPPackage {
|
||||||
public class RPMessage
|
public class RPMessage
|
||||||
{
|
{
|
||||||
public string Type { get; set; }
|
public string Type { get; set; } = string.Empty;
|
||||||
public string Cmd { get; set; }
|
public string Cmd { get; set; } = string.Empty;
|
||||||
public Dictionary Data { get; set; }
|
public Dictionary? Data { get; set; }
|
||||||
|
|
||||||
public string Uid { get; set; }
|
public string? Uid { get; set; }
|
||||||
public string Token { get; set; }
|
public string? Token { get; set; }
|
||||||
public string Code { get; set; }
|
public string? Code { get; set; }
|
||||||
public Dictionary ToDictionary()
|
public Dictionary ToDictionary()
|
||||||
{
|
{
|
||||||
var dict = new Dictionary();
|
var dict = new Dictionary {
|
||||||
if (Type != null)
|
// if (Type != null)
|
||||||
dict.Add("type", Type);
|
{ "type", Type },
|
||||||
if (Cmd != null)
|
// if (Cmd != null)
|
||||||
dict.Add("cmd", Cmd);
|
{ "cmd", Cmd }
|
||||||
|
};
|
||||||
if (Data != null)
|
if (Data != null)
|
||||||
dict.Add("data", Data);
|
dict.Add("data", Data);
|
||||||
|
|
||||||
|
@ -2,16 +2,16 @@ using Godot;
|
|||||||
using Godot.Collections;
|
using Godot.Collections;
|
||||||
|
|
||||||
public partial class EventDrivenWebSocket : WebSocketPeer {
|
public partial class EventDrivenWebSocket : WebSocketPeer {
|
||||||
public delegate void WebSocketEventHandler(string eventName, params object[] args);
|
public delegate void WebSocketEventHandler(string eventName, params object[]? args);
|
||||||
public delegate void WSBinMsgEventHandler(byte[] args);
|
public delegate void WSBinMsgEventHandler(byte[] args);
|
||||||
public delegate void WSMsgEventHandler(string args);
|
public delegate void WSMsgEventHandler(string args);
|
||||||
|
|
||||||
public event WebSocketEventHandler OnOpen;
|
public event WebSocketEventHandler? OnOpen;
|
||||||
public event WSBinMsgEventHandler OnMessage;
|
public event WSBinMsgEventHandler? OnMessage;
|
||||||
public event WSMsgEventHandler OnText;
|
public event WSMsgEventHandler? OnText;
|
||||||
public event WSBinMsgEventHandler OnBinary;
|
public event WSBinMsgEventHandler? OnBinary;
|
||||||
public event WebSocketEventHandler OnClose;
|
public event WebSocketEventHandler? OnClose;
|
||||||
public event WebSocketEventHandler OnError;
|
public event WebSocketEventHandler? OnError;
|
||||||
|
|
||||||
private bool isConnected = false;
|
private bool isConnected = false;
|
||||||
private bool isCloseEventFired = false;
|
private bool isCloseEventFired = false;
|
||||||
@ -32,7 +32,7 @@ public partial class EventDrivenWebSocket : WebSocketPeer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ConnectToUrlEx(string url, double delayTime = 3,
|
public void ConnectToUrlEx(string url, double delayTime = 3,
|
||||||
TlsOptions tlsClientOptions = null) {
|
TlsOptions? tlsClientOptions = null) {
|
||||||
if (connectingTime >= 0) {
|
if (connectingTime >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -6,20 +6,20 @@ using static IBoard;
|
|||||||
public abstract class AbstractBoard : IBoard {
|
public abstract class AbstractBoard : IBoard {
|
||||||
private readonly int rows;
|
private readonly int rows;
|
||||||
private readonly int cols;
|
private readonly int cols;
|
||||||
protected readonly IPiece[,] pieces;
|
protected readonly IPiece?[,] pieces;
|
||||||
protected readonly List<MoveRecord> moveRecords = new();
|
protected readonly List<MoveRecord> moveRecords = new();
|
||||||
protected readonly int MAX_RECORDS;
|
protected readonly int MAX_RECORDS;
|
||||||
|
|
||||||
public int Rows => rows;
|
public int Rows => rows;
|
||||||
public int Cols => cols;
|
public int Cols => cols;
|
||||||
|
|
||||||
public event EventHandler<SetPieceEventArgs> OnSetPiece;
|
public event EventHandler<SetPieceEventArgs>? OnSetPiece;
|
||||||
public event EventHandler<IPiece> OnInsert;
|
public event EventHandler<IPiece>? OnInsert;
|
||||||
public event EventHandler<IPiece> OnRemove;
|
public event EventHandler<IPiece>? OnRemove;
|
||||||
public event EventHandler<MoveEventArgs> OnMove;
|
public event EventHandler<MoveEventArgs>? OnMove;
|
||||||
|
|
||||||
public event EventHandler<MoveRecord> OnAddRecord;
|
public event EventHandler<MoveRecord>? OnAddRecord;
|
||||||
public event EventHandler<MoveRecord> OnUndoRecord;
|
public event EventHandler<MoveRecord>? OnUndoRecord;
|
||||||
|
|
||||||
public AbstractBoard(int rows, int cols, int maxRecords = int.MaxValue) {
|
public AbstractBoard(int rows, int cols, int maxRecords = int.MaxValue) {
|
||||||
this.rows = rows;
|
this.rows = rows;
|
||||||
@ -32,15 +32,15 @@ public abstract class AbstractBoard : IBoard {
|
|||||||
return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols;
|
return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IPiece GetPiece(Vector2I arrayPos) {
|
public virtual IPiece? GetPiece(Vector2I arrayPos) {
|
||||||
if (IsPosOutOfRange(arrayPos)) return null;
|
if (IsPosOutOfRange(arrayPos)) return null;
|
||||||
return pieces[arrayPos.X, arrayPos.Y];
|
return pieces[arrayPos.X, arrayPos.Y];
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IPiece SetPiece(IPiece piece, Vector2I pos) {
|
public virtual IPiece? SetPiece(IPiece? piece, Vector2I pos) {
|
||||||
if (IsPosOutOfRange(pos)) return null;
|
if (IsPosOutOfRange(pos)) return null;
|
||||||
|
|
||||||
IPiece oldPiece = pieces[pos.X, pos.Y];
|
IPiece? oldPiece = pieces[pos.X, pos.Y];
|
||||||
pieces[pos.X, pos.Y] = piece;
|
pieces[pos.X, pos.Y] = piece;
|
||||||
if (piece != null) piece.Pos = pos;
|
if (piece != null) piece.Pos = pos;
|
||||||
// if (oldPiece != null) oldPiece.Pos = Vector2I.Zero;
|
// if (oldPiece != null) oldPiece.Pos = Vector2I.Zero;
|
||||||
@ -64,8 +64,8 @@ public abstract class AbstractBoard : IBoard {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPiece piece = GetPiece(from);
|
IPiece? piece = GetPiece(from);
|
||||||
if (GetPiece(to) != null && piece == null) {
|
if (GetPiece(to) != null || piece == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,8 +75,9 @@ public abstract class AbstractBoard : IBoard {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IPiece RemovePiece(Vector2I pos) {
|
public virtual IPiece? RemovePiece(Vector2I pos) {
|
||||||
IPiece piece = GetPiece(pos);
|
IPiece? piece = GetPiece(pos);
|
||||||
|
if (piece == null) return null;
|
||||||
OnRemove?.Invoke(this, piece);
|
OnRemove?.Invoke(this, piece);
|
||||||
return SetPiece(null, pos);
|
return SetPiece(null, pos);
|
||||||
}
|
}
|
||||||
@ -96,7 +97,7 @@ public abstract class AbstractBoard : IBoard {
|
|||||||
moveRecords.Clear();
|
moveRecords.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
|
public virtual void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
|
||||||
if (moveRecords.Count >= MAX_RECORDS) {
|
if (moveRecords.Count >= MAX_RECORDS) {
|
||||||
moveRecords.RemoveAt(0);
|
moveRecords.RemoveAt(0);
|
||||||
}
|
}
|
||||||
@ -125,12 +126,12 @@ public abstract class AbstractBoard : IBoard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class MoveRecord {
|
public class MoveRecord {
|
||||||
public IPiece From { get; }
|
public IPiece? From { get; }
|
||||||
public IPiece To { get; }
|
public IPiece? To { get; }
|
||||||
public Vector2I FromPos { get; }
|
public Vector2I FromPos { get; }
|
||||||
public Vector2I ToPos { get; }
|
public Vector2I ToPos { get; }
|
||||||
|
|
||||||
public MoveRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
|
public MoveRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
|
||||||
this.From = From;
|
this.From = From;
|
||||||
this.To = To;
|
this.To = To;
|
||||||
this.ToPos = ToPos;
|
this.ToPos = ToPos;
|
||||||
|
@ -46,10 +46,10 @@ public abstract class AbstractPiece : IPiece {
|
|||||||
set => data = value;
|
set => data = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<Vector2I> OnPos;
|
public event EventHandler<Vector2I>? OnPos;
|
||||||
public event EventHandler<Vector2I> OnMove;
|
public event EventHandler<Vector2I>? OnMove;
|
||||||
public event EventHandler<bool> OnSelected;
|
public event EventHandler<bool>? OnSelected;
|
||||||
public event EventHandler<string> OnName;
|
public event EventHandler<string>? OnName;
|
||||||
|
|
||||||
public virtual bool Move(Vector2I pos) {
|
public virtual bool Move(Vector2I pos) {
|
||||||
if (!CanMove(pos)) {
|
if (!CanMove(pos)) {
|
||||||
@ -66,7 +66,7 @@ public abstract class AbstractPiece : IPiece {
|
|||||||
return $"{Name} at {pos}";
|
return $"{Name} at {pos}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractPiece(string name = "", Vector2I pos = null) {
|
public AbstractPiece(string name = "", Vector2I? pos = null) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.pos = pos ?? new();
|
this.pos = pos ?? new();
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ using Vector2I = Vector.Vector2I;
|
|||||||
namespace ChineseChess;
|
namespace ChineseChess;
|
||||||
public class CCBoard : AbstractBoard
|
public class CCBoard : AbstractBoard
|
||||||
{
|
{
|
||||||
public event EventHandler<int> OnStepsChanged;
|
public event EventHandler<int>? OnStepsChanged;
|
||||||
private int steps = 0;
|
private int steps = 0;
|
||||||
public int Steps {
|
public int Steps {
|
||||||
get => steps;
|
get => steps;
|
||||||
@ -20,7 +20,7 @@ public class CCBoard : AbstractBoard
|
|||||||
public CCBoard() : base(9, 10) {
|
public CCBoard() : base(9, 10) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddRecord(IPiece From, IPiece To, Vector2I FromPos, Vector2I ToPos) {
|
public override void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
|
||||||
base.AddRecord(From, To, FromPos, ToPos);
|
base.AddRecord(From, To, FromPos, ToPos);
|
||||||
Steps += 1;
|
Steps += 1;
|
||||||
}
|
}
|
||||||
|
@ -33,12 +33,19 @@ public class ChessCore {
|
|||||||
playerSelf = new(board, Player.PlayerType.Human);
|
playerSelf = new(board, Player.PlayerType.Human);
|
||||||
playerOpponent = new(board, Player.PlayerType.Human);
|
playerOpponent = new(board, Player.PlayerType.Human);
|
||||||
|
|
||||||
void func(object _self, IBoard.MoveEventArgs record) {
|
void func(object? _self, IBoard.MoveEventArgs record) {
|
||||||
// 防止 Undo 时 Selected Clear 出现 Null Pointer Exception
|
// 防止 Undo 时 Selected Clear 出现 Null Pointer Exception
|
||||||
playerSelf.SelectedClear();
|
playerSelf.SelectedClear();
|
||||||
playerOpponent.SelectedClear();
|
playerOpponent.SelectedClear();
|
||||||
board.AddRecord(board.GetPiece(record.From), board.GetPiece(record.To),
|
|
||||||
record.From, record.To);
|
// TODO FIXME it can be simple
|
||||||
|
if (record.From is null || record.To is null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPiece? from = record.From is not null ? board.GetPiece(record.From) : null;
|
||||||
|
IPiece? to = record.To is not null ? board.GetPiece(record.To) : null;
|
||||||
|
board.AddRecord(from, to, record.From ?? new(), record.To ?? new());
|
||||||
}
|
}
|
||||||
playerSelf.OnMove += func;
|
playerSelf.OnMove += func;
|
||||||
playerOpponent.OnMove += func;
|
playerOpponent.OnMove += func;
|
||||||
|
@ -7,7 +7,7 @@ using Vector;
|
|||||||
using static ChineseChess.ChessCore;
|
using static ChineseChess.ChessCore;
|
||||||
|
|
||||||
public class CCPiece : AbstractPiece {
|
public class CCPiece : AbstractPiece {
|
||||||
public string CNName { get; protected set; }
|
public string CNName { get; protected set; } = "unknown";
|
||||||
public TurnsSideType TurnsSide { get; }
|
public TurnsSideType TurnsSide { get; }
|
||||||
protected CCBoard board;
|
protected CCBoard board;
|
||||||
protected Vector2I localPos = new();
|
protected Vector2I localPos = new();
|
||||||
@ -16,14 +16,15 @@ public class CCPiece : AbstractPiece {
|
|||||||
new(new Vector2I(1, 0), new Vector2I(0, -1), new Vector2I(-4, 9));
|
new(new Vector2I(1, 0), new Vector2I(0, -1), new Vector2I(-4, 9));
|
||||||
static readonly Trans2DI transBlackGlobal2Local =
|
static readonly Trans2DI transBlackGlobal2Local =
|
||||||
new(new Vector2I(-1, 0), new Vector2I(0, 1), new Vector2I(4, 0));
|
new(new Vector2I(-1, 0), new Vector2I(0, 1), new Vector2I(4, 0));
|
||||||
public CCPiece(CCBoard board = null, TurnsSideType turnsSide = TurnsSideType.Red,
|
public CCPiece(CCBoard? board = null, TurnsSideType turnsSide = TurnsSideType.Red,
|
||||||
string name = "", Vector2I pos = null) : base(name) {
|
string name = "", Vector2I? pos = null) : base(name) {
|
||||||
this.board = board;
|
this.board = board ?? new();
|
||||||
TurnsSide = turnsSide;
|
TurnsSide = turnsSide;
|
||||||
OnPos += (sender, args) => {
|
OnPos += (sender, args) => {
|
||||||
localPos = Global2Local(Pos);
|
localPos = Global2Local(Pos);
|
||||||
};
|
};
|
||||||
Pos = pos != null ? Local2Global(pos) : Vector2I.Zero;
|
Pos = pos is not null ? Local2Global(pos) : Vector2I.Zero;
|
||||||
|
localPos = Global2Local(Pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanMove(Vector2I to) {
|
public override bool CanMove(Vector2I to) {
|
||||||
@ -38,8 +39,8 @@ public class CCPiece : AbstractPiece {
|
|||||||
return TurnsSide == TurnsSideType.Red ? (transRedGlobal2Local * pos) : (transBlackGlobal2Local * pos);
|
return TurnsSide == TurnsSideType.Red ? (transRedGlobal2Local * pos) : (transBlackGlobal2Local * pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CCPiece GetCCPieceLocal(in Vector2I pos) {
|
protected CCPiece? GetCCPieceLocal(in Vector2I pos) {
|
||||||
return (CCPiece)board.GetPiece(Local2Global(pos));
|
return (CCPiece?)board.GetPiece(Local2Global(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual List<Vector2I> CanMoveAllPosSelf() {
|
public virtual List<Vector2I> CanMoveAllPosSelf() {
|
||||||
@ -49,7 +50,8 @@ public class CCPiece : AbstractPiece {
|
|||||||
public IEnumerable<Vector2I> CanMoveAllPosLocal() {
|
public IEnumerable<Vector2I> CanMoveAllPosLocal() {
|
||||||
var self = CanMoveAllPosSelf().Select(item => item + localPos);// 转换局部坐标
|
var self = CanMoveAllPosSelf().Select(item => item + localPos);// 转换局部坐标
|
||||||
var ret = self.Where(item => {
|
var ret = self.Where(item => {
|
||||||
bool ret = GetCCPieceLocal(item) == null || GetCCPieceLocal(item).TurnsSide != TurnsSide;
|
CCPiece? piece = GetCCPieceLocal(item);
|
||||||
|
bool ret = piece is null || piece.TurnsSide != TurnsSide;
|
||||||
// Console.WriteLine($"{item} can move: {ret}");
|
// Console.WriteLine($"{item} can move: {ret}");
|
||||||
return ret;
|
return ret;
|
||||||
}); // 过滤无效位置
|
}); // 过滤无效位置
|
||||||
@ -71,7 +73,7 @@ public class CCPiece : AbstractPiece {
|
|||||||
return board.IsPosOutOfRange(Local2Global(pos));
|
return board.IsPosOutOfRange(Local2Global(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CCPiece GetRecursivePieceLocal(Vector2I origin, Vector2I pos) {
|
protected CCPiece? GetRecursivePieceLocal(Vector2I origin, Vector2I pos) {
|
||||||
Vector2I with = origin + pos;
|
Vector2I with = origin + pos;
|
||||||
while (!IsPosOutOfRangeLocal(with) && GetCCPieceLocal(with) == null) {
|
while (!IsPosOutOfRangeLocal(with) && GetCCPieceLocal(with) == null) {
|
||||||
with += pos;
|
with += pos;
|
||||||
|
@ -7,7 +7,7 @@ public class Player {
|
|||||||
private readonly CCBoard board;
|
private readonly CCBoard board;
|
||||||
private readonly SelectedPiece selectedNode;
|
private readonly SelectedPiece selectedNode;
|
||||||
|
|
||||||
public EventHandler<IBoard.MoveEventArgs> OnMove;
|
public EventHandler<IBoard.MoveEventArgs>? OnMove;
|
||||||
public bool CanMove { get; set; } = true;
|
public bool CanMove { get; set; } = true;
|
||||||
|
|
||||||
public enum PlayerType {
|
public enum PlayerType {
|
||||||
@ -24,7 +24,7 @@ public class Player {
|
|||||||
public void HandleBoardPosClick(Vector2I clickPos) {
|
public void HandleBoardPosClick(Vector2I clickPos) {
|
||||||
if (board.IsPosOutOfRange(clickPos)) return;
|
if (board.IsPosOutOfRange(clickPos)) return;
|
||||||
// Console.WriteLine($"VirtualBoard {clickPos} clicked");
|
// Console.WriteLine($"VirtualBoard {clickPos} clicked");
|
||||||
IPiece clickChess = board.GetPiece(clickPos);
|
IPiece? clickChess = board.GetPiece(clickPos);
|
||||||
|
|
||||||
if (!selectedNode.HasSelected()) {
|
if (!selectedNode.HasSelected()) {
|
||||||
// Select piece
|
// Select piece
|
||||||
@ -45,9 +45,10 @@ public class Player {
|
|||||||
|
|
||||||
public void MoveAndRecord(Vector2I toPos, Vector2I fromPos) {
|
public void MoveAndRecord(Vector2I toPos, Vector2I fromPos) {
|
||||||
// GD.Print($"{fromPos} move to {toPos}");
|
// GD.Print($"{fromPos} move to {toPos}");
|
||||||
IPiece toChess = board.GetPiece(toPos);
|
IPiece? toChess = board.GetPiece(toPos);
|
||||||
IPiece fromChess = board.GetPiece(fromPos);
|
IPiece? fromChess = board.GetPiece(fromPos);
|
||||||
if (fromChess != null) fromChess.IsSelected = false;
|
if (fromChess != null) fromChess.IsSelected = false;
|
||||||
|
else return;
|
||||||
|
|
||||||
selectedNode.Clear();
|
selectedNode.Clear();
|
||||||
if (!fromChess.CanMove(toPos)) {
|
if (!fromChess.CanMove(toPos)) {
|
||||||
@ -55,7 +56,8 @@ public class Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MUST BE THERE !!! 防止删除节点后在启动回调导致错误
|
// MUST BE THERE !!! 防止删除节点后在启动回调导致错误
|
||||||
OnMove?.Invoke(this, new IBoard.MoveEventArgs { From = fromPos, To = toPos });
|
OnMove?.Invoke(this, new IBoard.MoveEventArgs
|
||||||
|
{ From = fromPos, To = toPos, Piece = fromChess });;
|
||||||
|
|
||||||
if (toChess != null) {
|
if (toChess != null) {
|
||||||
board.RemovePiece(toPos);
|
board.RemovePiece(toPos);
|
||||||
@ -76,9 +78,9 @@ public class Player {
|
|||||||
private class SelectedPiece {
|
private class SelectedPiece {
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
private Vector2I selectedNodePos = Vector2I.MaxValue;
|
private Vector2I selectedNodePos = Vector2I.MaxValue;
|
||||||
private IPiece piece;
|
private IPiece? piece = null;
|
||||||
private readonly CCBoard board;
|
private readonly CCBoard board;
|
||||||
public ArrayList allowedPieces = null;
|
public ArrayList? allowedPieces = null;
|
||||||
|
|
||||||
public SelectedPiece(CCBoard board) {
|
public SelectedPiece(CCBoard board) {
|
||||||
this.board = board;
|
this.board = board;
|
||||||
@ -87,6 +89,7 @@ public class Player {
|
|||||||
public void Clear() {
|
public void Clear() {
|
||||||
if (selectedNodePos != Vector2I.MaxValue) {
|
if (selectedNodePos != Vector2I.MaxValue) {
|
||||||
selectedNodePos = Vector2I.MaxValue;
|
selectedNodePos = Vector2I.MaxValue;
|
||||||
|
if (piece != null)
|
||||||
piece.IsSelected = false;
|
piece.IsSelected = false;
|
||||||
}
|
}
|
||||||
// Console.WriteLine("SelectedPiece.Clear {0}", piece);
|
// Console.WriteLine("SelectedPiece.Clear {0}", piece);
|
||||||
@ -98,11 +101,13 @@ public class Player {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectedNodePos = pos;
|
selectedNodePos = pos;
|
||||||
|
if (piece == null)
|
||||||
|
return;
|
||||||
piece.IsSelected = true;
|
piece.IsSelected = true;
|
||||||
Console.WriteLine("SelectedPiece.SetPos {0}", piece);
|
Console.WriteLine("SelectedPiece.SetPos {0}", piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPiece GetPiece() {
|
public IPiece? GetPiece() {
|
||||||
return piece;
|
return piece;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ using Vector2I = Vector.Vector2I;
|
|||||||
|
|
||||||
namespace ChineseChess;
|
namespace ChineseChess;
|
||||||
public class CCGeneral : CCPiece {
|
public class CCGeneral : CCPiece {
|
||||||
public CCGeneral(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
|
public CCGeneral(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
|
||||||
: base(board, turnsSide, name : "General", pos) {
|
: base(board, turnsSide, name : "General", pos) {
|
||||||
if (turnsSide == TurnsSideType.Red) {
|
if (turnsSide == TurnsSideType.Red) {
|
||||||
CNName = "帅";
|
CNName = "帅";
|
||||||
@ -31,7 +31,7 @@ public class CCGeneral : CCPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CCAdvisor : CCPiece {
|
public class CCAdvisor : CCPiece {
|
||||||
public CCAdvisor(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
|
public CCAdvisor(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
|
||||||
: base(board, turnsSide, name : "Advisor", pos) {
|
: base(board, turnsSide, name : "Advisor", pos) {
|
||||||
if (turnsSide == TurnsSideType.Red) {
|
if (turnsSide == TurnsSideType.Red) {
|
||||||
CNName = "仕";
|
CNName = "仕";
|
||||||
@ -58,7 +58,7 @@ public class CCAdvisor : CCPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CCElephant : CCPiece {
|
public class CCElephant : CCPiece {
|
||||||
public CCElephant(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
|
public CCElephant(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
|
||||||
: base(board, turnsSide, name : "Bishop", pos) {
|
: base(board, turnsSide, name : "Bishop", pos) {
|
||||||
if (turnsSide == TurnsSideType.Red) {
|
if (turnsSide == TurnsSideType.Red) {
|
||||||
CNName = "相";
|
CNName = "相";
|
||||||
@ -85,7 +85,7 @@ public class CCElephant : CCPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CCHorse : CCPiece {
|
public class CCHorse : CCPiece {
|
||||||
public CCHorse(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
|
public CCHorse(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
|
||||||
: base(board, turnsSide, name : "Horse", pos) {
|
: base(board, turnsSide, name : "Horse", pos) {
|
||||||
if (turnsSide == TurnsSideType.Red) {
|
if (turnsSide == TurnsSideType.Red) {
|
||||||
CNName = "馬";
|
CNName = "馬";
|
||||||
@ -125,7 +125,7 @@ public class CCHorse : CCPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CCChariot : CCPiece {
|
public class CCChariot : CCPiece {
|
||||||
public CCChariot(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
|
public CCChariot(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
|
||||||
: base(board, turnsSide, name : "Chariot", pos) {
|
: base(board, turnsSide, name : "Chariot", pos) {
|
||||||
if (turnsSide == TurnsSideType.Red) {
|
if (turnsSide == TurnsSideType.Red) {
|
||||||
CNName = "車";
|
CNName = "車";
|
||||||
@ -145,7 +145,7 @@ public class CCChariot : CCPiece {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (GetCCPieceLocal(ptr) != null) {
|
if (GetCCPieceLocal(ptr) != null) {
|
||||||
list.Add(ptr);
|
list.Add(ptr - localPos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list.Add(ptr - localPos);
|
list.Add(ptr - localPos);
|
||||||
@ -161,7 +161,7 @@ public class CCChariot : CCPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CCCannon : CCPiece {
|
public class CCCannon : CCPiece {
|
||||||
public CCCannon(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
|
public CCCannon(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
|
||||||
: base(board, turnsSide, name : "Cannon", pos) {
|
: base(board, turnsSide, name : "Cannon", pos) {
|
||||||
if (turnsSide == TurnsSideType.Red) {
|
if (turnsSide == TurnsSideType.Red) {
|
||||||
CNName = "砲";
|
CNName = "砲";
|
||||||
@ -202,7 +202,7 @@ public class CCCannon : CCPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CCPawn : CCPiece {
|
public class CCPawn : CCPiece {
|
||||||
public CCPawn(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I pos = null)
|
public CCPawn(CCBoard board, TurnsSideType turnsSide = TurnsSideType.Red, Vector2I? pos = null)
|
||||||
: base(board, turnsSide, name : "Pawn", pos) {
|
: base(board, turnsSide, name : "Pawn", pos) {
|
||||||
if (turnsSide == TurnsSideType.Red) {
|
if (turnsSide == TurnsSideType.Red) {
|
||||||
CNName = "兵";
|
CNName = "兵";
|
||||||
|
@ -6,15 +6,15 @@ public interface IBoard {
|
|||||||
public int Cols { get; }
|
public int Cols { get; }
|
||||||
|
|
||||||
public class SetPieceEventArgs : EventArgs {
|
public class SetPieceEventArgs : EventArgs {
|
||||||
public IPiece OldPiece { get; set; }
|
public IPiece? OldPiece { get; set; }
|
||||||
public IPiece NewPiece { get; set; }
|
public IPiece? NewPiece { get; set; }
|
||||||
public Vector2I Pos { get; set; }
|
public Vector2I Pos { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MoveEventArgs : EventArgs {
|
public class MoveEventArgs : EventArgs {
|
||||||
public IPiece Piece { get; set; }
|
public IPiece? Piece { get; set; }
|
||||||
public Vector2I From { get; set; }
|
public Vector2I From { get; set; } = new();
|
||||||
public Vector2I To { get; set; }
|
public Vector2I To { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
event EventHandler<IPiece> OnInsert;
|
event EventHandler<IPiece> OnInsert;
|
||||||
@ -23,10 +23,10 @@ public interface IBoard {
|
|||||||
event EventHandler<SetPieceEventArgs> OnSetPiece;
|
event EventHandler<SetPieceEventArgs> OnSetPiece;
|
||||||
|
|
||||||
bool IsPosOutOfRange(Vector2I pos);
|
bool IsPosOutOfRange(Vector2I pos);
|
||||||
IPiece GetPiece(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 InsertPiece(IPiece piece, Vector2I pos);
|
||||||
bool MovePiece(Vector2I from, Vector2I to);
|
bool MovePiece(Vector2I from, Vector2I to);
|
||||||
IPiece RemovePiece(Vector2I pos);
|
IPiece? RemovePiece(Vector2I pos);
|
||||||
void Clear();
|
void Clear();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ public class Vector2I {
|
|||||||
return X * with.X + Y * with.Y;
|
return X * with.X + Y * with.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object? obj) {
|
||||||
if (obj is Vector2I other) {
|
if (obj is Vector2I other) {
|
||||||
return this == other;
|
return this == other;
|
||||||
}
|
}
|
||||||
|
0
Test/.gdignore
Normal file
0
Test/.gdignore
Normal file
31
Test/Test.csproj
Normal file
31
Test/Test.csproj
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.14.0" />
|
||||||
|
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="NUnit.Framework" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- <ItemGroup>
|
||||||
|
<ProjectReference Include="..\Chinese_Chess.csproj" />
|
||||||
|
</ItemGroup> -->
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\Scripts\Src\*.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
16
Test/UnitTest1.cs
Normal file
16
Test/UnitTest1.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Vector;
|
||||||
|
|
||||||
|
namespace Test;
|
||||||
|
public class Tests
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
Assert.Pass();
|
||||||
|
}
|
||||||
|
}
|
93
Test/src/TestVector.cs
Normal file
93
Test/src/TestVector.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using Vector;
|
||||||
|
namespace Test;
|
||||||
|
public class TestsVector
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
Assert.Pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestVector2I_Constructors()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var v1 = new Vector2I();
|
||||||
|
var v2 = new Vector2I(1, 2);
|
||||||
|
var v3 = new Vector2I(v2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
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.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 TestTrans2DI_Constructors()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var t1 = new Trans2DI();
|
||||||
|
var t2 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(0, 0));
|
||||||
|
var t3 = new Trans2DI(t2);
|
||||||
|
var t4 = new Trans2DI(1, 0, 0, 1, 0, 0);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(t1.XAxis, Is.EqualTo(new Vector2I(1, 0)));
|
||||||
|
Assert.That(t1.YAxis, Is.EqualTo(new Vector2I(0, 1)));
|
||||||
|
Assert.That(t1.Origin, Is.EqualTo(new Vector2I(0, 0)));
|
||||||
|
|
||||||
|
Assert.That(t2.XAxis, Is.EqualTo(new Vector2I(1, 0)));
|
||||||
|
Assert.That(t2.YAxis, Is.EqualTo(new Vector2I(0, 1)));
|
||||||
|
Assert.That(t2.Origin, Is.EqualTo(new Vector2I(0, 0)));
|
||||||
|
|
||||||
|
Assert.That(t3.XAxis, Is.EqualTo(new Vector2I(1, 0)));
|
||||||
|
Assert.That(t3.YAxis, Is.EqualTo(new Vector2I(0, 1)));
|
||||||
|
Assert.That(t3.Origin, Is.EqualTo(new Vector2I(0, 0)));
|
||||||
|
|
||||||
|
Assert.That(t4.XAxis, Is.EqualTo(new Vector2I(1, 0)));
|
||||||
|
Assert.That(t4.YAxis, Is.EqualTo(new Vector2I(0, 1)));
|
||||||
|
Assert.That(t4.Origin, Is.EqualTo(new Vector2I(0, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var v2 = t1 * v1;
|
||||||
|
var v3 = v1 * t1;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(v2, Is.EqualTo(new Vector2I(4, 6)));
|
||||||
|
Assert.That(v3, Is.EqualTo(new Vector2I(2, 2)));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user