人机对战版aardio五子棋

popdes001 17小时前 49


还是AI 编程: 

提示词: 五子棋了解吗?帮我用aardio编写一个人机对战版程序

import win.ui;
import gdip;

/*DSG{{*/
var winform = win.form(text="五子棋 (人机对战版) - 挑战AI";right=560;bottom=580)
winform.add(
plus={cls="plus";left=0;top=0;right=560;bottom=580;db=1;dl=1;dr=1;dt=1;notify=1;z=1}
);
/*}}*/

// ==========================================
// 1. 游戏配置
// ==========================================
var boardSize = 15;
var cellSize = 35;
var margin = 30;
var pieceRadius = 15;

// 状态: 0:空, 1:黑子(玩家), 2:白子(电脑)
var boardData = {}; 
var isPlayerTurn = true; 
var isGameOver = false;
var lastMove = null;

// 重置游戏
var resetGame = function(){
    boardData = ..table.array(boardSize, ..table.array(boardSize, 0));
    isPlayerTurn = true; // 玩家执黑先行
    isGameOver = false;
    lastMove = null;
    winform.text = "五子棋 (人机对战) - 轮到你了";
    winform.plus.redraw();
}
resetGame();

// ==========================================
// 2. 基础逻辑 (胜负判定)
// ==========================================
var countLine = function(r, c, dr, dc, color){
    var count = 0;
    // 正向
    var i = 1;
    while(true){
        var nr, nc = r + dr*i, c + dc*i;
        if(nr<1 || nr>boardSize || nc<1 || nc>boardSize || boardData[nr][nc] != color) break;
        count++; i++;
    }
    // 反向
    i = 1;
    while(true){
        var nr, nc = r - dr*i, c - dc*i;
        if(nr<1 || nr>boardSize || nc<1 || nc>boardSize || boardData[nr][nc] != color) break;
        count++; i++;
    }
    return count + 1;
}

var checkWin = function(r, c, color){
    if(countLine(r, c, 1, 0, color) >= 5) return true;
    if(countLine(r, c, 0, 1, color) >= 5) return true;
    if(countLine(r, c, 1, 1, color) >= 5) return true;
    if(countLine(r, c, 1, -1, color) >= 5) return true;
    return false;
}

// ==========================================
// 3. AI 核心算法 (评分引擎)
// ==========================================

// 评分表 (权重)
var scoreTable = {
    win5  = 100000; // 连五
    live4 = 10000;  // 活四 (两头空)
    dead4 = 1000;   // 死四 (一头堵)
    live3 = 1000;   // 活三
    dead3 = 100;    // 死三
    live2 = 100;    // 活二
    dead2 = 10;     // 死二
}

// 计算某一点在某个方向上的棋型分数
var evaluateLine = function(r, c, dr, dc, color){
    var count = 1; // 假设落子在此
    var emptyEnds = 0;
    
    // 向前探
    var i = 1;
    while(true){
        var nr, nc = r + dr*i, c + dc*i;
        if(nr<1 || nr>boardSize || nc<1 || nc>boardSize) break; // 边界
        if(boardData[nr][nc] == color) count++;
        else {
            if(boardData[nr][nc] == 0) emptyEnds++; // 遇到空位
            break; // 遇到敌方或空位都停止计数
        }
        i++;
    }
    
    // 向后探
    i = 1;
    while(true){
        var nr, nc = r - dr*i, c - dc*i;
        if(nr<1 || nr>boardSize || nc<1 || nc>boardSize) break;
        if(boardData[nr][nc] == color) count++;
        else {
            if(boardData[nr][nc] == 0) emptyEnds++;
            break;
        }
        i++;
    }
    
    // 评分规则
    if(count >= 5) return scoreTable.win5;
    if(count == 4) return (emptyEnds == 2) ? scoreTable.live4 : (emptyEnds == 1 ? scoreTable.dead4 : 0);
    if(count == 3) return (emptyEnds == 2) ? scoreTable.live3 : (emptyEnds == 1 ? scoreTable.dead3 : 0);
    if(count == 2) return (emptyEnds == 2) ? scoreTable.live2 : (emptyEnds == 1 ? scoreTable.dead2 : 0);
    return 0;
}

// 计算某点总分 (进攻 + 防守)
var getPointScore = function(r, c){
    var score = 0;
    
    // 1. 进攻分 (如果电脑下这,对自己有多大好处)
    var myScore = 0;
    myScore += evaluateLine(r, c, 1, 0, 2); // 横
    myScore += evaluateLine(r, c, 0, 1, 2); // 竖
    myScore += evaluateLine(r, c, 1, 1, 2); // 捺
    myScore += evaluateLine(r, c, 1, -1, 2);// 撇
    
    // 2. 防守分 (如果玩家下这,对电脑有多大威胁)
    var enemyScore = 0;
    enemyScore += evaluateLine(r, c, 1, 0, 1);
    enemyScore += evaluateLine(r, c, 0, 1, 1);
    enemyScore += evaluateLine(r, c, 1, 1, 1);
    enemyScore += evaluateLine(r, c, 1, -1, 1);
    
    // 策略:进攻为主,但如果有致命威胁要防守
    // 简单的加法通常就足够聪明了
    return myScore + enemyScore;
}

