【问题标题】:OutOfBoundsException for TicTacToe Game; Issue: arrays?井字游戏的 OutOfBoundsException;问题:数组?
【发布时间】:2010-10-27 20:23:30
【问题描述】:

我是编写井字游戏的开端。我刚刚运行它并得到以下堆栈跟踪:

 Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
 at java.util.ArrayList.rangeCheck(ArrayList.java:571)
 at java.util.ArrayList.get(ArrayList.java:349)
 at TicTacToe.isMarked(TicTacToe.java:23)
 at TicTacToe.mark(TicTacToe.java:59)
 at TicTacToe.main(TicTacToe.java:7)

我怀疑是我设置 ArrayList 的方式有问题?我在某处读到了关于导致问题的空值,但这是我第一次处理数组,所以我不熟悉这个主题。无论如何,这是我的代码:

    import java.util.*;

    public class TicTacToe {

    public static void main(String[] args) {
    newBoard();
    ******************System.out.println(mark(1));************
    System.out.println(mark(5));
    System.out.println(mark(9));
   }

 // Creates a blank board.
 public static ArrayList<String> newBoard() {
  ArrayList<String> board = new ArrayList<String>(8);
  return board;
 }

 // Returns true if the square has been marked.
 public static boolean isMarked(int numberOfSquare) {
  if (numberOfSquare > 9 || numberOfSquare < 1) {
   throw new IllegalArgumentException("Input a valid square number.");
  }
  ************if (newBoard().get(numberOfSquare - 1) == null) {***********
   return false;
  } else
   return true;
 }

 // Returns the number of moves that have been made.
 public static int moveCount() {
  return countMove();
 }

 // If called, adds 1 to number of moves.
 public static int countMove() {
  int moveNumber = 0;
  moveNumber++;
  return moveNumber;
 }

 // Checks for a win at the specified array location and player (X or O).
 public static boolean checkForWin(int x, int y, int z, int player) {
  if (player == 0) {
   return (newBoard().get(x)).equals("O")
     && (newBoard().get(y)).equals("O")
     && (newBoard().get(y)).equals("O");
  } else {
   return (newBoard().get(x)).equals("O")
     && (newBoard().get(y)).equals("O")
     && (newBoard().get(y)).equals("O");
  }
 }

 // Places an X or O on the specified square.
 public static boolean mark(int markSquareNumber) {
  if (markSquareNumber > 9 || markSquareNumber < 1) {
   throw new IllegalArgumentException("Input a valid square number.");
  }
  ***********if (isMarked(markSquareNumber)) {*******************
   throw new IllegalArgumentException("Square is already marked.");
  }
  if (moveCount() % 2 != 0) {
   newBoard().add(markSquareNumber - 1, "X");
   countMove();
  } else {
   newBoard().add(markSquareNumber - 1, "O");
   countMove();
  }
  if (checkForWin(0, 1, 2, 1) || checkForWin(3, 4, 5, 1)
    || checkForWin(6, 7, 8, 1)) {
   System.out.println("Player-X just won horizontally!");
   return true;
  } else if (checkForWin(0, 3, 6, 1) || checkForWin(1, 4, 7, 1)
    || checkForWin(2, 5, 8, 1)) {
   System.out.println("Player-X just won vertically!");
   return true;
  } else if (checkForWin(0, 4, 5, 1) || checkForWin(2, 4, 6, 1)
    || checkForWin(0, 4, 8, 1)) {
   System.out.println("Player-X just won diagonally!");
   return true;
  }
  if (checkForWin(0, 1, 2, 0) || checkForWin(3, 4, 5, 0)
    || checkForWin(6, 7, 8, 0)) {
   System.out.println("Player-O just won horizontally!");
   return true;
  } else if (checkForWin(0, 3, 6, 0) || checkForWin(1, 4, 7, 0)
    || checkForWin(2, 5, 8, 0)) {
   System.out.println("Player-O just won vertically!");
   return true;
  } else if (checkForWin(0, 4, 5, 0) || checkForWin(2, 4, 6, 0)
    || checkForWin(0, 4, 8, 0)) {
   System.out.println("Player-O just won diagonally!");
   return true;
  } else
   return false;
 }
}

我只是在堆栈跟踪中出现的行旁边加上一大堆星号。如果有人能指出我哪里出错了,那就太好了,谢谢!

好的,这是我在您的所有精彩输入后提出的解决方案:(请仅将其用于教育和参考目的,如果您在我的 CS1410 课,你抄我!!!)

