利用aardio制作简单的五子棋游戏

Mr_MAO 1天前 75

import win.ui;
/*DSG{{*/
var winform = win.form(text="五子棋游戏 (By: Mr_MAO)";right=760;bottom=620;bgcolor=0xFFFFFF;border="dialog frame";max=false)
winform.add(
boardPlus={cls="plus";left=10;top=10;right=610;bottom=610;bgcolor=0xFFFFFF;edge=1;forecolor=0xFFFFFF;notify=1;z=1};
btnRestart={cls="button";text="重新开始";left=630;top=20;right=730;bottom=60;z=2};
staticInfo={cls="static";text="玩家执黑先行";left=630;top=80;right=730;bottom=200;transparent=1;z=3}
)
/*}}*/

// --- 游戏配置 ---
var boardSize = 15;   // 棋盘 15x15
var cellSize = 40;    // 格子变大一点,视觉更好
var margin = 20;      // 棋盘边缘留白
var pieceRadius = 17; // 棋子半径

// --- 游戏状态 ---
var board = {};       // 存储棋盘数据 0:空, 1:黑(玩家), 2:白(电脑)
var isPlayerTurn = true; 
var isGameOver = false;

// --- 初始化/重置游戏 ---
function initGame(){
    for(r=1;boardSize){
        board[r] = {};
        for(c=1;boardSize){
            board[r][c] = 0;
        }
    }
    isPlayerTurn = true;
    isGameOver = false;
    winform.staticInfo.text = '当前回合:\n玩家 (黑棋)';
    winform.boardPlus.redraw(); 
}

// --- Plus控件绘图逻辑 ---
winform.boardPlus.onDrawForegroundEnd = function(graphics,rc){
    graphics.smoothingMode = 4; // 抗锯齿

    // 1. 绘制棋盘底色 (在Plus区域内)
    var brushBg = gdip.solidBrush(0xFFEEDD82); 
    graphics.fillRectangle(brushBg, 0, 0, rc.width, rc.height);
    brushBg.delete();

    // 2. 绘制网格线
    var penLine = gdip.pen(0xFF000000, 1);
    var boardWidth = (boardSize-1) * cellSize;
    
    // 确保网格居中绘制
    var offsetX = margin;
    var offsetY = margin;

    for(i=1;boardSize){
        var pos = (i-1)*cellSize;
        // 横线
        graphics.drawLine(penLine, offsetX, offsetY + pos, offsetX + boardWidth, offsetY + pos);
        // 竖线
        graphics.drawLine(penLine, offsetX + pos, offsetY, offsetX + pos, offsetY + boardWidth);
    }
    
    // 3. 绘制天元和星位
    var brushDot = gdip.solidBrush(0xFF000000);
    var stars = {4;8;12};
    for(i=1;3){
        for(j=1;3){
            var x = offsetX + (stars[i]-1)*cellSize;
            var y = offsetY + (stars[j]-1)*cellSize;
            graphics.fillEllipse(brushDot, x-4, y-4, 8, 8);
        }
    }
    brushDot.delete();
    
    // 4. 绘制棋子
    var brushBlack = gdip.solidBrush(0xFF000000);
    var brushWhite = gdip.solidBrush(0xFFFFFFFF);
    var penBorder = gdip.pen(0xFFAAAAAA, 1);

    for(r=1;boardSize){
        for(c=1;boardSize){
            if(board[r][c] != 0){
                var px = offsetX + (c-1)*cellSize;
                var py = offsetY + (r-1)*cellSize;
                
                if(board[r][c] == 1){
                    // 黑棋 + 简单的反光效果
                    graphics.fillEllipse(brushBlack, px-pieceRadius, py-pieceRadius, pieceRadius*2, pieceRadius*2);
                    var brushShine = gdip.solidBrush(0x50FFFFFF);
                    graphics.fillEllipse(brushShine, px-pieceRadius+5, py-pieceRadius+5, 10, 10);
                    brushShine.delete();
                } elseif(board[r][c] == 2){
                    // 白棋
                    graphics.fillEllipse(brushWhite, px-pieceRadius, py-pieceRadius, pieceRadius*2, pieceRadius*2);
                    graphics.drawEllipse(penBorder, px-pieceRadius, py-pieceRadius, pieceRadius*2, pieceRadius*2);
                }
            }
        }
    }
    
    brushBlack.delete();
    brushWhite.delete();
    penLine.delete();
    penBorder.delete();
}

