用Gemini AI编写的aardio版本[五子棋]游戏
By
admin
at 7 天前 • 0人收藏 • 68人看过
全程Gemini Pro AI 一次性生成 , 五子棋游戏, 摸鱼必备!
2026年了, 分分钟一个软件还会远吗? 有想法有创意, 编程的事情交给AI...
提示词: 五子棋了解吗? 帮我用aardio编写一个这样的程序

import win.ui;
import gdip;
/*DSG{{*/
var winform = win.form(text="五子棋 (双人对战版) - aardio演示";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; // 15路棋盘
var cellSize = 35; // 格子大小
var margin = 30; // 棋盘边缘留白
var pieceRadius = 15; // 棋子半径
// 游戏状态
// 0:空, 1:黑子, 2:白子
var boardData = {};
var isBlackTurn = true; // 当前是否黑方落子
var isGameOver = false;
var lastMove = null; // 记录最后一步 {r, c},用于高亮显示
// 初始化/重置棋盘
var resetGame = function(){
boardData = ..table.array(boardSize, ..table.array(boardSize, 0));
isBlackTurn = true;
isGameOver = false;
lastMove = null;
winform.text = "五子棋 - 黑方执黑先行";
winform.plus.redraw();
}
resetGame();
// ==========================================
// 2. 核心逻辑:胜负判断
// ==========================================
// 检查某个方向是否有5连
// r, c: 当前落子坐标
// dr, dc: 方向增量 (例如 1,0 表示横向)
// color: 当前棋子颜色 (1或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) break;
if(boardData[nr][nc] == color) count++;
else 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 break;
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. 绘图渲染
// ==========================================
winform.plus.onDrawForegroundEnd = function(graphics, rc){
graphics.smoothingMode = 4/*_SmoothingModeAntiAlias*/;
// 1. 绘制棋盘背景 (木纹色)
var brushBg = gdip.solidBrush(0xFFDEB887);
graphics.fillRectangle(brushBg, 0, 0, rc.right, rc.bottom);
brushBg.delete();
// 2. 绘制网格线
var penLine = gdip.pen(0xFF000000, 1);
for(i=1; boardSize; 1){
var pos = margin + (i-1) * cellSize;
// 横线
var startX, endX = margin, margin + (boardSize-1)*cellSize;
graphics.drawLine(penLine, startX, pos, endX, pos);
// 竖线
var startY, endY = margin, margin + (boardSize-1)*cellSize;
graphics.drawLine(penLine, pos, startY, pos, endY);
}
penLine.delete();
// 3. 绘制星位 (天元和四个星)
var drawStar = function(r, c){
var x = margin + (c-1) * cellSize;
var y = margin + (r-1) * cellSize;
var brush = gdip.solidBrush(0xFF000000);
graphics.fillEllipse(brush, x-3, y-3, 6, 6);
brush.delete();
}
// 标准15路盘星位:4, 8, 12
var stars = {4, 8, 12};
for(i=1; #stars){
for(j=1; #stars){
drawStar(stars[i], stars[j]);
}
}
// 4. 绘制棋子
for(r=1; boardSize){
for(c=1; boardSize){
var val = boardData[r][c];
if(val == 0) continue;
var x = margin + (c-1) * cellSize;
var y = margin + (r-1) * cellSize;
// 棋子带一点阴影效果
// var brushShadow = gdip.solidBrush(0x50000000);
// graphics.fillEllipse(brushShadow, x-pieceRadius+2, y-pieceRadius+2, pieceRadius*2, pieceRadius*2);
// brushShadow.delete();
var color = (val == 1) ? 0xFF000000 : 0xFFFFFFFF;
var brushPiece = gdip.solidBrush(color);
graphics.fillEllipse(brushPiece, x-pieceRadius, y-pieceRadius, pieceRadius*2, pieceRadius*2);
brushPiece.delete();
// 如果是白子,画个细黑边,防止和背景混淆
if(val == 2){
var penPiece = gdip.pen(0xFFCCCCCC, 1);
graphics.drawEllipse(penPiece, x-pieceRadius, y-pieceRadius, pieceRadius*2, pieceRadius*2);
penPiece.delete();
}
}
}
// 5. 标记最后一步 (红色小方块)
if(lastMove){
var x = margin + (lastMove.c-1) * cellSize;
var y = margin + (lastMove.r-1) * cellSize;
var brushMark = gdip.solidBrush(0xFFFF0000);
graphics.fillRectangle(brushMark, x-3, y-3, 6, 6);
brushMark.delete();
}
// 6. 游戏结束文字
if(isGameOver){
var font = gdip.font("微软雅黑", 24, 1);
var brushText = gdip.solidBrush(0xFFFF0000);
var msg = (isBlackTurn ? "白方" : "黑方") + "获胜! (右键重开)";
graphics.drawString(msg, font, ::RECTF(50, 200, 500, 300), gdip.stringformat(), brushText);
font.delete(); brushText.delete();
}
}
// ==========================================
// 4. 鼠标交互
// ==========================================
winform.plus.onMouseDown = function(wParam, lParam){
// 右键重开
if(wParam == 0x204/*_WM_RBUTTONDOWN*/){
if(win.msgboxTest("确定要重新开始吗?", "五子棋")){
resetGame();
}
return;
}
if(isGameOver) return;
var x, y = win.getMessagePos(lParam);
// 1. 坐标换算:将屏幕像素转换为网格索引
// 使用 round 实现"吸附"效果,点击交叉点附近都算该点
var c = ..math.round((x - margin) / cellSize) + 1;
var r = ..math.round((y - margin) / cellSize) + 1;
// 2. 边界检查与空位检查
if(r < 1 || r > boardSize || c < 1 || c > boardSize) return;
if(boardData[r][c] != 0) return; // 已经有子了
// 3. 落子
var color = isBlackTurn ? 1 : 2;
boardData[r][c] = color;
lastMove = {r=r, c=c};
winform.plus.redraw(); // 立即重绘显示落子
// 4. 胜负判断
if(checkWin(r, c, color)){
isGameOver = true;
winform.text = "五子棋 - 游戏结束";
winform.plus.redraw();
// win.msgbox((isBlackTurn ? "黑方" : "白方") + "获胜!");
}
else {
// 5. 换手
isBlackTurn = !isBlackTurn;
winform.text = "五子棋 - 轮到" + (isBlackTurn ? "黑" : "白") + "方";
}
}
winform.show();
win.loopMessage();
1 个回复 | 最后更新于 7 天前
登录后方可回帖
人机对战版:
提示词: 帮我改成人机对战版
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();修改要点解析
AI 评分机制 (getPointScore): 这是 AI 的“大脑”。代码模拟了人类下棋的思维:
AI 会遍历棋盘上每一个空点。
进攻(MyScore):计算“如果我下这,能连成什么样?”(例如:下这能连成 4 个,必胜,分数极高)。
防守(EnemyScore):计算“如果我不下这,让玩家下这,他能连成什么样?”(例如:玩家下这就能连成活三,很危险,分数也很高)。
最后取两者的总和。这意味着 AI 既想赢(进攻),也怕输(堵截玩家的关键子)。
权重设计 (scoreTable):
win5 (100,000):必须赢,优先级最高。
live4 (10,000):活四(两头空),下一步必胜,优先级次之。
dead4 / live3 (1,000):死四或者活三,属于极具威胁的棋型。 通过调整这些数值,你可以改变 AI 的性格(比如进攻型或防守型)。
回合制管理:
增加了 isPlayerTurn 变量。
在 onMouseDown 中,玩家下完子后,立即锁定输入,设置 isPlayerTurn = false。
使用 winform.setTimeout(computerMove, 50) 稍微延迟执行 AI 代码。这样做的好处是让界面有机会重绘,显示出玩家刚下的那颗黑子,然后再开始卡顿计算 AI。如果不延迟,界面会卡住,感觉像死机了一样。
如何获胜?
这个 AI 只有“一步预测”能力(它只看当前局面的最佳落点,不会预测未来几步)。虽然比较基础,但对于初学者来说已经相当难缠了。要赢它,你需要利用“双三”或者“四三”战术,同时制造两个威胁,让它顾此失彼。