Вопрос по работе цикла while внутри метода
Оригинал кода тут: https://gist.github.com/EugeneWenew/381d5ef9bb5fcb6a63ef9b4debb96ee8
В общем: есть крестики-нолики. Есть метод получения координат от пользователя. Есть метод простановки этих координат на поле.
/**
* Класс игрока
*/
package TicTacToe;
public class Player {
private int id;
private static int count = 0;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
Player() {
count++;
id = count;
}
Player(String name) {
this();
this.name = name;
}
@Override
public String toString() {
return "Player{" +
"id " + id +
", name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
}
/**
* Менеджер игроков
*/
package TicTacToe;
import java.util.ArrayList;
public class PlayerManager {
ArrayList<Player> players;
PlayerManager() {
players = new ArrayList<>();
}
void addPlayer(String name) {
Player player = new Player(name);
players.add(player);
}
Player getFirstPlayer() {
return players.get(0);
}
Player getSecondPlayer() {
return players.get(1);
}
@Override
public String toString() {
return "PlayerManager{" +
", players=" + players +
'}';
}
}
/**
* класс игровое поле
*/
public class Field {
char[][] field; //видимое поле 1
ArrayList<Integer> space; //альтернативное внутреннее поле 2
private Point point;
Scanner scanner;
Player player;
Field() {
char[][] field = new char[3][3]; // 1
this.field = field;
space = new ArrayList<Integer>();
}
void fillTheField() { // 1
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
this.field[i][j] = '.';
}
}
}
void fillTheSpace() {
for (int i = 0; i < 9; i++) {
space.add(i);
}
}
void printFields() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(this.field[i][j] + "\t\t");
}
System.out.println("");
System.out.println("");
}
for (int i = 0; i < 9; i++) {
System.out.print(space.get(i) + "\t");
}
System.out.println("");
System.out.println("");
}
void madeTheMark(Field field, Point point, Player player) {
if (player.getId() == 1) {
field.markO(point.getX(), point.getY());
} else {
field.markX(point.getX(), point.getY());
}
}
void markX(int x, int y) {
this.field[x][y] = 'X';
}
void markO(int x, int y) {
this.field[x][y] = '0';
}
Point getCellCoords() {
scanner = new Scanner(System.in);
int i = -2;
while ((i < 0) | (i > 2)) {
System.out.println("Введите позицию по горизонтали(от 0 до 2):");
i = scanner.nextInt();
scanner.nextLine();
}
int j = -3;
while ((i < 0) | (i > 2)) {
System.out.println("Введите позицию по вертикали(от 0 до 2):");
j = scanner.nextInt();
scanner.nextLine();
}
Point point = new Point(j, i);
return point;
}
boolean checkCells(char[][] field) {
for (int i = 0; i < 3; i++) {
if (((field[i][0]) == 'X') & ((field[i][1]) == 'X') & ((field[i][2]) == 'X')) {
return true;
} else if ((((field[0][i]) == 'X')) & ((field[1][i]) == 'X') & ((field[2][i]) == 'X')) {
return true;
}
}
if (((field[0][0]) == 'X') & ((field[1][1]) == 'X') & ((field[2][2]) == 'X')) {
return true;
} else if (((field[2][0]) == 'X') & ((field[1][1]) == 'X') & ((field[0][2]) == 'X')) {
return true;
}
for (int i = 0; i < 3; i++) {
if (((field[i][0]) == '0') & ((field[i][1]) == '0') & ((field[i][2]) == '0')) {
return true;
} else if ((((field[0][i]) == '0')) & ((field[1][i]) == '0') & ((field[2][i]) == '0')) {
return true;
}
}
if (((field[0][0]) == '0') & ((field[1][1]) == '0') & ((field[2][2]) == '0')) {
return true;
} else if (((field[2][0]) == '0') & ((field[1][1]) == '0') & ((field[0][2]) == '0')) {
return true;
}
return false;
}
}
/**
*Основной цикл
*/
public class Main {
public static void main(String[] args) {
Main start = new Main();
start.runGame();
}
void runGame() {
PlayerManager manager = new PlayerManager();
manager.addPlayer(playerInvitation());
manager.addPlayer(playerInvitation());
Field plate = new Field();
plate.fillTheField(); //инициализация поля отображаемого для игроков
plate.fillTheSpace(); //поле для вычислений
plate.printFields();
mainCycle(plate, manager);
}
void mainCycle(Field plate, PlayerManager manager) {
do {
nextTurn(manager.getFirstPlayer());
plate.madeTheMark(plate, plate.getCellCoords(), manager.getFirstPlayer());
plate.printFields();
if (plate.checkCells(plate.field)) {
System.out.println("Победил игрок " + manager.getFirstPlayer().getName());
break;
}
nextTurn(manager.getSecondPlayer());
plate.madeTheMark(plate, plate.getCellCoords(), manager.getSecondPlayer());
plate.printFields();
if (plate.checkCells(plate.field)) {
System.out.println("Победил игрок " + manager.getSecondPlayer().getName());
break;
}
} while (!plate.checkCells(plate.field));
}
String playerInvitation() {
System.out.println("Введите имя игрока: ");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
return name;
}
void nextTurn(Player player) {
System.out.println("Ходит игрок " + player.getName());
}
}
Описание проблемы:
При получении координат, я попытался создать ОГРАНИЧИТЕЛЬ на принимаемое число:
while ((i < 0) | (i > 2)) {
, т.е. чтобы координата не выходила за пределы поля. При этом, чтобы условие изначально выполнялось, проинициализированы переменные:
int i = -2;
int j = -3;
При работе цикла WHILE, при введении правильных координат (т.е. 0 или 1 или 2), цикл завершается. И по идее код должен выполняться дальше. Но получается, что я получаю первую координату, а вторая координата УЖЕ ЗАДАНА числом:
int j = -3;
И я натыкаюсь на:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -3 out of bounds for length 3
at TicTacToe.Field.markO(Field.java:65)
at TicTacToe.Field.madeTheMark(Field.java:54)
at TicTacToe.Main.mainCycle(Main.java:27)
at TicTacToe.Main.runGame(Main.java:21)
at TicTacToe.Main.main(Main.java:10)
Почему НЕ НАЧИНАЕТ выполняться второй ЦИКЛ WHILE ?
Т.е. почему метод сразу принимает заданное число, заместо ПРИЕМА координаты от пользователя ?
Ответы (1 шт):
Мы с Вами уже говорили о недостаточной внимательности.
int j = -3;
//while ((i < 0) | (i > 2)) {
while ((j < 0) | (j > 2)) {
Здесь не требуется полного вычисления всех операндов булевского выражения:
while (j < 0 || j > 2) {