Реализация шахматного ИИ в проекте Java - PullRequest
0 голосов
/ 13 января 2020

В настоящее время я использую шахматный AI в своей шахматной игре. Сейчас я пытаюсь справиться с игровым состоянием для ИИ.

Поскольку я чувствую себя как ИИ, мне нужны новейшие свойства с доски или класса игры (в моем случае я посылаю игровой класс). Но мне интересно, что это неправильный путь. Почему?

Всякий раз, когда я вычисляю ход для ИИ, используя minmax, я пытаюсь разместить движения на доске, но проблема в том, что этого не должно быть на доске. Потому что второй игрок в основном использует доску. Я чувствую, что он взломает sh, потому что всякий раз, когда ИИ пытается сделать движение, он будет пытаться обновляться на доске, что приводит к взлому sh.

. Я думаю, что мне нужно создать поддельную / ложную копию (со свойствами, которые необходимы, список доступных ходов, цвет фигуры, игрок и т. д. c.) игры / доски и отправить ее ИИ. Но как лучше всего это сделать?

Моя текущая настройка кода минимаксного алгоритма соответствует другим используемым кодам: https://hastebin.com/niqaderule.java:

public class MiniMax implements MoveStrategy {

    private final BoardEvaluator boardEvaluator;
    private int searchDepth;


    public MiniMax(BoardEvaluator boardEvaluator, int searchDepth) {
        this.boardEvaluator = boardEvaluator;
        this.searchDepth = searchDepth;
    }

    @Override
    public String toString() {
        return "MiniMax{" +
                "boardEvaluator=" + boardEvaluator +
                '}';
    }

    @Override
    public Move execute(ChessGame game) {

        long startTime = System.currentTimeMillis();

        Move calculatedBestMove = null;

        int highestSeenValue = Integer.MIN_VALUE;
        int lowestSeenValue = Integer.MAX_VALUE;
        int currentValue;

        System.out.println("computer thinks" + " depth= " + this.searchDepth);

        var numberOfAllMoves = game.getBoard().getAllAvailableMoves(PieceColor.BLACK);

        for(Move move : game.getBoard().getAllAvailableMoves(PieceColor.BLACK)){
             game.getBoard().movePiece(move.getSelectedPiece(), move);
             currentValue = calculateValue(game);
             if(game.getCurrentTurn() == game.getPlayers().get(0) && currentValue >= highestSeenValue)
             {
                 highestSeenValue = currentValue;
                 calculatedBestMove = move;
             }
             else if(game.getCurrentTurn() == game.getPlayers().get(1) && currentValue <= lowestSeenValue){
                 lowestSeenValue = currentValue;
                 calculatedBestMove = move;
             }

        }
        long CalculationTime = System.currentTimeMillis() - startTime;
        return  calculatedBestMove;
    }

    public int calculateValue(ChessGame game){
        if(game.getCurrentTurn() == game.getPlayers().get(0)){
           return  min(game, -1);
        }
            return max(game,  -1);
    }


    public int min(ChessGame game, int depth){

        if(depth == 0 || game.getGameStatus() == GameStatus.BLACK_CHECK_MATE || game.getGameStatus() == GameStatus.WHITE_CHECK_MATE){
            return this.boardEvaluator.evaluate(game, depth);
        }

        int lowestValue = Integer.MAX_VALUE;

        for(Move move: game.getBoard().getAllAvailableMoves(PieceColor.BLACK)){
            game.getBoard().movePiece(move.getSelectedPiece(), move);
            int currentValue = max(game, depth -1);
            if(currentValue <= lowestValue)
            {
                lowestValue = currentValue;
            }
        }
        return lowestValue;
    }

    public int max(ChessGame game, int depth){
        if(depth == 0 || game.getGameStatus() == GameStatus.BLACK_CHECK_MATE || game.getGameStatus() == GameStatus.WHITE_CHECK_MATE){
            return this.boardEvaluator.evaluate(game, depth);
        }

        int highestSeenValue = Integer.MIN_VALUE;

        for(Move move: game.getBoard().getAllAvailableMoves(PieceColor.BLACK)){
            game.getBoard().movePiece(move.getSelectedPiece(), move);

            int currentValue = min(game, depth -1);
            if(currentValue <= highestSeenValue)
            {
                highestSeenValue = currentValue;
            }
        }
        return highestSeenValue;
    }
}

1 Ответ

0 голосов
/ 29 января 2020

Есть 2 распространенных способа сделать это:

  1. Создать глубокую копию представления доски перед тем, как сделать ход (перед рекурсивным вызовом), а затем отправить копию доски на минимаксная функция.

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

...