Java-код для игры с искусственным интеллектом

В настоящее время я разрабатываю Java-игру, похожую на шашки.

Есть два игрока, player X и player Y. Мне не нужен графический интерфейс для этой игры, просто вывод ниже. В игре игрок X начинает с [0,0], а игрок Y начинает с [7,7].

Моя первая проблема заключается в том, что я не знаю, как ввести, например, [3,6], чтобы заставить игрока X перейти к [3,6].

Когда игрок X перемещается из [0,0], то [0,0] должен быть помечен как недоступный, следовательно, ни один из игроков не может ни пройти на это поле, ни перепрыгнуть через него, и это моя вторая проблема, так как я не уверен, как это можно сделать.

Цель игры на самом деле состоит в том, чтобы поставить одного из игроков в положение, когда он не может никуда двигаться. Мы должны добавить в него разные ИИ, но если я заработаю основу, я смогу попробовать разработать ИИ.

Я не самый сильный программист, поэтому, если мой код можно каким-либо образом отредактировать, чтобы упростить задачу, любая помощь будет оценена по достоинству. Спасибо

Мой код выглядит следующим образом:

public static AIProject {

    public static String [][] board = new String[9][9];

    public static void addPiece(int x, int y, String r) {
        board [x][y] = r;
    }

    public static void showBoard() {
        for(int row = 0; row < board.length; row++) {
            System.out.println(" ");
            System.out.println("-------------------");

            for (int col = 0; col < board[row].length; col++) {
                System.out.print("I");
                if(board[col][row] == null) {
                    System.out.print(" ");
                } else {
                    System.out.print(board[col][row]);
                }
            }
        }

        System.out.println(" ");
        System.out.println("-------------------");
    }   

    public static void mainn(String[] args) {
        System.out.println(board.length);

        addPiece(0,0,"0");
        addPiece(0,1,"1");
        addPiece(0,2,"2");
        addPiece(0,3,"3");
        addPiece(0,4,"4");
        addPiece(0,5,"5");
        addPiece(0,6,"6");
        addPiece(0,7,"7");
        addPiece(0,8,"8");
        addPiece(1,0,"1");
        addPiece(2,0,"2");
        addPiece(3,0,"3");
        addPiece(4,0,"4");
        addPiece(5,0,"5");
        addPiece(6,0,"6");
        addPiece(7,0,"7");
        addPiece(8,0,"8");

        addPiece(1,1,"X");
        addPiece(8,8,"Y");

        showBoard();
     }
}

person Ryan Scollard    schedule 04.05.2015    source источник
comment
Итак, ваш вопрос в основном заключается в том, как взаимодействовать с пользователем?   -  person Willem Van Onsem    schedule 04.05.2015
comment
Да, в значительной степени, мне просто нужно иметь возможность ввести пробел на доске в x или y, чтобы переместиться, и любое пространство x или y, из которого он переместился, отметьте это как недоступное или пометьте его как *, чтобы x или y не могли туда переместиться или перепрыгнуть через него   -  person Ryan Scollard    schedule 04.05.2015
comment
Если вы программируете ИИ для шашек, самая большая проблема, с которой вы столкнетесь, — найти алгоритм ИИ. Для шашек подойдет minimax. Это хорошо известно, и этому учат на многих курсах по искусственному интеллекту, но оно подведет вас, когда пространство для поиска станет большим. Для таких игр, как го, посмотрите Поиск по дереву Монте-Карло.   -  person Agostino    schedule 08.05.2015


Ответы (1)


Моя первая проблема заключается в том, что я не уверен, как ввести, например, [3,6], чтобы заставить игрока X перейти в [3,6].

Вы можете использовать некоторые значимые координаты - например, если пользователь хочет перейти к [3,6], тогда он вводит 36 и т. д. Метки для координат должны быть видны на доске.

Когда игрок X перемещается из [0,0], то [0,0] должен быть помечен как недоступный, поэтому ни один из игроков не может ни пойти в это место, ни перепрыгнуть через него, и это моя вторая проблема, так как я не уверен, как это осуществимо.

Вы можете создать новый класс, например BoardItem - он будет содержать поля isOccupied и label - label будет показывать лейбл игрока, если поле будет занято или координаты, если поле не занято.

Я также рекомендую считать массивы с 1, а не с 0. Это будет более осмысленно для пользователя - "когда я хочу перейти к 1 строке, 1 столбцу, я должен ввести 11".

Предлагаемое мной решение:

