0

我正在尝试使用 OOP 在 java 中创建 Othello AI。我正在使用对象“板”,在这个对象中,我试图创建一个包含所有“孩子”的 ArrayList,其中每个孩子都是板的克隆,其中一个合法的动作 - 我正在努力解决这个问题。我在 board.java 的 addChild 类中遇到的一个问题是每次调用 addChild 时都尝试创建一个新板,我不确定如何执行此操作。目前,每一个合法的动作都被应用于一个名为 child 的棋盘,这是 children ArrayList 中唯一的棋盘。任何帮助将非常感激。

另外,我想知道 Minimax 的最佳方法,我的想法是从当前棋盘遍历游戏树,进入孩子,直到我碰到一个叶子(所选棋盘没有孩子),通过对这个叶子的评估将叶子与其所有兄弟节点进行比较,然后将父节点与其所有兄弟节点进行比较,依此类推。

谢谢,斯图尔特

MiniMax.java

package com.company.Minimax;

import com.company.Main;
import com.company.othello.board;
import com.company.othello.gameHandler;

import java.util.ArrayList;
import java.util.Random;

public class MiniMax {

    //tile types
    public static int[][] corners = {{0, 0}, {0, 7}, {7, 0}, {7, 7}};
    public static int[][] cornerBuffers = {{0, 1}, {0, 6}, {1, 0}, {1, 1},{1, 6}, {1, 7}, {6, 0},{6, 1}, {6, 6}, {6, 7}, {7, 1}, {7, 6}};
    public static int[][] edges = {{2, 0},{3, 0},{4, 0},{5, 0},{0, 2},{0, 3},{0, 4},{0, 5}, {7, 2},{7, 3},{7, 4},{7, 5},{2, 7},{3, 7},{4, 7},{5, 7}};
    public static int[][] edgeBuffers = {{2, 1},{3, 1},{4, 1},{5, 1}, {1, 2},{1, 3},{1, 4},{1, 5}, {6, 2},{6, 3},{6, 4},{6, 5}, {2, 6},{3, 6},{4, 6},{5, 6}};
    
    //need to swap between user turn and AI turn. when its not user turn say "not your turn" when click

    public static void Random(){
//        try{
//            System.out.println("sleep here");
//            Thread.sleep(2000);
//        }
//        catch(InterruptedException ex){
//            Thread.currentThread().interrupt();
//        }

        System.out.println("in random");

        ArrayList<int[]> legalMoves;
        legalMoves = gameHandler.potentialMovesList();


        System.out.println("-----legal moves list-----");

        for (int[] i : legalMoves) {
            System.out.println(i[0] + " " + i[1]);
        }
        System.out.println("-------------------------");

        //selects a random legal move from the list of legal moves
        Random rand = new Random(); //instance of random class
        int upperbound = legalMoves.size();
        int int_random = rand.nextInt(upperbound);

        int[] coords = legalMoves.get(int_random);
        int x = coords[0];
        int y = coords[1];

        System.out.println("random move select");
        System.out.println(x);
        System.out.println(y);
        System.out.println("------");

        Main.grid.setMove(new int[]{x, y}, 'w');    //need to change this from 'w' hardcoded to whichever AIs turn it is (both could be ai)

        Main.blackTurn = false; //set it to be white turn

        gameHandler.flipDiscs('w','b',x,y, Main.grid.getBoard());

        Main.blackTurn = !Main.blackTurn; //swap back to black (player) turn
    }

    public static void minimax(){

        ArrayList<int[]> legalMoves;
        legalMoves = gameHandler.potentialMovesList();
        int min = -1000;
        int max = 1000;

        System.out.println("-----legal moves list-----");
        char disc;
        if (Main.blackTurn = true){
            disc = 'b';
        }
        else {
            disc = 'w';
        }

        int count = 0;
        for (int[] i : legalMoves) {
            System.out.println(i[0] + " " + i[1]);

            board.addChild(Main.grid, i,  disc, count);
            count++;
        }
        System.out.println("-------------------------");

        System.out.println("----------children list-----------");
        for (int x = 0; x < board.getChildren().size(); x++){
            System.out.println(board.getChildren().get(x));
        }
        System.out.println("-------------------------");

        System.out.println("-----------list scores----------");
        int maxIndex = 0;
        int maxBoardVal = 0;
        for (int i =0; i < board.getChildren().size() ; i++){
            if (board.getChildren().get(i).getBoardVal() > maxBoardVal){
                maxBoardVal = board.getChildren().get(i).getBoardVal();
                maxIndex = i;
            }
            System.out.println(board.getChildren().get(i).getBoardVal()); //children only has 1 item in currently
        }
        System.out.println("-------------------------");

        int[] coord = legalMoves.get(maxIndex);
        int x = coord[0];
        int y = coord[1];

        System.out.println("minimax move select");
        System.out.println(x);
        System.out.println(y);
        System.out.println("------");
        Main.grid.setMove(new int[]{x, y}, 'w');    //need to change this from 'w' hardcoded to whichever AIs turn it is (both could be ai)

        System.out.println("pick: " + x + " " + y);
        Main.blackTurn = false; //set it to be white turn

        gameHandler.flipDiscs('w','b',x,y, Main.grid.getBoard());

        Main.blackTurn = !Main.blackTurn; //swap back to black (player) turn

        //(this is only for one depth), for multiple depth we need to then make a list of all moves
        //from each next ply (after accouting for every move that the opposite colour could make)
    }


