在课堂上,我们的任务是创建一个二维数组并围绕它创建一个井字游戏。除了显示整个棋盘已满并且游戏是平局时,我已经完成了所有工作。我尝试过一些东西,但我没有找到解决方案,我需要一些帮助...这是我的代码:
import java.util.Scanner;
public class TicTacToe {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int row, column;
char player = 'X';
//create 2 dimensional array for tic tac toe board
char[][] board = new char[3][3];
char ch = '1';
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
board[i][j] = ch++;
}
}
displayBoard(board);
while(!winner(board) == true){
//get input for row/column
System.out.println("Enter a row and column (0, 1, or 2); for player " + player + ":");
row = in.nextInt();
column = in.nextInt();
//occupied
while (board[row][column] == 'X' || board[row][column] == 'O') {
System.out.println("This spot is occupied. Please try again");
}
//place the X
board[row][column] = player;
displayBoard(board);
if (winner(board)){
System.out.println("Player " + player + " is the winner!");
}
//time to swap players after each go.
if (player == 'O') {
player = 'X';
}
else {
player = 'O';
}
if (winner(board) == false) {
System.out.println("The game is a draw. Please try again.");
}
}
private static void displayBoard(char[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
if (j == board[i].length - 1) System.out.print(board[i][j]);
else System.out.print( board[i][j] + " | ");
}
System.out.println();
}
}
//method to determine whether there is an x or an o in the spot
public static Boolean winner(char[][] board){
for (int i = 0; i< board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == 'O' || board[i][j] == 'X') {
return false;
}
}
}
return (board[0][0] == board [0][1] && board[0][0] == board [0][2]) ||
(board[0][0] == board [1][1] && board[0][0] == board [2][2]) ||
(board[0][0] == board [1][0] && board[0][0] == board [2][0]) ||
(board[2][0] == board [2][1] && board[2][0] == board [2][2]) ||
(board[2][0] == board [1][1] && board[0][0] == board [0][2]) ||
(board[0][2] == board [1][2] && board[0][2] == board [2][2]) ||
(board[0][1] == board [1][1] && board[0][1] == board [2][1]) ||
(board[1][0] == board [1][1] && board[1][0] == board [1][2]);
}
}
我想要输出说当电路板已满时电路板已满,但我什么都没得到。这是我输出的最后一行,正如您所看到的,我当前的策略不起作用,因为它继续要求输入。 - &GT;
输入行和列(0,1或2);对于玩家X: 2 0 X | O | X O | O | X X | X | Ø 输入行和列(0,1或2);对于球员O:
答案 0 :(得分:2)
首先关闭:
while (board[row][column] == 'X' || board[row][column] == 'O') {
System.out.println("This spot is occupied. Please try again");
}
这将创建一个无限循环,因为row
和column
不应该改变,你应该要求新的输入!
另外
public static Boolean winner(char[][] board){
for (int i = 0; i< board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == 'O' || board[i][j] == 'X') {
return false;
}
}
}
一旦你点击“O&#39;或者&#39; X&#39;您将使用false(无赢家)
退出Method您可能想要检查的是每个地点是否被占用
public static Boolean winner(char[][] board){
//Boolean which is true until there is a empty spot
boolean occupied = true;
//loop and check if there is empty space or if its a draw
for (int i = 0; i< board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
//Check if spot is not 'O' or not 'X' => empty
if (board[i][j] != 'O' || board[i][j] != 'X') {
occupied = false;
}
}
}
if(occupied)
return false;
//Check if someone won
return (board[0][0] == board [0][1] && board[0][0] == board [0][2]) ||
(board[0][0] == board [1][1] && board[0][0] == board [2][2]) ||
(board[0][0] == board [1][0] && board[0][0] == board [2][0]) ||
(board[2][0] == board [2][1] && board[2][0] == board [2][2]) ||
(board[2][0] == board [1][1] && board[0][0] == board [0][2]) ||
(board[0][2] == board [1][2] && board[0][2] == board [2][2]) ||
(board[0][1] == board [1][1] && board[0][1] == board [2][1]) ||
(board[1][0] == board [1][1] && board[1][0] == board [1][2]);
}
现在可以检查是否有赢家或其平局
Occupied == true == tie == return false
Winner == return true
但你有三种状态:
使用更改后的方法,在获胜之前,您将无法完成游戏。
原因:
while(!winner(board) == true)
只要没有赢家,这就会让游戏运行起来 (赢家()将是假的,因为一切都被占用或没有赢家)
while(!false==true) => while(true)
你可以写一个类似于胜利者的方法,但它只检查董事会是否有空位:
public static Boolean hasEmptySpot(char[][] board){
//loop and check if there is empty space
for (int i = 0; i< board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] != 'O' && board[i][j] != 'X') {
return true;
}
}
}
return false;
}
//New code
while(hasEmptySpot(board) || !winner(board)){
//Your code for the game here
....
}
当没有空位时,这将结束游戏 完成游戏后,你可以打电话给胜利者(董事会),如果你并列或赢了,它将会回来!
通过创建hasEmptySpot()
,您可以将获胜方法更改为
public static Boolean winner(char[][] board){
return (board[0][0] == board [0][1] && board[0][0] == board [0][2]) ||
(board[0][0] == board [1][1] && board[0][0] == board [2][2]) ||
(board[0][0] == board [1][0] && board[0][0] == board [2][0]) ||
(board[2][0] == board [2][1] && board[2][0] == board [2][2]) ||
(board[2][0] == board [1][1] && board[0][0] == board [0][2]) ||
(board[0][2] == board [1][2] && board[0][2] == board [2][2]) ||
(board[0][1] == board [1][1] && board[0][1] == board [2][1]) ||
(board[1][0] == board [1][1] && board[1][0] == board [1][2]);
}
为什么呢? 因为你完成了游戏并且你知道只有两种可能的结果Win或Tie。
我希望这对你有所帮助。
修改强> 我自己有一个逻辑错误!
第一个错误: 你还需要检查游戏运行时是否有赢家忘记了这一点!
while(hasEmptySpot(board) || !winner(board)){
}
现在,当有赢家或没有留下空白点时,这将退出游戏循环
第二个错误: 在hasEmptySpot()
中 if (board[i][j] != 'O' && board[i][j] != 'X') {
return true;
不是
if (board[i][j] != 'O' || board[i][j] != 'X') {
return true;
修正了上面的例子。
对不起给我很抱歉!
答案 1 :(得分:1)
执行此操作的最有效方法是保持先前已填充的空间数的运行计数,并在每次占用空间时增加该计数。当计数达到9时,董事会可被视为已满。
如果您熟悉面向对象的编程,我认为如果将2D数组包装在Board类中,您会发现这更容易实现。
示例:
public static class Board {
private char[][] spaces = new char[3][3];
private int numMoves = 0;
public void makeMove(int row, int col, char player) {
if (spaces[row][col] == 'X' || spaces[row][col] == 'O') {
System.out.println("This spot is occupied. Please try again");
} else {
spaces[row][col] = player;
numMoves++;
}
}
public boolean isFull() {
return numMoves == 9;
}
public boolean hasWinner() {
...
}
public void display() {
...
}
}
答案 2 :(得分:0)
您可以尝试合并一种新方法,例如:
public Boolean boardFull()
{
short count = 0;
for(short i = 0; i < 3; i++){
for(short j = 0; j < 3; j++){
if(board[i][j] == ‘O’ || board[i][j] == ’X’){
count++;
} else {
continue;
}
}
}
if(count == 9){
return true;
} else {
return false;
}
}
你可以使用if语句来查看它是否返回true然后打印出来的话。
答案 3 :(得分:0)
无效的代码是winner()
方法。如果至少有一个单元被占用,它总是返回false
。您可以根据Nordiii's answer的最后一部分继续进行。
检查单元格是否被占用的代码是无限的。您需要使用'if'语句而不是'while'循环:
if(board[row][column] == 'X' || board[row][column] == 'O'){
System.out.println("This spot is occupied. Please try again");
continue;
}
你的旧代码卡住了,总是检查1个单元是否被占用,它总是返回true
,这使循环保持活动状态并淹没你的控制台。 continue
语句将退出其他'while'循环的当前迭代并开始新的迭代,从而要求新的输入。
男人,这是很多未被捕获的例外!如果我搞砸了我的意见,那就去吧!整件事都失败了。只需为输入检查代码添加try
块:
try {
row = in.nextInt();
column = in.nextInt();
// Attempt to place player (an ArrayOutOfBoundsException could be thrown)
if(board[row][column] == 'X' || board[row][column] == 'O'){
System.out.println("This spot is occupied. Please try again");
continue;
}
board[row][column] = player;
} catch(Exception e){
System.out.println("I'm sorry, I didn't get that.");
continue;
}
这会尝试在try
语句中执行代码,如果有人输入了错误的内容,则异常会被“捕获”并创建新的迭代。天才!
答案 4 :(得分:0)
虽然已经有一些很好的答案,但我想发布另一个在其逻辑上更通用的解决方案,以确定获胜者。目前,当您为此编写更多通用逻辑时,您已经对一些可能的获胜方案进行了硬编码。
正如其他答案所指出的那样,你需要一种方法来检查电路板中未占用的空间,这将告诉你是否存在平局。我已经在下面的代码中实现了这样一个方法以及更通用的赢家逻辑。
请注意,某些方法是公开的,以便更容易测试,但它们不一定要公开。
import java.util.Scanner;
public class TicTacToe {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int row, column;
char player = 'X';
//create 2 dimensional array for tic tac toe board
char[][] board = new char[3][3];
char ch = '1';
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
board[i][j] = ch++;
}
}
displayBoard(board);
while(!winner(board) == true){
//get input for row/column
System.out.println("Enter a row and column (0, 1, or 2); for player " + player + ":");
row = in.nextInt();
column = in.nextInt();
//occupied
while (board[row][column] == 'X' || board[row][column] == 'O') {
System.out.println("This spot is occupied. Please try again");
}
//place the X
board[row][column] = player;
displayBoard(board);
if (winner(board)){
System.out.println("Player " + player + " is the winner!");
}
//time to swap players after each go.
if (player == 'O') {
player = 'X';
}
else {
player = 'O';
}
if (winner(board) == false && !hasFreeSpace(board)) {
System.out.println("The game is a draw. Please try again.");
}
}
//Don't forget to close the scanner.
in.close();
}
public static void displayBoard(char[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
if (j == board[i].length - 1) System.out.print(board[i][j]);
else System.out.print( board[i][j] + " | ");
}
System.out.println();
}
}
/**
* Determines whether the board is completely occupied by X and O characters
* @param board the board to search through
* @return true if entire board is populated by X or O, false otherwise.
*/
public static boolean hasFreeSpace(char[][] board){
for (int i = 0; i< board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] != 'O' && board[i][j] != 'X') {
return true;
}
}
}
return false;
}
//method to determine whether there is a winner
public static boolean winner(char[][] board){
return isHorizontalWin(board) || isVerticalWin(board) || isDiagonalWin(board);
}
/**
* Determines if there is a winner by checking each row for consecutive
* matching tokens.
* @return true if there is a winner horizontally, false otherwise.
*/
private static boolean isHorizontalWin(char[][] board) {
for(int row = 0; row < board.length; row++){
if(isWin(board[row]))
return true;
}
return false;
}
/**
* Determines whether all of the buttons in the specified array have the
* same text and that the text is not empty string.
* @param lineToProcess an array of buttons representing a line in the grid
* @return true if all buttons in the array have the same non-empty text, false otherwise.
*/
private static boolean isWin(char[] lineToProcess) {
boolean foundWin = true;
char prevChar = '-';
for(char character: lineToProcess) {
if(prevChar == '-')
prevChar = character;
if ('O' != character && 'X' != character) {
foundWin = false;
break;
} else if (prevChar != character) {
foundWin = false;
break;
}
}
return foundWin;
}
/**
* Determines whether there is a winner by checking column for consecutive
* matching tokens.
* @return true if there is a vertical winner, false otherwise.
*/
private static boolean isVerticalWin(char[][] board) {
char[] column = null;
//assuming all rows have same legnth (same number of cols in each row), use first row
for(int col = 0; col < board[0].length; col++){
column = new char[board[0].length];
for(int row = 0; row < column.length; row++){
column[row] = board[row][col];
}
if(isWin(column))
return true;
}
return false;
}
/**
* Determines if there is a winner by checking each diagonal for consecutive
* matching tokens.
* @return true if a diagonal winner exists, false otherwise.
*/
private static boolean isDiagonalWin(char[][] board) {
int row = 0, col = 0;
int cols = board.length;
int rows = board[0].length; //assuming all rows are equal length so just use the first one
//Create a one-dimensional array to represent the diagonal. Use the lesser
// of the rows or columns to set its size. If the grid is rectangular then
// a diagonal will always be the size of the lesser of its two dimensions.
int size = rows < cols ? rows : cols;
char[] diagonal = new char[size];
//Since we know the grid is a square we really could just check one of
// these - either row or col, but I left both in here anyway.
while (row < rows && col < cols) {
diagonal[col] = board[row][col];
row++;
col++;
}
if (isWin(diagonal)) {
return true;
}
row = rows - 1;
col = 0;
diagonal = new char[size];
while (row >=0 && col < cols) {
diagonal[col] = board[row][col];
row--;
col++;
}
return isWin(diagonal);
}
}