public static AIProject {

private static int BOARD_SIZE = 8;

static BoardItem[][] board = new BoardItem[BOARD_SIZE][BOARD_SIZE];

// available players
public static String[] players = { "X", "Y" };

// x,y are the coordinates, label is the string, it can take coordinates or
// player name if the field is occupied
public static void addPiece(int x, int y, String label, boolean isOccupied)    {
// here we are assigning to a specific board piece a BoardItem - label      and if it
// is occupied
    board[x][y] = new BoardItem(label, isOccupied);
}

public static void showBoard() {
    for (int row = 0; row < BOARD_SIZE; row++) {
        for (int col = 0; col < BOARD_SIZE; col++) {
            if (board[col][row] == null) {
                System.out.print("\t");
            } else {
                System.out.print(board[col][row] + "\t");
            }
        }
        System.out.println("\n_____________________________________________________________");
    }
}

public static void main(String[] args) {
    // board creating
    for (int x = 1; x < BOARD_SIZE ; x++) {
        for (int y = 1; y < BOARD_SIZE ; y++) {
          // as you can see in method definition we are passing coordinates 
         // as integers in 2 first arguments, next coordinates as string
         // this "label" would be displayed on board
         // the last parameter is indicating that the field are not occupied
            addPiece(x, y, x + "" + y, false);
        }
    }
    // however, you want to point that 1,1 is occupied by player 'X'...
    addPiece(1, 1, players[0], true);
    // and 7,7 is occupied by player 'Y'
    addPiece(7, 7, players[1], true);

    // 'X' is active player now
    String activePlayer = players[0];
    Scanner keyboard = new Scanner(System.in);

    // infinite loop - in the loop condition you should check
    // if someone lose/win to end the game
    while (true) {
        // clearing output
        clearScreen();
        // showing board            
        showBoard();
        // moving player - waiting for input from player and then 
        // mark chosen coordinates as occupied by active player
        playerMove(activePlayer, keyboard);
        // changing active player. First X, then Y, then X and so on.
        activePlayer = changeActivePlayer(activePlayer);
    }

}

private static void playerMove(String player, Scanner keyboard) {

    BoardItem boardItem = getBoardItemForPosition(keyboard.next());
    // it should be isNotValid
    while (boardItem.isOccupied()) {
        System.out.println("Chosen position is occupied! Please choose another one");
        boardItem = getBoardItemForPosition(keyboard.next());
    }
    boardItem.setOccupied(true);
    boardItem.setLabel(player);
}

private static BoardItem getBoardItemForPosition(String position) {
    int x = Integer.parseInt(position.substring(0, 1));
    int y = Integer.parseInt(position.substring(1, 2));
    return board[x][y];
}

private static String changeActivePlayer(String activePlayer) {
    if (activePlayer.equals(players[0])) {
        return players[1];
    }
    return players[0];
}

private static void clearScreen() {
    for (int i = 0; i < 50; ++i)
        System.out.println();
}
}

И класс BoardItem:

public class BoardItem {

private String label;

private boolean isOccupied;

public BoardItem(String label, boolean isOccupied) {
    this.label = label;
    this.isOccupied = isOccupied;
}

public String getLabel() {
    return label;
}

public void setLabel(String label) {
    this.label = label;
}

public boolean isOccupied() {
    return isOccupied;
}

public void setOccupied(boolean isOccupied) {
    this.isOccupied = isOccupied;
}

@Override
public String toString() {
    return label;
}

}

Еще советы:

  • класс с основным методом должен только запускать приложение, вся логика должна быть в другом месте;
  • вы должны написать валидацию для пользовательского ввода и проверить там, вводит ли пользователь правильный ввод - 2 числа в соответствующем диапазоне, если поле занято или нет, и может ли пользователь перейти в указанное поле;
  • Я бы поменял все массивы на новые классы, но это только предложение :) один класс должен отвечать за 1 вещь: за запуск приложения, за создание и вывод представления, за движение игрока с соответствующей проверкой.
person Tomek    schedule 04.05.2015
comment
Спасибо за это, хотя при попытке переместить X я набираю 1167, чтобы переместить x с 1,1 на 6,7. Но там написано, что место занято, но это мой первый ход. Как мне начать с них все пустые, кроме 1,1 (где начинается x) и 7,7 (где начинается y). И как только я делаю этот ход, я тоже делаю 1,1 занятым, потому что оттуда я только что переехал? Спасибо за вашу помощь - person Ryan Scollard; 04.05.2015
comment
Для версии, которую я вставил, вам нужно только ввести пункт назначения, например. 67 - 2 первые буквы ввода: «x» и «y». Они установлены как незанятые, здесь установлены только 1,1 и 7,7: addPiece(1, 1,players[0], true); addPiece(7, 7, player[1], true); Хотите, чтобы я прокомментировал код? - person Tomek; 04.05.2015
comment
Хорошо, я понимаю, спасибо. Да, если вы можете, это было бы здорово. Спасибо за помощь - person Ryan Scollard; 06.05.2015