Определение победителя в игре Крестики Нолики
Пытаюсь написать программу Крестики Нолики, но есть проблема с финальным этапом - определением победителя.
Вместо того чтобы прервать игру после определения победителя, моя программа даёт пользователю возможность ввести лишний нолик или крестик. В чем моя ошибка?
В инпуте цифры от 1 включительно до 3 включительно через пробел. Пример: 2 3, 1 1.
Вот код:
package tictactoe;
import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class UserTurn {
static String coordinates1;
static String coordinates2;
static int coordRow;
static int coordCol;
static int countX;
static int countO;
static char symbolX = 'X';
static char symbolO = 'O';
static String str2;
static String grid;
static int[][] combosToWin = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, //Записываем в массив все возможные комбинации для выигрыша
{0, 4, 8}, {2, 4, 6},
{0, 3, 6}, {1, 4, 7}, {2, 5, 8}};
public static void main(String[] args) {
printStartGrid(); // вывод пустой сетки
Character[][] ticTacToeGrid = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}}; // заполняющийся массив
boolean has3X = false;
boolean has3O = false;
//boolean draw = false;
while (!has3X || !has3O) { //пока не будет 3 крестика либо 3 нолика в выигрышной комбинации, не выходить из цикла
userTurn(ticTacToeGrid); // первый ход
for (int i = 0; i < 8; i++) {
// определение победителя
if (grid.charAt(combosToWin[i][0]) == symbolX && grid.charAt(combosToWin[i][1]) == symbolX && grid.charAt(combosToWin[i][2]) == symbolX) {
System.out.println("X wins");
has3X = true;
break;
} else if (grid.charAt(combosToWin[i][0]) == symbolO && grid.charAt(combosToWin[i][1]) == symbolO && grid.charAt(combosToWin[i][2]) == symbolO) {
System.out.println("O wins");
has3O = true;
break;
}
}
secondUserTurn(ticTacToeGrid); //второй ход
}
}
public static void printStartGrid() { //пустая сетка
System.out.println("---------\n" +
"| " + " " + " " + " " + " " + " " + " |\n" +
"| " + " " + " " + " " + " " + " " + " |\n" +
"| " + " " + " " + " " + " " + " " + " |\n" +
"---------");
}
public static void printCurrentGrid(Character[][] ticTacToeGrid) { // сетка, которая обновляется после каждого хода
System.out.println("---------");
for (Character[] characters : ticTacToeGrid) {
System.out.print("| ");
for (Character character : characters) {
System.out.print(character + " ");
}
System.out.println("|");
}
System.out.println("---------");
}
public static void userTurn(Character[][] ticTacToeGrid) { //первый ход
Scanner scn = new Scanner(System.in);
Pattern p1 = Pattern.compile("(.*[0-4]+.*)"); // проверка на тип int, на правильность координаты ячейки и на "свободна ли ячейка"
Matcher m1;
boolean areNumbers1 = false;
boolean inRange1 = false;
boolean isOccupiedForUser = false;
while (!areNumbers1) {
while (!inRange1) {
while (!isOccupiedForUser) {
System.out.print("User 1 Enter the coordinates: ");
coordinates1 = scn.nextLine();
m1 = p1.matcher(coordinates1);
if (!m1.matches()) {
System.out.println("You should enter numbers!");
areNumbers1 = false;
} else {
areNumbers1 = true;
coordRow = Integer.parseInt(String.valueOf(coordinates1.charAt(0)));
coordCol = Integer.parseInt(String.valueOf(coordinates1.charAt(2)));
if (coordRow < 1 || coordRow > 3 || coordCol < 1 || coordCol > 3) {
System.out.println("Coordinates should be from 1 to 3!");
inRange1 = false;
} else {
inRange1 = true;
coordRow -= 1;
coordCol -= 1;
if (ticTacToeGrid[coordRow][coordCol] == symbolX) {
isOccupiedForUser = false;
System.out.println("This cell is occupied! Choose another one!");
} else if (ticTacToeGrid[coordRow][coordCol] == symbolO) {
isOccupiedForUser = false;
System.out.println("This cell is occupied! Choose another one!");
} else {
isOccupiedForUser = true;
ticTacToeGrid[coordRow][coordCol] = symbolX;
printCurrentGrid(ticTacToeGrid);
convert(ticTacToeGrid);
countX++;
System.out.println(countX);
}
}
}
}
}
}
}
public static void secondUserTurn(Character[][] ticTacToeGrid) {
Scanner scn2 = new Scanner(System.in);
Pattern p2 = Pattern.compile("(.*[0-4]+.*)");
Matcher m2;
boolean areNumbers2 = false;
boolean inRange2 = false;
boolean isOccupiedForUser2 = false;
while (!areNumbers2) {
while (!inRange2) {
while (!isOccupiedForUser2) {
System.out.print("User 2 Enter the coordinates: ");
coordinates2 = scn2.nextLine();
m2 = p2.matcher(coordinates2);
if (!m2.matches()) {
System.out.println("You should enter numbers!");
areNumbers2 = false;
} else {
areNumbers2 = true;
coordRow = Integer.parseInt(String.valueOf(coordinates2.charAt(0)));
coordCol = Integer.parseInt(String.valueOf(coordinates2.charAt(2)));
if (coordRow < 1 || coordRow > 3 || coordCol < 1 || coordCol > 3) {
System.out.println("Coordinates should be from 1 to 3!");
inRange2 = false;
} else {
inRange2 = true;
coordRow -= 1;
coordCol -= 1;
if (ticTacToeGrid[coordRow][coordCol] == symbolX) {
isOccupiedForUser2 = false;
System.out.println("This cell is occupied! Choose another one!");
} else if (ticTacToeGrid[coordRow][coordCol] == symbolO) {
isOccupiedForUser2 = false;
System.out.println("This cell is occupied! Choose another one!");
} else {
isOccupiedForUser2 = true;
ticTacToeGrid[coordRow][coordCol] = symbolO;
printCurrentGrid(ticTacToeGrid);
convert(ticTacToeGrid);
countO++;
System.out.println(countO);
}
}
}
}
}
}
}
public static void convert(Character[][] ticTacToeGrid) {
str2 = Arrays.deepToString(ticTacToeGrid); //Конвертирование массива в строку
grid = str2.substring(2, 3) + str2.substring(5, 6) + str2.substring(8, 9) + // Новая строка с введенными X и O. Сделал это для того,
str2.substring(13, 14) + str2.substring(16, 17) + str2.substring(19, 20) + // чтобы было легче определить победителя
str2.substring(24, 25) + str2.substring(27, 28) + str2.substring(30, 31);
System.out.println("Tic-Tac-Toe line grid: " + grid);
}
}
Ответы (1 шт):
Автор решения: Alexander Chernin
→ Ссылка
Вы делаете break в случае либо крестики, либо нолики победили, после чего происходит просто выход из цикла for и переход к методу secondUserTurn.
for (int i = 0; i < 8; i++) {
// определение победителя
if (grid.charAt(combosToWin[i][0]) == symbolX && grid.charAt(combosToWin[i][1]) == symbolX && grid.charAt(combosToWin[i][2]) == symbolX) {
has3X = true;
break;
} else if (grid.charAt(combosToWin[i][0]) == symbolO && grid.charAt(combosToWin[i][1]) == symbolO && grid.charAt(combosToWin[i][2]) == symbolO) {
has3O = true;
break;
}
}
secondUserTurn(ticTacToeGrid); //второй ход
Надо просто делать перед этим вызовом проверку, что уже есть победитель. Рекомендую следующую модификацию:
while(true) {
for (int i = 0; i < 8; i++) {
...
}
if (!has3O || !has3X) {
secondUserTurn(ticTacToeGrid); //второй ход
} else {
// У нас есть победитель - игра закончена
break; // выходим из while
}
}