C#/Unity-需要帮助调试我的Chess程序-在同一类的另一个实例中创建类的实例时遇到问题



我正在创建一个国际象棋程序。我决定这样做,当一件作品被选中时,它所有可能的合法动作都会被显示出来。为了实现这一点,我必须有一个机制来预测行动的结果(例如,因为你不能采取合法的行动来控制你自己的国王(。当我开始研究计算机对手时,这也会很有用,因为人工智能需要能够提前看到几个转弯,才能做出明智的决定。

为此,我已经做到了,在每个回合开始时,都会为玩家的棋子计算出所有可能的移动,然后模拟每一个可能的移动来看看它是否会让国王受到控制。如果是,则删除该选项。我有一个名为BoardManager的主类,它控制视觉效果并包含实际的棋盘布局(在ChessBoardSim中(,还有一个类ChessBoadSIM,它的每个对象都包含一个可能的棋盘状态。ChessBoardSim可以创建ChessBoadSim的其他实例,允许模拟板的状态,提前任意圈数。

我有一个错误,我已经挣扎了5个多小时,它是在我试图重组很多代码后出现的。我已经无计可施了,我只需要一双新的眼睛。问题是,在移动时,碎片不会从原来的位置移走,而且板上一些碎片的位置似乎向上移动了两块瓷砖。根据调试,我认为问题出现在ChessBoardSim类的CalculateAllMovementOptions((中——出于某种原因,当ChessBoadSim有一个ChessBordSim子级,并且在子级中调用CalculateAll MovementOptions((函数时,它会更改父级中的数据。我在下面包含了完整的代码,我将尽我所能描述具体的问题。

问题的流程是:

1:调用BoardManager中的private void Start((。

2:程序正确绘制和填充板。创建ChessBoardSim(称为ChessPieces(以包含当前板状态的数据。

3:StartTurn((在BoardManager中调用,以便开始游戏。

4:StartTurn((调用ChessPieces.CalculateAllMovementOptions((。CalculateAll MovementOptions的预期功能是返回一个列表数组。数组中的每个列表都包含玩家棋子的合法移动。然而,这实际上似乎改变了实际的董事会数据,我不知道为什么。

  1. 当玩家试图移动一个棋子时,游戏会中断,因为棋子不在它们应该在的地方,软件无法处理它。被移动的棋子不会从原来的位置移动(尽管我尽了最大努力(,这会导致该对象有两个实例,当一段代码试图访问具有16个元素的数组的第17个元素时,导致indexoutofrange异常

如果有人能帮助我,我真的很感激,我觉得我已经在这件事上浪费了一整天,我肯定我错过了一些简单的东西。

我的代码链接是https://github.com/FC123321/Chess

Array.Clone不会创建数组的深度副本,因此当您在SimulateBoard中调用boardLayout.Clone()(并在ChessBoardSim构造函数中再次调用(时,您正在将boardLayout中的引用复制到新数组。这意味着新数组中的片段与旧数组中的相同对象。

这意味着,当您在SimulateBoard中的MovePiece中,并对复制的数组的成员调用piece.SetPosition等时,您也在设置副本源中片段的位置。

您不需要使用boardLayout.Clone(),而是需要遍历整个源数组,然后执行newBoardLayout[x,y] = new ChessPiece();,然后将值复制到新的ChessPiece。或者,您可以创建一个新的ChessPiece构造函数,它接受另一个棋子并复制那里的值:

// ChessPiece copy constructor
public ChessPiece(ChessPiece other) {
this.Position = new int[2] { other.Position[0], other.Position[1]};
this.isWhite = other.isWhite;
this.movementType = other.movementType;
this.hasMoved = other.hasMoved;
this.turnDoubleMoved = other.turnDobleMoved;
}
// instead of boardLayout.Clone() in the ChessBoardSim constructor:
for (int x=0 ; x<8;x++){
for(int y=0; y<8;y++){
if (boardLayout[x,y] != null)
this.boardLayout[x,y] = new ChessPiece(boardLayout[x,y]);
}
}

// In SimulateBoard, take out the redundant Clone call
ChessBoardSim simBoard = new ChessBoardSim(boardLayout, turnNumber);

最新更新