2014-11-21 28 views
1

当游戏执行时,玩家可以进入一个移动,但然后它卡在一个循环中,逻辑错误是在isWinner方法,但我不知道该怎么做没有使用一堆长长的if语句?请帮助我不能发现我的逻辑错误

public class TicTacToe { 

    public static char board[] = new char[10]; 

    public static void resetgame(){ 
     for (int x = 0; x < board.length; x++) 
      board[x] = '-'; // resets board to all - 
    } 

    public static void displayBoard(){ 
     for (int x = 1; x < board.length; x++){ 
      if (board[x] == '-') 
       System.out.print(x + " "); 
      else 
       System.out.print(board[x] + " "); 
      if (x % 3 == 0) 
       System.out.println(); 
     } 
    } 

    public static boolean isSpotEmpty(int m){ 
     return (board[m] == '-');   
    } 

    public static void getPlayerMove(){ 
     Scanner input = new Scanner(System.in); 
     System.out.print("Enter your move (1-9): "); 
     int move = input.nextInt(); 
     while (move < 1 || move > 9 || !isSpotEmpty(move)){ //validate move 
      System.out.print("Move is not valid. Reenter move (1-9): "); 
      move = input.nextInt(); 
     } 
     board[move] = 'X'; 
    } 

    public static void computerMove(){ 
     int move = ((int)(Math.random() * 9)+1);    
     while (isSpotEmpty(move)==false) 
      move = ((int)(Math.random() * 9)+1); 
     board[move] = 'O';   
    } 

    public static boolean isWinner(char ch){ 

     for(int x = 1; x < 4; x++){ 
      while (board[x] != ch) 
       return false;} 
     for(int x = 4; x < 7; x++){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 7; x < board.length; x++){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 1; x < 8; x += 3){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 2; x < 9; x += 3){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 3; x < board.length; x += 3){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 1; x < board.length; x += 4){ 
      while (board[x] != ch) 
       return false;} 
     for (int x = 3; x < 8; x += 2){ 
      while (board[x] != ch) 
       return false;} 
     return true; 
    } 

    public static boolean isFull(){ 
     boolean draw = false; 
     for (int x = 0; x < board.length; x++){ 
      while (board[x] != '-') 
       draw = true; 
     } 
     return draw; 
    } 

    public static boolean isGameDone(){ 
     if (isWinner('X')){ 
      System.out.println("Player wins!"); 
      return true; 
     } 
     if (isWinner('O')){ 
      System.out.println("You suck! Computer wins!"); 
      return true; 
     } 
     if (isFull()){ 
      System.out.println("Draw!"); 
      return true; 
     } 
     return false;   
    } 

    public static void tictactoe(){ 
     resetgame(); 
     displayBoard(); 
     while (true){ 
      getPlayerMove();   
      displayBoard(); 
      if (isGameDone()==true) return;   
      System.out.println("Computer's move!");      
      computerMove();      
      displayBoard(); 
      if (isGameDone()==true) return; 
      System.out.println("Your move!"); 
     } 
    } 

    public static void main(String[] args) { 

     tictactoe();  
    } 
} 
+0

您可以使用'switch'语句。 – 2014-11-21 05:19:26

+0

用'if'替换所有'while',看看它是否解决了这个问题。 – 2014-11-21 05:21:21

+0

尝试过......没有骰子 – Luke 2014-11-21 05:22:36

回答

0

您需要重构既isWinner()isFull()方法。你被困在一个无限循环中,因为你在检查第一个水平行后立即返回。如果这是错误的,其他循环都不会执行。

我还没有做完整的代码审查,但上面提到的bug可以通过下面的代码修复。

boolean finishedFlag = true; 
for(int x = 1; x < 4; x++){ 
    if (board[x] != ch){ 
     finishedFlag = false; 
     break; 
    } 
} 
if(finishedFlag) return finishedFlag; 

/* 

... 
Check similarly for all horizontal,vertical and diagonal 
... 

*/ 

return finishedFlag; 

这个想法是在评估所有可能性而不是在每个循环中返回函数一次。 下面的条件有利于在任何成功的结果的情况下立即返回:

if(finishedFlag) return finishedFlag; 
+0

好吧,这是有道理的。谢谢你这么好解释。我按照你解释的方式对它进行了重构,现在程序运行良好,只是不能确定赢家,或者如果板子满了,它只是让我玩,直到板子满了并卡住,即使有赢家 – Luke 2014-11-21 05:55:53

+0

@Luke很高兴知道它的工作。请不要停止我的建议,并尝试进一步重构,以便您可以使其更具可读性和简洁性。我发现了这个错误,并给出了一个快速的解决方法,如果你给予更多的思考,这个代码可以显着提高。 – toddlermenot 2014-11-21 06:01:10

+0

所以我需要条件if(finishedFlag)return finishedFlag;每个循环之后? – Luke 2014-11-21 06:01:45

0

更新的代码: 下面的代码进行测试和工作。

isWinner方法

public static boolean isWinner(char ch){ 
    boolean finishFlag = true; 
    for(int x = 1; x < 4; x++){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for(int x = 4; x < 7; x++){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 7; x < board.length; x++){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 1; x < 8; x += 3){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 2; x < 9; x += 3){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 3; x < board.length; x += 3){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 1; x < board.length; x += 4){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    if (finishFlag) 
     return finishFlag; 
    finishFlag = true; 
    for (int x = 3; x < 8; x += 2){ 
     if (board[x] != ch) { 
      finishFlag = false; 
      break; 
     } 
    } 
    return finishFlag; 
} 

isFull方法

public static boolean isFull(){ 
    boolean draw = false; 
    for (int x = 1; x < board.length; x++){ 
     if (board[x] == '-') { 
      draw = false; 
      break; 
     } else { 
      draw = true; 
     } 
    } 
    return draw; 
} 

编辑:在isFull初始化x到1,而不是0()

+0

结果是相同的,无限循环。我打算做一个for循环来检查棋盘上的每一行,每列和对角线上是否有3 X或O的组合......它不像我做的那样 – Luke 2014-11-21 05:28:10

+0

Luke,你需要重构isWinner(),该功能正在走很长的路。 – 2014-11-21 05:29:20

+0

我应该如何重构它? – Luke 2014-11-21 05:31:54

0

我会有点钝这里。您的问题是由于滥用了while运营商。让我们来看看其中的问题:

while (board[x] != '-') 
    draw = true; 

当我们在循环,我们要问:

  1. 是我的条件真的在循环的开始?
  2. 循环过程中会发生什么变化?
  3. 我的条件在循环结束时是否真实?

条件是board[x] != '-'。在循环开始时,board[x]必须不等于'-'

while循环结束时,'-'当然不会改变,因为它是一个常量字符串。

请问board[x]已经改变了吗?我们来看看while循环的主体。唯一要做的是将true分配到drawx不会改变,board[x]也不会改变。

那么,这个while循环会循环多久?看看您使用while的其他代码,并了解它们的运行方式。

+0

谢谢你的帮助。我把他们全部改为if。尽管如此,我会尽力记住那3个未来的问题 – Luke 2014-11-21 06:19:36