首先,我希望我可以在这里请求一些调试帮助。这就是说, 我已经创建了这个简单的小型tic tac脚趾程序,它基本上完成了,但是这个语义错误一直在困扰着我。Java中基本Tictactoe程序的语义错误
很显然,我花了一些时间,试图找出问题上我自己的,但是你可以说,我已经放弃了对所以这里我现在:)
对于一些简要概述,该板由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]被初始化,使得每个元素都是''。
大部分程序运行良好。为了尽量节省一些时间,你们这些家伙,我相信下面的方法是完全运行
- 布尔赢家(焦球员)
- 布尔gameIsDraw()
- 无效displayBoard()
- 字符串playerID(焦球员)
- 和主要方法
在那里我确实看到了问题最有可能包含我内getPlayerInput(焦球员)方法:
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;
}
}
对我来说,它看起来不错,但我的输出另有指示。该方法包括两个failsafes,
如果用户输入的东西的板范围外(的“a”到“I”外字符),
,或者如果用户选择了信/位置在已经被另一个'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]
通知是A-Z-E-F。 'z'显然是一个无效字符,所以该方法按照预期工作(到目前为止),打印出它是无效输入,然后该方法再次运行,要求输入。然后输入'e',这显然是一个有效的位置,但是当显然没有时,该方法打印出“方块已经被占用”。但是,输入一个不同的char'f'可以让我退出它。
最终的结果是玩家'X'有两圈,并填充了'e'和'f'两个方格。
需要注意的是,如果用户不断输入错误的输入,那么他应该被卡在该方法中直到输入有效的输入,但是很明显这种情况下好的输入被错误解释为错误的输入,并且除非输入一个不同的输入实例,否则不能退出循环。
所以,有了这一切,帮助我?无论如何,我非常欣赏的人谁是有耐心看完这么远......
如果你喜欢跑自己的代码,这是源:
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");
}
}
谢谢你!除了你的帮助之外,我还睡在上面并且弄清楚了。我会提到,不幸的是,你的建议会导致运行时错误,因为如果输入错误输入,if语句会检查超出范围的位置,但这很容易通过另一个while循环进行修复。使用迭代而不是递归的关键思想我确定是主要观点。不过,如果你能解释为什么递归不是一个有效的策略吗? – HelloMyNameIsRay
我尝试添加更多解释并修复代码。在任何情况下,RuntimeException正是你想要的!有些事情是错误的,它失败了。在原始代码中,由于行,列最初设置为0,0,所以错误的输入总是会导致尝试在0,0平方中播放。如果采用这个方块,递归调用会给用户另一次机会进行第二次递归调用(记住第一次发生在交换机的默认块中),基本上使用户获得的输入尝试次数加倍。 –