0

首先,我希望允许我在这里寻求一些调试帮助。话虽如此,我已经创建了这个简单的小井字游戏,基本上已经完成了,但是这个语义错误一直在杀死我。

显然,我花了一些时间试图自己找出问题所在,但你可以说我已经放弃了,所以我现在就在这里 :)

对于一些简要概述,该板由 char ttt[3][3] 类型的数组表示。玩家也是 char 类型的变量,因此它们不是“X”就是“O”,棋盘坐标以字母形式输入:

示例运行将如下所示:

********************************
  ---a------b------c---
  |      |      |     |
  ---d------e------f---
  |      |      |     |
  ---g------h------i---
  |      |      |     |
  ---------------------
player1: O, it is your turn.
Select a cell [a, b, c, ... i]
a
********************************
  ---a------b------c---
  |  O   |      |     |
  ---d------e------f---
  |      |      |     |
  ---g------h------i---
  |      |      |     |
  ---------------------
player2: X, it is your turn.
Select a cell [a, b, c, ... i]

数组 ttt[3][3] 被初始化,使得每个元素都只是 ' '。

在大多数情况下,程序运行良好。为了为你们节省一些时间,我相信以下方法运行良好

  • 布尔获胜者(字符播放器)
  • 布尔游戏IsDraw()
  • 无效的显示板()
  • 字符串播放器ID(字符播放器)
  • 和主要方法

我确实看到问题很可能包含在我的 getPlayerInput(char player) 方法中:

void getPlayerInput(char player)
{       
    int row = 0;
    int col = 0;

    System.out.println(playerID(player) + ", it is your turn.");
    System.out.println("Select a cell [a, b, c, ... i]");

    char answer;
    answer = scan.next().charAt(0);

    switch(answer)
    {
    case 'a':
        row = 0;
        col = 0;
        break;          
    case 'b':
        row = 0;
        col = 1;
        break;          
    case 'c':
        row = 0;
        col = 2;
        break;          
    case 'd':
        row = 1;
        col = 0;
        break;          
    case 'e':
        row = 1;
        col = 1;
        break;          
    case 'f':
        row = 1;
        col = 2;
        break;
    case 'g':
        row = 2;
        col = 0;
        break;
    case 'h':
        row = 2;
        col = 1;
        break;
    case 'i':
        row = 2;
        col = 2;
        break;

    default:
        System.out.println("Invalid location, try again.");
        getPlayerInput(player);             
    }

    if(ttt[row][col] != ' ')
    {
        System.out.println("This square is taken. Try again.");
        getPlayerInput(player);
    }
    else
    {
        ttt[row][col] = player;
    }            
}

对我来说,它看起来不错,但我的输出表明并非如此。该方法包括两个故障保险,

  1. 如果用户输入了超出棋盘范围的内容('a' 到 'i' 之外的字符),

  2. 或者如果用户在板上选择了已经被另一个“X”或“O”占据的字母/位置。

在这两种情况下,该方法都会打印出输入了一些错误的输入,然后再次调用 getPlayerInput()。

我通过调试注意到的是,如果只输入有效的输入,程序似乎运行良好。但是,如果输入了错误的输入(任一类型),然后输入了有效的输入,有时该方法会打印仍然输入了错误的输入。

例如,

********************************
  ---a------b------c---
  |      |      |     |
  ---d------e------f---
  |      |      |     |
  ---g------h------i---
  |      |      |     |
  ---------------------
player1: O, it is your turn.
Select a cell [a, b, c, ... i]
a
********************************
  ---a------b------c---
  |  O   |      |     |
  ---d------e------f---
  |      |      |     |
  ---g------h------i---
  |      |      |     |
  ---------------------
player2: X, it is your turn.
Select a cell [a, b, c, ... i]
z
Invalid location, try again.
player2: X, it is your turn.
Select a cell [a, b, c, ... i]
e
This square is taken. Try again.
player2: X, it is your turn.
Select a cell [a, b, c, ... i]
f
********************************
  ---a------b------c---
  |  O   |      |     |
  ---d------e------f---
  |      |  X   |  X  |
  ---g------h------i---
  |      |      |     |
  ---------------------
player1: O, it is your turn.
Select a cell [a, b, c, ... i]

请注意,我输入了 char 的 azef。'z' 显然是一个无效字符,因此该方法按预期工作(到目前为止),打印出它是无效输入,然后该方法再次运行,要求输入。然后输入了“e”,显然是一个有效的位置,但是该方法打印出“正方形已经被占用”,而显然不是。但是,输入不同的字符“f”允许我退出它。

最终结果是玩家“X”有两个回合并填满了“e”和“f”两个方格。

应该注意的是,如果用户不断输入错误的输入,他应该一直停留在该方法中,直到输入有效的输入,但这显然是一个好的输入被误解为错误输入的情况,并且循环可以'除非输入了不同的良好输入实例,否则将退出。

所以,说了这么多,帮助meee?无论如何,我非常感谢任何有耐心读到这里的人......

如果您想自己运行代码,以下是源代码:

import java.util.*;

class TicTacToe
{
    char ttt[][] = new char[3][3];
    static final char player1 = 'O';
    static final char player2 = 'X';
    Scanner scan  =new Scanner(System.in);


