我正在为我的入门CS类创建一个可逆游戏。
我在SearchN((中发现了一个错误,会导致它给出错误的playableN标志,并创建了isSame((作为解决方案。
现在,当我尝试移动时,游戏崩溃了。
我有一个隔离到isPlayable((的错误,它导致程序停止运行而没有错误消息。
我以为是因为程序搜索超出了范围;然而,当我运行.isPlayable(0,0(时,它会返回一个NullPointerException(我也不太知道如何消除它(。
所以在处理未播放的空格时一定有一些错误。
有人有什么想法吗?
/**
* a method to return the color of a tile
*@params x y tile coordinates
*/
public Color getColor(int x, int y){
try{
return buttons[x][y].getBackground();
}
catch(ArrayIndexOutOfBoundsException e){
return null;
}
}
/**
* a method to determine whether a tile has been played
*@params x y tile coordinates
*/
public boolean isPlayed(int x, int y){
if(this.isBlack(x,y) || this.isWhite(x,y)){
return true;
}else{
return false;
}
}
/**
* a method to determine whether a tile has a color opposite to a given color
*@params x y c tile coordinates and color to compare
*/
public boolean isOpposite(int x, int y, Color c){
if(this.isPlayed(x,y)){
return(!(this.getColor(x,y).equals(c)));
} else
return false; // this was giving the false playableN flag
}
/**
* a method to determine weather a tile has the same color as the one given
*@params x y c tile coordinates and color to compare
*/
public boolean isSame(int x, int y, Color c){
if(this.isPlayed(x,y)){
return(this.getColor(x,y).equals(c));
}else{
return false;
}
}
/**
* a method used to check tiles north of an attempted play to verify legal moves
*@params x y c tile coordinates and comparing color
*/
public void searchN(int x, int y, int increment, Color c){
if(increment>1 && (this.isSame(x-increment,y, c))){
playableN = true;
leadN = false;
} else {
if(this.isOpposite(x-increment,y,c)){
leadN=true;
}
}
}
/**
* a method used to determine if a tile is playable
*@params x y tile coordinates
*/
public boolean isPlayable(int x, int y){
this.searchN(x,y,1,turnColor);
// search 7 other directions
while(leadN||leadNE||leadE||leadSE||leadS||leadSW||leadW||leadNW){
int i = 2;
if(leadN)
this.searchN(x,y,i,turnColor);
// search 7 other directions
i++;
}
if(playableN||playableNE||playableE||playableSE||playableS||playableSW||playableW||playableNW)
return true;
else
return false;
}
**所有瓷砖都是黑色、白色或默认瓷砖颜色(绿色(,并且在gridLayout((中显示的JButtons的2D阵列中。
我看到了NullPointerException
发生的两种方式:
您在getColor
中得到一个ArrayIndexOutOfBoundsException
。在这种情况下,您将捕获异常并返回null
。
或
CCD_ 5正在返回CCD_。
在任何一种情况下,getColor
都将返回null
,这将导致在isOpposite
或isSame
中调用.equals
时抛出NullPointerException
。
在尝试对getColor调用.equals
之前,您应该检查它的结果。然后您应该弄清楚getBackground
返回null
或抛出ArrayIndexOutOfBoundsException
的原因。
因为@goto10已经给出了你需要寻找的方向,这里还有一些其他注意事项:
-
你需要学会更好地分离关注点。特别是,您将显示代码与游戏规则代码混合在一起。有了正确的设计,几乎所有的程序都应该可以从命令行运行——GUI只是来帮助最终用户。
-
当您有两个(或多个(相关参数时,实际上只有一个参数——一个包含它们的复合类。例如,用于搜索数组的
x
和y
参数实际上代表一个CoordinatePair
、Location
或Point
实例。尽管这种可能性很小,但这将有助于避免未来出现问题——例如,如果有人意外地交换了searchN()
中的y
和increment
参数,会发生什么?编写一个不可变的Point
类并使用它——它将完全消除这个问题:public final class Point { // Yes, public variables are almost universally frowned upon, with good reason. // Here, though, it's kind of the 'point' public final int x; public final int y; // Note: private constructor - can't call this from outside. private Point(final int x, final int y) { this.x = x; this.y = y; } // Static factory method for construction instead. // It is left as an exercise for the reader to implement caching. public static Point fromCoordinates(final int x, final int y) { return new Point(x, y); } }
您需要实现一个好的
.hashCode()
和.equals()
方法来实现这一点,但Eclipse(或任何其他好的工具(所提供的应该是好的。使用不可变对象有一些性能方面的考虑,但对于您的需要,这不是问题。 -
努力使方法具有尽可能少的副作用;也就是说,试着让它们尽可能少地修改(最好是NO(外部状态。此包含状态,该状态是对象(如
leadN
(的一部分,但在其他方面不是方法的"一部分"。副作用使人们很难对对象的状态进行"推理"(弄清楚发生了什么(,并使良好的测试成为真正的噩梦。编写仅依赖于传入对象的(希望是不可变的(状态和"主机"(this
(对象的不可变状态的方法可能会更困难,但更容易推理;几乎所有(或者可能完全(不可变的系统更容易思考,并且可以免费获得线程安全/并行执行。 -
你的方法
.isSame()
和.isOpposite()
有点乱,因为播放/未播放的正方形之间的唯一区别是它的颜色。相关的规则端代码应该不知道显示端代码——没有绿色边的棋子(从技术上讲,也没有白色或黑色棋子(——有一个棋子是给玩家1的,还有一个棋子给玩家2的。即使在现实世界中,这也是一种仅显示的效果,而写着"白人获得4.5分"的规则实际上意味着"第二名的玩家获得4.5分的额外分数"(。此外,这两种方法不会为未播放的正方形返回相反的结果(.isSame()
返回false(,这是不合乎逻辑的。 -
每当您有一个类似元素的长列表(
leadX
和playableX
变量集(时,请尝试将它们重新格式化为实际列表。如果你想制作一个3D版本,这也会有很大帮助。。。此外,还有一种方法可以使用所谓的策略模式(以及哈希图或数组列表(,使在不同方向上移动/搜索更加容易。