Игра AI bot Java подземелье

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

То, что я сейчас делаю, это писать бота, чтобы сделать то же самое. До сих пор я придумал «глупую» бота, которая основана главным образом на случайности. У бота есть действия для следующих функций:

look() - Может видеть вокруг карты ASCII в радиусе 2. Функция выводит ее, поэтому бот не может ее хранить в памяти (я могу сохранить его память).

move <direction>() - перемещение в направлении, которое включает N E S W.

pickUp() - Если бот стоит на золоте, это подбирает его.

exitGame() - Если бот стоит на выходе, имеет все золото и эта команда запускается, он выйдет из игры.

Вот мой бот-код.

import java.io.IOException;
import java.util.Random;


public class Bot{
    public GameLogic bot;

    public static void main(String[] args) throws IOException{
        // TODO Auto-generated method stub
        GameLogic bot = new GameLogic("map2.txt"); 
        bot.startGame();
        int gold = bot.gold();
        System.out.println(gold);
        int turn = 0;
        char[][] myWorld = bot.getMap();
        while(true){
            int posX = bot.getPosX();
            int posY = bot.getPosY();
            Random rn = new Random();
            int min = 0;
            int max = 3;
            int n = max - min + 1;
            int i = rn.nextInt(n);
            if(myWorld[posX][posY] == 'G'){
                bot.pickUp();
            }
            if(myWorld[posX][posY] == 'E'){
                boolean y = bot.exitGame();
                if(y){break;}
            }
            turn++;
            if(i == 0){
                bot.moveN();
            }else if(i == 1){
                bot.moveE();
            }else if(i == 2){
                bot.moveS();
            }else if(i == 3){
                bot.moveW();

            }else{
                System.out.println("SOMETHING WENT WRONG!!!");
            }

        }
        System.out.println(turn);

    }
}

То, что я спрашиваю, - это лучший способ сделать это. Как я могу улучшить свой бот, чтобы потребовалось меньше оборотов? Как я могу сделать своего бота «умнее»?

11 голосов | спросил user202051 23 FebruaryEurope/MoscowbSun, 23 Feb 2014 01:54:57 +0400000000amSun, 23 Feb 2014 01:54:57 +040014 2014, 01:54:57

2 ответа


9

В целом

Я думаю, что у вас слишком много кода в основном методе. Вы должны разделить это на более удобоваримые сегменты. Возможно, еще несколько методов в вашем классе GameLogic (который, вероятно, должен быть разделен на один Game и один GameBot /Player). (По крайней мере) один метод определения следующего хода, один метод выбора правильного действия на основе текущей плитки и т. Д.

Улучшение вашего бота

Предполагая, что золото никогда не перемещается после его размещения, вы можете использовать Set всех фрагментов, которые вы посетили. Затем вы можете попытаться не перейти к фрагменту, который вы уже посетили.

Сами плитки могут быть представлены как класс Point, который содержит x и y, или он может быть представлен как int, если вы делаете небольшую математику для представления столбца и строка на один единственный int (я рекомендую класс Point). Или вы можете сделать класс Tile, так как каждая плитка также имеет некоторый контент (стена, выход, золото, пустое пространство ...)

Случайное

Random rn = new Random();
int min = 0;
int max = 3;
int n = max - min + 1;
int i = rn.nextInt(n);
  • Так как min равен нулю, нет необходимости делать - min
  • Поскольку max является константой, было бы проще объявить max как 4 с самого начала, а не использовать + 1
  • Поскольку n используется только один раз, вы можете просто использовать int i = rn.nextInt(4);
  • Случайные объекты предназначены для повторного использования. Инициализировать объект Random вне цикла. Это связано с тем, что рандомизация будет отличаться при создании объекта снова и снова.

Перемещение

Вы можете перемещаться в четырех направлениях, это говорит мне, что вы должны использовать Перечисление направления и замените четыре метода одним move(Direction4 dir); Используя это перечисление, вы также можете упростить случайный процесс:

Direction4 chosenDirection = Direction4.values()[rn.nextInt(Direction4.values().length)];

Эта строка захватывает все возможные направления и рандомизирует int от 0 (включительно) до длины (исключая) и захватывает направление с этим индексом.

Когда что-то пойдет не так

System.out.println("SOMETHING WENT WRONG!!!");

Я могу заверить вас, этого никогда не произойдет. И даже если бы это было, Исключения были предназначены для ... ну, исключений. throw new AssertionError("Something went wrong."); - вот что я сделал бы здесь. Вернее ... я бы снял всю линию, так как этого никогда не произойдет. Особенно, если вы используете подход Direction4.

Spacing

Это одна из тех вещей, которые я чаще всего упоминаю в своих обзорах, но, пожалуйста,

}else if(i == 1){

измените на

} else if (i == 1) {

Это делает код более читаемым с правильным интервалом.

ответил Simon Forsberg 23 FebruaryEurope/MoscowbSun, 23 Feb 2014 02:08:11 +0400000000amSun, 23 Feb 2014 02:08:11 +040014 2014, 02:08:11
6

+1 до @Simon и некоторые другие примечания:

  1. В текущем проекте не предусмотрено, что боты играют в честную игру. Мошенник-бот мог бы перебирать всю карту myWorld, найти точку выхода и идти туда прямо. То же самое верно и для золота. Вы должны создать упомянутый метод look, который возвращает только частичную карту в 2 кварталах и скрыть всю карту от бота.

  2. Я бы попытался создать проект, в котором бот просто возвращает свое следующее действие (nextAction()), и игра оценивает действия в цикл и вызов nextAction, пока бот не достигнет точки выхода. Это поможет, когда немой бот никогда не найдет точку выхода. Логика оценки может убить бота, не нужно дублировать эту логику в каждом боте. Текущий код содержит аналогичную вещь: подсчет поворотов. Это может быть обязанностью игры подсчитать, сколько поворотов было использовано для поиска выхода (и сколько золота было выбрано).

    Он также удалит логику из ботов, например:

    final boolean y = game.exitGame();
    if (y) {
        break;
    }
    

    Не должно быть ответственности бота, чтобы решить, действительно ли он достиг точки выхода или нет.

  3. Метод main содержит слишком много логики и пытается отделить его. Если вы хотите протестировать двух или более разных ботов, что будет дублироваться? Если вы устраните это дублирование, у вас будет лучший дизайн.

  4. public GameLogic bot;
    

    Это поле не используется. Удалите его, если это не необходимо. (Публичные поля обычно приводят к более сложному обслуживанию. См. Что такое сделка с публичными полями Java? )

  5. Переменная для GameLogic называется bot. Это немного вводит в заблуждение.

  6. Я бы использовал более описательные имена переменных и не сокращал бы. Более длинные имена сделают код более читаемым, поскольку читателям /сопровождающим не нужно декодировать или запоминать сокращения.

    • moveW - moveWest
    • moveN - moveNorth
    • moveE - moveEast
    • moveS - moveSouth
    • rn - random
    • i - nextDirection
    • min - minDirection
    • max - maxDirection
    • y - exitPointReached

    (Я согласен с @Simon , что здесь перечисление лучше).

ответил palacsint 23 FebruaryEurope/MoscowbSun, 23 Feb 2014 08:58:38 +0400000000amSun, 23 Feb 2014 08:58:38 +040014 2014, 08:58:38

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132