//Written by JTN for Assignment7.3- CS1410; October 2010. 
import java.util.*;

public class TicTacToe {
private static int moveNumber = 0;
private static ArrayList<String> board = new ArrayList<String>(8);
    public static void main(String[] args) {
        newBoard();
        mark(1);mark(2);
        mark(5);mark(3);
        mark(9);
        boardString();
    }
    // Returns the number of moves that have been made.
    public static int moveCount() {
        return (countMove()-1);
    }

    // If called, adds 1 to number of moves.
    public static int countMove() {
        moveNumber= moveNumber + 1;
        return moveNumber;
    }
    // Creates a blank board.
    public static ArrayList<String> newBoard() {
        for (int i = 0; i <= 8; i++)
            board.add("_");
        return board;
    }

    // Returns true if the square has been marked.
    public static boolean isMarked(int numberOfSquare) {
        if (numberOfSquare > 9 || numberOfSquare < 1) {
            throw new IllegalArgumentException("Input a valid square number.");
        }
        if ((board.get(numberOfSquare - 1)).equals("_")) {
            return false;
        } else
            return true;
    }



    // Checks for a win at the specified array location and player (X or O).
    public static boolean checkForWin(int x, int y, int z, int player) {
        if (player == 0) {
            return     (board.get(x)).equals("O")
                    && (board.get(y)).equals("O")
                    && (board.get(z)).equals("O");
        } 
        else {
            return     (board.get(x)).equals("X")
                    && (board.get(y)).equals("X")
                    && (board.get(z)).equals("X");
        }
    }

    // Places an X or O on the specified square.
    public static boolean mark(int markSquareNumber) {
        if (markSquareNumber > 9 || markSquareNumber < 1) {
            throw new IllegalArgumentException("Input a valid square number.");
        }
        if (isMarked(markSquareNumber)) {
            throw new IllegalArgumentException("Square is already marked.");
        }       
        if ((countMove() % 2) == 0){
            board.set(markSquareNumber - 1, "O");
        }
        else {
            board.set(markSquareNumber - 1, "X");
        } 

        if (checkForWin(0, 1, 2, 1) || checkForWin(3, 4, 5, 1)
                || checkForWin(6, 7, 8, 1)) {
            System.out.println("Player-X just won horizontally!");
            return true;
        } else if (checkForWin(0, 3, 6, 1) || checkForWin(1, 4, 7, 1)
                || checkForWin(2, 5, 8, 1)) {
            System.out.println("Player-X just won vertically!");
            return true;
        } else if (checkForWin(0, 4, 5, 1) || checkForWin(2, 4, 6, 1)
                || checkForWin(0, 4, 8, 1)) {
            System.out.println("Player-X just won diagonally!");
            return true;
        }
         else if (checkForWin(0, 1, 2, 0) || checkForWin(3, 4, 5, 0)
                || checkForWin(6, 7, 8, 0)) {
            System.out.println("Player-O just won horizontally!");
            return true;
        } else if (checkForWin(0, 3, 6, 0) || checkForWin(1, 4, 7, 0)
                || checkForWin(2, 5, 8, 0)) {
            System.out.println("Player-O just won vertically!");
            return true;
        } else if (checkForWin(0, 4, 5, 0) || checkForWin(2, 4, 6, 0)
                || checkForWin(0, 4, 8, 0)) {
            System.out.println("Player-O just won diagonally!");
            return true;
        } else
            return false;
    }

    public static String boardString(){
        String row1 = board.get(0)+"|"+board.get(1)+"|"+board.get(2);
        String row2 = board.get(3)+"|"+board.get(4)+"|"+board.get(5);
        String row3 = board.get(6)+"|"+board.get(7)+"|"+board.get(8);
        System.out.println(row1);
        System.out.println(row2);
        System.out.println(row3);
        return row1+row2+row3;
    }
}

【问题讨论】:

  • 你能格式化你的代码吗?选择代码,然后按编辑器顶部的 100100 按钮。
  • 请编辑您的帖子并修复代码格式。这将为您生成更多反馈/答案。 Edit 看起来像 shoebox639 打败了我。
  • 抱歉,我已将其格式化,但后来发生了什么事?现在已经修复了。
  • 只是对设计的评论:你不想在 mark() 方法中检查胜利。你的 checkForWin 方法真的应该没有参数,只返回获胜者,如果没有人获胜,则返回 -1。在检查胜利中,您可以进行硬编码检查。
  • 对不起,我不知道胜利检查的事情......关于这个问题,我只是按照我的教授告诉我们的去做。好吧,他只要求返回真或假,但这只是帮助我验证它在打印他们如何获胜以及在哪里获胜时的工作。我其实发现了一些错误,但我会在完成后立即更新和胜利。

