zoukankan      html  css  js  c++  java
  • 极大/小搜索,alpha/beta剪枝


    1. 剪枝min层剪去beta最小得分比alpha最大得分还要小的得分,如果alpha是8,beta比8小的节点都剪掉,因为max层,只会选最大的
    2. 剪枝max层剪去比alpha最大得分比beta最小得分还要大的得分,如果beta是8,alpha比8的节点都需要剪掉,因为min层只会选最小的
         let board = [
                ['', '', ''],
                ['', '', ''],
                ['', '', '']
            ];
    
            let w; // = width / 3;
            let h; // = height / 3;
    
            let ai = 'X';
            let human = 'O';
            let currentPlayer = human;
    
            function setup() {
                createCanvas(400, 400);
                w = width / 3;
                h = height / 3;
                bestMove();
            }
    
            function equals3(a, b, c) {
                return a == b && b == c && a != '';
            }
    
            function checkWinner() {
                let winner = null;
    
                // horizontal
                for (let i = 0; i < 3; i++) {
                    if (equals3(board[i][0], board[i][1], board[i][2])) {
                        winner = board[i][0];
                    }
                }
    
                // Vertical
                for (let i = 0; i < 3; i++) {
                    if (equals3(board[0][i], board[1][i], board[2][i])) {
                        winner = board[0][i];
                    }
                }
    
                // Diagonal
                if (equals3(board[0][0], board[1][1], board[2][2])) {
                    winner = board[0][0];
                }
                if (equals3(board[2][0], board[1][1], board[0][2])) {
                    winner = board[2][0];
                }
    
                let openSpots = 0;
                for (let i = 0; i < 3; i++) {
                    for (let j = 0; j < 3; j++) {
                        if (board[i][j] == '') {
                            openSpots++;
                        }
                    }
                }
    
                if (winner == null && openSpots == 0) {
                    return 'tie';
                } else {
                    return winner;
                }
            }
    
            function mousePressed() { 
                if (currentPlayer == human) {
                    // Human make turn
                    let i = floor(mouseX / w);
                    let j = floor(mouseY / h);
                    // If valid turn
                    if (board[i][j] == '') {
                        board[i][j] = human;
                        currentPlayer = ai;
                        bestMove();
                    }
                }
            }
    
            function draw() {
                background(255);
                strokeWeight(4);
    
                line(w, 0, w, height);
                line(w * 2, 0, w * 2, height);
                line(0, h, width, h);
                line(0, h * 2, width, h * 2);
    
                for (let j = 0; j < 3; j++) {
                    for (let i = 0; i < 3; i++) {
                        let x = w * i + w / 2;
                        let y = h * j + h / 2;
                        let spot = board[i][j];
                        textSize(32);
                        let r = w / 4;
                        if (spot == human) {
                            noFill();
                            ellipse(x, y, r * 2);
                        } else if (spot == ai) {
                            line(x - r, y - r, x + r, y + r);
                            line(x + r, y - r, x - r, y + r);
                        }
                    }
                }
    
                let result = checkWinner();
                if (result != null) {
                    noLoop();
                    let resultP = createP('');
                    resultP.style('font-size', '32pt');
                    if (result == 'tie') {
                        resultP.html('Tie!');
                    } else {
                        resultP.html(`${result} wins!`);
                    }
                }
            }
    
    
        function bestMove() {
                // bestMove AI要下棋的位置
                let bestScore = -Infinity;
                let move;
                for (let i = 0; i < 3; i++) {
                    for (let j = 0; j < 3; j++) {
                        if (board[i][j] == '') {
                            // 随便找一个空位置下
                            board[i][j] = ai;
                            // 使用minmax计算一下下这个空位置的得分怎么样
                            let score = minimax(board, 0, false);
                            // 计算完得分后将位置还原
                            board[i][j] = '';
                            // 如果当前得分大于最佳得分
                            if (score > bestScore) {
                                // 记录最佳得分
                                bestScore = score;
                                // 记录最佳得分位置
                                move = { i, j };
                            }
                        }
                    }
                }
                // 移动到最近得分位置
                board[move.i][move.j] = ai;
                // 切换角色
                currentPlayer = human;
            }
    
            let scores = {
                X: 1,
                O: -1,
                tie: 0
            };
    
            function minimax(board, depth, isMaximizing, alpha = -Infinity, beta = Infinity) {
                let result = checkWinner();
                if (result !== null) {
                    // 如果是x赢了就返回1,如果是o赢了返回-1,如果是平局返回0
                    return scores[result];
                }
                if (isMaximizing) {
                    // max层假设是玩家下的时候
                    for (let i = 0; i < 3; i++) {
                        for (let j = 0; j < 3; j++) {
                            if (board[i][j] == '') {
                                // 假设ai下的位置
                                board[i][j] = ai;
                                let score = minimax(board, depth + 1, false, alpha, beta);
                                board[i][j] = '';
                                // 1. 计算最低得分中最大的
                                alpha = max(score, alpha);
                                // 2. min层只选最小的,如果比最小的还大直接剪枝
                                // beta是min的上限,当前节点的最低得分里面的最大(alpha)已经大于了之前最小得分,直接剪枝
                                if (alpha >= beta) return alpha
                            }
                        }
                    }
                    // 返回min里面最大的那个
                    return alpha
                } else {
                    // min层假设是ai玩家下的时候
                    for (let i = 0; i < 3; i++) {
                        for (let j = 0; j < 3; j++) {
                            if (board[i][j] == '') {
                                board[i][j] = human;
                                let score = minimax(board, depth + 1, true, alpha, beta);
                                board[i][j] = '';
                                // 1. 计算最低得分
                                beta = min(beta, score)
                                // 2. max层只选最大的,比max层小的不用比较
                                // alpha代表的是max的下限,如果现在计算的最低得分比之前节点计算的最低得分要小直接剪枝
                                if (alpha >= beta) return beta
                            }
                        }
                    }
                    // 返回最低得分
                    return beta
                }
            }
    
  • 相关阅读:
    java作业总结1
    Java课程学习感想
    java第二阶段作业小结
    java第一阶段作业小结
    Java课程总结
    第二周期作业总结
    第一次作业周期总结
    Java第二阶段作业总结
    Java第一阶段作业总结
    java最后一阶段总结
  • 原文地址:https://www.cnblogs.com/pluslius/p/15042296.html
Copyright © 2011-2022 走看看