    String playerID(char player)
    {    
        if (player == player1)
            return "player1: "+player;
        else
            return "player2: "+ player;
    }

    void getPlayerInput(char player)
    {       
        int row = 0;
        int col = 0;

        System.out.println(playerID(player) + ", it is your turn.");
        System.out.println("Select a cell [a, b, c, ... i]");

        char answer;
        answer = scan.next().charAt(0);

        switch(answer)
        {
        case 'a':
            row = 0;
            col = 0;
            break;          
        case 'b':
            row = 0;
            col = 1;
            break;          
        case 'c':
            row = 0;
            col = 2;
            break;          
        case 'd':
            row = 1;
            col = 0;
            break;          
        case 'e':
            row = 1;
            col = 1;
            break;          
        case 'f':
            row = 1;
            col = 2;
            break;
        case 'g':
            row = 2;
            col = 0;
            break;
        case 'h':
            row = 2;
            col = 1;
            break;
        case 'i':
            row = 2;
            col = 2;
            break;

        default:
            System.out.println("Invalid location, try again.");
            getPlayerInput(player);             
        }

        if(ttt[row][col] != ' ')
        {
            System.out.println("This square is taken. Try again.");
            getPlayerInput(player);
        }
        else
        {
            ttt[row][col] = player;
        }            
    }

    boolean gameIsDraw()
    {       
        boolean isDraw = true;
        for(int i = 0; i < 3; i++)
        {
            for(int j = 0; j < 3; j++)
            {
                if(ttt[i][j] == ' ')
                {
                    isDraw = false;
                }
            }
        }

        return isDraw;
    }

    boolean winner(char player)
    {
        boolean hasWon = false;

        // possible horizontal wins
        for(int i = 0; i < 3; i++)
        {
            if(ttt[i][0] == player && ttt[i][1] == player && ttt[i][2] == player)
            {
                hasWon = true;
            }
        }

        // possible vertical wins
        for(int i = 0; i < 3; i++)
        {
            if(ttt[0][i] == player && ttt[1][i] == player && ttt[2][i] == player)
            {
                hasWon = true;
            }
        }

        // one diagonal win    
        if(ttt[0][0] == player && ttt[1][1] == player && ttt[2][2] == player)
        {
            hasWon = true;
        }

        // other diagonal win
        if(ttt[0][2] == player && ttt[1][1] == player && ttt[2][0] == player)
        {
            hasWon = true;
        }

        return hasWon;
    }


void displayBoard()
    {
        System.out.println("********************************");        
        System.out.println("      ---a------b------c---");

        for (int i=0; i<3; i++)
        {
            for (int j=0; j< 3; j++)
            {
              if (j == 0) System.out.print("      |  "); 
              System.out.print(ttt[i][j]);
              if (j < 2) System.out.print( "   |  ");
              if (j==2)  System.out.print("  |");
            }
            System.out.println();
            switch (i)
            {
            case 0:
                System.out.println("      ---d------e------f---");
                break;
            case 1:
                System.out.println("      ---g------h------i---");
                break;
            case 2:
                System.out.println("      ---------------------");
                break;
            }
        }
    }


void newgame()
{
    char currPlayer = player1;
    for(int i=0; i<3; i++)
        for(int j=0; j<3; j++)
            ttt[i][j] =' ';

    boolean continueFlag = true;        
    while (continueFlag)
    {
        displayBoard();
        if (gameIsDraw())
        {
            System.out.println("Game Ends in Draw");
            continueFlag = false;
        }
        else
        {
            getPlayerInput(currPlayer);
            if (winner(currPlayer))
            {
                System.out.println("We have a winner: " + playerID(currPlayer));
                displayBoard();
                continueFlag = false;
            }
            else
            { 
                if (currPlayer == player1) currPlayer = player2;
                    else currPlayer = player1;
            }
         }
    }

}


public static void main(String[] args)
{
    TicTacToe game = new TicTacToe();
    String str;
    do
    {
        game.newgame();

        System.out.println("Do you want to play Tic-Tac-Toe (y/n)?");
        str= game.scan.next();
    } while ("y".equals(str));

    System.out.println("Bye");
}    
} 
4

1 回答 1

1

真正的问题是getPlayerInput递归地调用自己。如果row并且column被初始化为错误值而不是实际值(例如int row = -1;. 递归通常非常适合大型问题,这些问题在拆分为较小的相同问题时更容易处理。在这种情况下,问题只是获得一个有效的输入,这个任务不能分解成更简单的任务。

该方法应该使用迭代来进行输入验证,而不是递归。例如:

void getPlayerInput(char player) {       
    int row = -1;
    int col = -1;

    System.out.println(playerID(player) + ", it is your turn.");

    while(row==-1) {
        System.out.println("Select a cell [a, b, c, ... i]");

        char answer;
        answer = scan.next().charAt(0);

        switch(answer) {
        case 'a':
            row = 0;
            col = 0;
            break;          
        // <snip>
        default:
            System.out.println("Invalid location, try again.");
        }
        if(row !- -1 && ttt[row][col] != ' ') {
            System.out.println("This square is taken. Try again.");
            row = -1;
        }
    }
    ttt[row][col] = player;
}
于 2013-08-04T05:41:05.687 回答