标签: java arrays exception-handling arraylist


【解决方案1】:

这一行

ArrayList<String> board = new ArrayList<String>(8);

不会创建一个包含 8 个字符串的数组(或 9 个字符串,如果这是有意的话)。它将创建一个初始 容量 为 8 个元素但大小为 0 的 ArrayList。

为板子创建 ArrayList 后,您必须使用 add- 方法在其中填充元素。尝试执行以下操作:

public static ArrayList<String> newBoard() {
    ArrayList<String> board = new ArrayList<String>(8);
    for (int i = 0; i < 9; i++)
        board.add("");
    return board;
}

消息Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 表示您正在尝试访问长度为 0 的列表中的第 0 个元素(在没有元素的列表中)。

此外,以下行:

newBoard().add(markSquareNumber - 1, "X");

应该是

newBoard().set(markSquareNumber - 1, "X");

【讨论】:

  • 谢谢!这似乎解决了这个问题! :) 作为记录,对于这种特殊情况,它必须是 i
【解决方案2】:

列表中似乎没有初始人口。您正在尝试访问不存在的元素。

【讨论】:

    【解决方案3】:

    从无格式代码的墙上,我想我知道你的问题。

    public static ArrayList newBoard() { 
        ArrayList board = new ArrayList(8); 
        return board; 
    }
    

    不初始化数组列表中的任何内容。它目前是空的,有 0 个对象。这就是你想要的。

    public static ArrayList newBoard() { 
        ArrayList<String> board = new ArrayList<String>();
        for (int i = 0; i < 9; i++) {
            board.add("");
        }
        return board; 
    }
    

    我质疑你为什么不只使用String[],在这种情况下new String[9] 将创建 9 个实际字符串。

    顺便说一句,井字棋盘有 9 个方格,我不知道你只用 8 个方格组成。

    【讨论】:

      【解决方案4】:

      ArrayList 是一个动态结构。即使您在创建它时放置了一个“大小”,它也不会填充数组列表。如果你愿意,你可以自己填充或使用一个简单的数组。

      另外,您的 countMove() 函数始终返回 1。因为您设置了 0 并将 ++ OP 也应用到了 0。如果您想要这种行为,只需返回 1

      希望这会有所帮助。 干杯。

      【讨论】:

      • 是的,我也刚刚意识到这一点......知道如何让它在每次移动时增加吗?我不同意这样一个事实,如果 x 总是先走,那么他们将总是在奇怪的移动 1、3、5 等......所以每次一个人标记某事时都必须增加它。
      • 你可以有一个全局变量和 countMove() 只是为了增加。但是,如果您想对每个用户进行计数,您可以拥有一个数组,该数组的每个条目都是该用户的计数。
      • 一个更好更优雅的解决方案是有一个类“Player”和一个变量“moves”。每个实例都会修改它的局部变量,更加“干净”。
      • 谢谢!我想我现在已经按照我想要的方式运行了!
      【解决方案5】:

      对于像这里这样的固定数组大小,我不确定您为什么使用ArrayList,而不仅仅是一个简单的String[] 数组?如果你初始化你的数组:

      String[] board = new String[9];
      

      然后,您实际上将能够获得任何正方形的值,而不必担心超出范围。

      【讨论】:

        【解决方案6】:

        每次尝试从ArrayList&lt;String&gt; 获取元素时,您都会调用newBoard() 函数。这将每次返回一个空的ArrayList&lt;String&gt;

        您需要初始化列表,然后对该变量调用 get 函数。其他答案解释了这一点。

        【讨论】:

          【解决方案7】:

          除了上述问题之外,您似乎每次都在调用newBoard() 方法,创建一个新的ArrayList,实际上并没有人们上面所说的任何东西。这样做没有意义。您可能希望有一个单板对象来检查玩家是否赢了。

          【讨论】:

            【解决方案8】:
            newBoard().get(numberOfSquare - 1) == null)
            

            每次调用newBoard() 方法时,都会创建一个没有元素的新ArrayList 对象。 如果您尝试在空的ArrayList 上获取某些内容,您将获得IndexOutOfBoundsException

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多