0

新程序员在这里,在 Eclipse 上使用 Java 编写一个 Tictactoe 游戏。

我认为我的获胜条件有问题。它出现了错误: Game.NoughtsCrosses.(NoughtsCrosses.java:106) at Game.Main.main(Main.java:5) 的线程“main”java.lang.NullPointerException 中的异常

这是我的获胜条件。imo制作得不好,但是我在编译时遇到了问题。谁能发现为什么?泰!!

我在 3x3 网格中设置了正方形,0 -> 8。每个按钮都有自己的文本,当每个玩家单击时,这些文本设置为 X 或 O。

win条件代码:

if (square[0].getText().equals(square[1].getText()) && square[1].getText().equals(square[2].getText()) != square[0].getText().isEmpty()) {
    win = true;
}

完整的Pastebin代码

再次感谢 :) 任何问题,我可以详细说明 :D

4

6 回答 6

3

看起来其中一个正方形文本为空。需要记住的重要一件事是空字符串与 null 不同。在 java 中,如果您没有专门为 String 分配值,那么它将为空。要解决此问题,您需要在""设置游戏板时将每个方块文本显式设置为(空字符串)。

于 2013-07-11T20:30:49.943 回答
0

如果您要实施这种类型的解决方案,请为自己简化工作。根据我在上面看到的一小段代码,看起来您确实使您必须完成的工作过于复杂。

char cell0 = //get that char, be it X or O
char cell1 = //
...
char cell8 = //

现在您可以逐个比较单元格以确定胜利。您的棋盘游戏设置如下:

0 1 2
3 4 5
6 7 8

所以你可以按顺序进行:

Horizontal Solutions:
(cell0 == cell1 && cell0 == cell2)
(cell3 == cell4 && cell3 == cell5)
(cell6 == cell7 && cell6 == cell8)

Vertical Solutions
(cell0 == cell3 && cell0 == cell6)
//And so on

Cross Solutions:
(cell0 == cell4 && cell0 == cell8)
(cell2 == cell4 && cell2 == cell6)

这将检查您的胜利条件。

于 2013-07-11T20:30:19.817 回答
0

问题是您的代码中有多余的大括号,因此问题中的语句实际上出现在类的实例初始化程序块中,NoughtsCrossesJButton尚未初始化任何组件,因为在构造函数之前调用实例初始化程序,这是JButton实例化存在(但从未调用)。当您尝试调用getText数组的第一个元素时squareNullPointerException会抛出 a。

要修复删除代码包含在前面的附加大括号ActionListener

class Action implements ActionListener {
    public void actionPerformed(ActionEvent e) {
       // existing code here
/// }    remove
//}      remove
// {     remove

    // win conditions. if true, set win==true; else set win
    // here is where the compilation error is, next line
    if (square[0].getText() == square[1].getText() ...) { 
      win = true;
    } //etc
} <-- add this
于 2013-07-11T20:34:09.287 回答
0

似乎您的获胜条件检查不在您的actionPerformed代码中,而是在类级别,因此可能在窗口填充有您的按钮之前调用它。

试着把支票放在actionPerformed这样的里面:http: //pastebin.com/xRViSUzy

于 2013-07-11T20:34:10.170 回答
0

有问题的行在什么范围内(最简单地说,是哪个花括号)?

根据您的缩进来判断有点棘手,但在我看来,您的“如果”不在方法内(例如构造函数)。我猜想您打算在初始化正方形的构造函数主体中的行之后执行此行及其周围的行。相反,这些行是预先运行的,因此对“new”的调用尚未运行。

我认为,如果您进行一些重组以将这些条件移动到您的构造函数或构造后调用的另一个方法中,那么事情看起来会好很多。

希望有帮助。

于 2013-07-11T20:35:23.340 回答
0

好吧,我采用了您提供的代码,经过大量修改后,我能够制作出功能齐全的井字游戏。你所做的事情大部分都在正确的轨道上,你只需要首先从设计开始。

在我的 NoughtsCrosses 课程中,我有以下内容:

  • 类 Action 实现 ActionListener
    • 这有一个 JButton 属性,我通过构造函数传入
    • 在actionPerformed中
      • 设置文本
      • 禁用按钮
      • 增加计数器
      • 检查是否有人获胜
        • 如果有赢家或平局游戏结束设置“再玩一次?” 文本
        • 否则调用 changeTurn 函数
  • 类 Reset 实现 ActionListenter
    • 这有一个 JButton 属性,我通过构造函数传入
    • 在actionPerformed中
      • 我调用了 resetGame 函数
  • 函数 changeTurn
  • 功能重置游戏
  • 函数 checkForWinners

作为提示,这是我对 Action 类的实现和我提到的构造函数的示例

class Action implements ActionListener{ 
 private JButton button;
 public Action(JButton button){ 
  this.button = button; 
 } 
 public void actionPerformed(ActionEvent e) { 
   button.setText(letter); 
   button.setEnabled(false); 
   counter++; 
   boolean gameOver = checkForWinners(); 
   if(!gameOver) 
    changeTurn(); 
   else{ 
    newgame.setText("Play again?"); 
    newgame.addActionListener(resetButton); 
   } 
 } 
}

像这样的电话new Action(square[i])是您完成这项工作所需要的。注意:我上面提到resetButton的类的 isReset很像Action它具有与我传入的相同构造的类newgame

于 2013-07-11T20:53:47.370 回答