// AI 思考并落子
var computerMove = function(){
    var maxScore = -1;
    var bestPoints = {}; // 存所有最高分的点
    
    // 遍历所有空位
    for(r=1; boardSize){
        for(c=1; boardSize){
            if(boardData[r][c] == 0){
                var s = getPointScore(r, c);
                
                // 如果是中心点,略微加分 (开局抢占天元)
                if(r==8 && c==8) s += 10;
                
                if(s > maxScore){
                    maxScore = s;
                    bestPoints = {{r=r, c=c}};
                } elseif(s == maxScore){
                    ..table.push(bestPoints, {r=r, c=c});
                }
            }
        }
    }
    
    // 如果有多个最高分,随机选一个
    var move = bestPoints[1];
    if(#bestPoints > 1){
        move = bestPoints[..math.random(1, #bestPoints)];
    }
    
    if(move){
        boardData[move.r][move.c] = 2; // 白子
        lastMove = move;
        winform.plus.redraw();
        
        if(checkWin(move.r, move.c, 2)){
            isGameOver = true;
            winform.text = "五子棋 - AI获胜! (右键重开)";
            win.msgbox("电脑赢了!人类还需要努力啊。");
        } else {
            isPlayerTurn = true;
            winform.text = "五子棋 - 轮到你了";
        }
    }
}

// ==========================================
// 4. 绘图渲染 (保持不变)
// ==========================================
winform.plus.onDrawForegroundEnd = function(graphics, rc){
    graphics.smoothingMode = 4;
    
    var brushBg = gdip.solidBrush(0xFFDEB887);
    graphics.fillRectangle(brushBg, 0, 0, rc.right, rc.bottom);
    brushBg.delete();
    
    var penLine = gdip.pen(0xFF000000, 1);
    for(i=1; boardSize){
        var pos = margin + (i-1) * cellSize;
        graphics.drawLine(penLine, margin, pos, margin+(boardSize-1)*cellSize, pos);
        graphics.drawLine(penLine, pos, margin, pos, margin+(boardSize-1)*cellSize);
    }
    penLine.delete();
    
    var stars = {4, 8, 12};
    for(i=1; #stars){
        for(j=1; #stars){
            var x, y = margin+(stars[j]-1)*cellSize, margin+(stars[i]-1)*cellSize;
            var b = gdip.solidBrush(0xFF000000); graphics.fillEllipse(b, x-3, y-3, 6, 6); b.delete();
        }
    }
    
    for(r=1; boardSize){
        for(c=1; boardSize){
            var val = boardData[r][c];
            if(val == 0) continue;
            var x, y = margin+(c-1)*cellSize, margin+(r-1)*cellSize;
            var color = (val == 1) ? 0xFF000000 : 0xFFFFFFFF;
            var b = gdip.solidBrush(color);
            graphics.fillEllipse(b, x-pieceRadius, y-pieceRadius, pieceRadius*2, pieceRadius*2);
            b.delete();
            if(val == 2){
                var p = gdip.pen(0xFFCCCCCC, 1); graphics.drawEllipse(p, x-pieceRadius, y-pieceRadius, pieceRadius*2, pieceRadius*2); p.delete();
            }
        }
    }
    
    if(lastMove){
        var x, y = margin+(lastMove.c-1)*cellSize, margin+(lastMove.r-1)*cellSize;
        var b = gdip.solidBrush(0xFFFF0000); graphics.fillRectangle(b, x-3, y-3, 6, 6); b.delete();
    }
}

// ==========================================
// 5. 鼠标交互
// ==========================================
winform.plus.onMouseDown = function(wParam, lParam){
    if(wParam == 0x204){ // 右键重开
        if(win.msgboxTest("确定要重新开始吗?", "五子棋")) resetGame();
        return;
    }
    
    if(isGameOver || !isPlayerTurn) return; // 游戏结束或AI思考时禁止点击
    
    var x, y = win.getMessagePos(lParam);
    var c = ..math.round((x - margin) / cellSize) + 1;
    var r = ..math.round((y - margin) / cellSize) + 1;
    
    if(r < 1 || r > boardSize || c < 1 || c > boardSize) return;
    if(boardData[r][c] != 0) return;
    
    // --- 玩家落子 ---
    boardData[r][c] = 1; // 黑子
    lastMove = {r=r, c=c};
    winform.plus.redraw();
    
    if(checkWin(r, c, 1)){
        isGameOver = true;
        winform.text = "五子棋 - 玩家获胜!";
        win.msgbox("恭喜!你战胜了AI!");
    } else {
        isPlayerTurn = false;
        winform.text = "五子棋 - AI思考中...";
        // 延迟一点点执行,让UI先刷新出玩家的子,看起来更自然
        winform.setTimeout(computerMove, 50); 
    }
}

winform.show();
win.loopMessage();


最新回复 (2)
  • 光庆 16小时前
    0 2

  • shzhbook 16小时前
    0 3
    AI现在这么强了,连aardio的代码都可以直接生成了?
返回
发新帖