// --- 胜负判定 ---
function checkWin(r, c, color){
    var directions = {{1;0}; {0;1}; {1;1}; {1;-1}};
    for(k=1;4){
        var count = 1;
        var dr = directions[k][1];
        var dc = directions[k][2];
        
        // 正向
        var i = 1;
        while(true){
            var nr = r + dr*i;
            var nc = c + dc*i;
            if(nr<1 || nr>boardSize || nc<1 || nc>boardSize || board[nr][nc]!=color) break;
            count++; i++;
        }
        // 反向
        i = 1;
        while(true){
            var nr = r - dr*i;
            var nc = c - dc*i;
            if(nr<1 || nr>boardSize || nc<1 || nc>boardSize || board[nr][nc]!=color) break;
            count++; i++;
        }
        if(count >= 5) return true;
    }
    return false;
}

// --- AI 逻辑 ---
function evaluatePoint(r, c, color){
    var score = 0;
    var directions = {{1;0}; {0;1}; {1;1}; {1;-1}};
    for(k=1;4){
        var dr = directions[k][1];
        var dc = directions[k][2];
        var count = 1; 
        var emptySides = 0;
        
        // Check side 1
        var i = 1;
        while(true){
            var nr = r + dr*i;
            var nc = c + dc*i;
            if(nr<1||nr>boardSize||nc<1||nc>boardSize) break;
            if(board[nr][nc]==color) count++;
            elseif(board[nr][nc]==0){ emptySides++; break;}
            else break;
            i++;
        }
        // Check side 2
        i = 1;
        while(true){
            var nr = r - dr*i;
            var nc = c - dc*i;
            if(nr<1||nr>boardSize||nc<1||nc>boardSize) break;
            if(board[nr][nc]==color) count++;
            elseif(board[nr][nc]==0){ emptySides++; break;}
            else break;
            i++;
        }
        
        if(count >= 5) score += 100000;
        elseif(count == 4 && emptySides == 2) score += 10000;
        elseif(count == 4 && emptySides == 1) score += 1000;
        elseif(count == 3 && emptySides == 2) score += 1000;
        elseif(count == 3 && emptySides == 1) score += 100;
        elseif(count == 2 && emptySides == 2) score += 100;
        elseif(count == 2 && emptySides == 1) score += 10;
    }
    return score;
}

function computerMove(){
    if(isGameOver) return;
    var maxScore = -1;
    var bestPoints = {};
    
    for(r=1;boardSize){
        for(c=1;boardSize){
            if(board[r][c] == 0){
                // 进攻(己方) + 防守(敌方)
                var attack = evaluatePoint(r, c, 2);
                var defend = evaluatePoint(r, c, 1);
                var total = attack + defend;
                if(attack >= 100000) total = 9999999; // 必胜
                
                if(total > maxScore){
                    maxScore = total;
                    bestPoints = {{r;c}};
                } elseif(total == maxScore){
                    table.push(bestPoints, {r;c});
                }
            }
        }
    }
    
    if(#bestPoints == 0) return;
    var move = bestPoints[math.random(1, #bestPoints)];
    
    board[move[1]][move[2]] = 2;
    winform.boardPlus.redraw();
    
    if(checkWin(move[1], move[2], 2)){
        isGameOver = true;
        winform.msgbox("电脑获胜!","游戏结束");
        return;
    }
    
    isPlayerTurn = true;
    winform.staticInfo.text = '当前回合:\n玩家 (黑棋)';
}

// --- 交互事件绑定到 Plus 控件 ---
winform.boardPlus.onMouseDown = function(wParam,lParam){
    if(isGameOver || !isPlayerTurn) return;
    
    // 获取相对于 Plus 控件的坐标
    var x,y = win.getMessagePos(lParam);
    
    // 坐标换算为行列
    var c = math.round((x - margin) / cellSize) + 1;
    var r = math.round((y - margin) / cellSize) + 1;
    
    // 边界检查
    if(c < 1 || c > boardSize || r < 1 || r > boardSize) return;
    
    // 模糊点击范围检查 (防止点在格子中间也落子)
    var centerX = margin + (c-1)*cellSize;
    var centerY = margin + (r-1)*cellSize;
    var dist = math.sqrt( (x-centerX)**2 + (y-centerY)**2 );
    if(dist > pieceRadius + 5) return; // 距离交叉点太远则无效
    
    // 检查空位
    if(board[r][c] != 0) return;
    
    // 玩家落子
    board[r][c] = 1;
    winform.boardPlus.redraw(); // 触发 onDraw
    
    if(checkWin(r, c, 1)){
        isGameOver = true;
        winform.msgbox("你赢了!","游戏结束");
        return;
    }
    
    isPlayerTurn = false;
    winform.staticInfo.text = '当前回合:\n电脑思考中...';
    
    // 延时让电脑下棋,避免界面卡顿
    winform.setTimeout(function(){
        computerMove();
    }, 50);
}

winform.btnRestart.oncommand = function(id,event){
    initGame();
}

initGame(); //运行程序后,直接开始游戏

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


最新回复 (1)
  • mfk 21小时前
    0 2

    太棒了


返回