    public static int evalFunction(board board, boolean blackTurn){

        //number of black vs white
        int[] scores = board.getScore(board);
        int blackScore = scores[0];
        int whiteScore = scores[1];

        if (blackTurn = true){
            return blackScore - whiteScore;
        }
        else {
            return whiteScore - blackScore;
        }
        //do player score - opposite score, higher is better. (min will be better for min player)

        //combined weight of pieces on board with weights of regions
        //called priorityBoard?
        //  https://github.com/codelucas/OthelloAI/blob/master/src/OthelloAI27404511.java

        //mobility how many legal moves there is
    }



}

板子.java

package com.company.othello;

import com.company.Main;
import com.company.Minimax.MiniMax;

import java.util.ArrayList;

public class board {

    private static char disc;
    private static char[][] gameboard;
    private static boolean blackTurn;
    private static ArrayList<board> children;
    private static int boardEval;

    //private static board[] children;
    //depth 0 = Main.grid
    //depth 1 = Main.grid with a move made

    //to make child boards (pass the current board, the turn and the move to make
    public board(boolean blackTurnIn, char[][] board, int[][] move){
        char[][] gameboard;
        gameboard = board;
        blackTurn = blackTurnIn;

        if (blackTurn = true){
            disc = 'b';
        }
        else {
            disc = 'w';
        }
        gameboard[move[1][0]][move[0][1]] = disc;
        //makes a new board that is the same as last gen, + the move that is made
    }

    //initializer to make first empty board
    public board() {
        gameboard = new char[8][8];
        for (int i = 0; i < 8; i++){
            for (int j = 0; j < 8; j++){
                gameboard[i][j] = ' ';
            }
        }
    }

    public static void setGameboard(char[][] gameboard) {
        board.gameboard = gameboard;
    }

    public static void setChildren(ArrayList<board> children) {
        board.children = children;
    }

    public static ArrayList<board> getChildren(){
        return children;
    }

    public char[][] getBoard(){
        return gameboard;
    }

    public boolean getTurn(){
        return blackTurn;
    }

    public static char getTile(int[] yo) {
        char value = gameboard[yo[0]][yo[1]];
        return value;
    }

    public static void setMove(int[] coord, char discColour){
        gameboard[coord[0]][coord[1]] = discColour;
    }

    public static void printBoard(board grid){
       //prints the logical grid in command line
            for (int i =0; i< 8; i++){
                for (int z =0; z< 8; z++){
                    System.out.print(grid.getBoard()[z][i]);
                    System.out.print("|");
                }
                System.out.println();
                for (int q =0; q< 16; q++) {
                    System.out.print("-");
                }
                System.out.println();
            }
            System.out.println("end of grid");
    }

    public static void initialBoard(board grid){
        for (int i = 0; i < 8; i++){
            for (int j = 0; j < 8; j++){
                int[] yo = {i, j};
                board.setMove(yo, ' ');
            }
        }

        board.setMove(new int[]{3, 3}, 'w');
        board.setMove(new int[]{4, 3}, 'b');
        board.setMove(new int[]{3, 4}, 'b');
        board.setMove(new int[]{4, 4}, 'w');
    }

    public static int[] getScore(board board){
        int blackScore = 0;
        int whiteScore = 0;
        for (int i = 0; i <= 7; i++){   //iterate over all tiles on board
            for (int j = 0; j <= 7; j++) {

                if (board.getTile(new int[]{i, j}) == 'b'){
                    blackScore++;
                }
                else if(board.getTile(new int[]{i, j}) == 'w'){
                    whiteScore++;
                }
            }
        }
        int score[] = {blackScore, whiteScore};
        return score;
    }

    public static void addChild(board board, int[] move, char discColour, int count){
        //public static void setMove(int[] coord, char discColour)
//        ArrayList<board> childList = board.getChildren();
//        board child = board; //clone current board
//        child.setMove(move, discColour);    //make the move on the child board
//        child.setBoardVal(MiniMax.evalFunction(child, Main.blackTurn)); //set value of child
//        childList.add(child);   //add child to list
//        board.setChildren(childList);   //set global list to local list
        board child = board;
        ArrayList<board> children = new ArrayList<>();
        child.setMove(move, discColour);    //make the move on the child board
        child.setBoardVal(MiniMax.evalFunction(board, Main.blackTurn)); //set value of child
        child.printBoard(child);
        children.add(child);   //add child to list
        board.setChildren(children);   //set global list to local list
    }

    public static void setBoardVal(int boardVal){
        boardEval = boardVal;
    }

    public static int getBoardVal(){
        return boardEval;
    }


}
4

0 回答 0