AI全自动编写aardio版"圈住小猫"的经典智力游戏

popdes001 3天前 129


全自动AI编写: 圈住小黑猫

你真的不试试 AI ?

import win.ui;
import gdip;

/*DSG{{*/
var winform = win.form(text="圈住小猫 (Catch the Cat) - aardio版";right=600;bottom=650)
winform.add(
plus={cls="plus";left=0;top=0;right=600;bottom=650;db=1;dl=1;dr=1;dt=1;notify=1;z=1}
);
/*}}*/

// ==========================================
// 1. 游戏地图初始化
// ==========================================
var gridSize = 11; // 11x11 网格
var map = {};      // 0:空地, 1:障碍物
var catPos = { r = 5, c = 5 }; // 小猫初始位置 (行, 列)

// 初始化地图
var initMap = function(){
    map = {};
    for(r=0; gridSize-1; 1){
        map[r] = {};
        for(c=0; gridSize-1; 1){
            map[r][c] = (..math.random(1, 100) < 15) ? 1 : 0; // 15% 几率随机障碍
        }
    }
    map[catPos.r][catPos.c] = 0; // 小猫位置不能有障碍
}
initMap();

// ==========================================
// 2. 小猫 AI (寻路算法)
// ==========================================
// 获取相邻坐标 (六边形网格逻辑)
var getNeighbors = function(r, c){
    var neighbors = {};
    // 六边形网格:偶数行和奇数行的偏移不同
    var offset = (r % 2 == 0) ? {{-1, -1}, {-1, 0}, {0, -1}, {0, 1}, {1, -1}, {1, 0}} 
                              : {{-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, 0}, {1, 1}};
    for(i=1; #offset){
        var nr, nc = r + offset[i][1], c + offset[i][2];
        if(nr >= 0 && nr < gridSize && nc >= 0 && nc < gridSize){
            ..table.push(neighbors, {r=nr, c=nc});
        }
    }
    return neighbors;
}

// 寻找逃跑路径 (BFS)
var findPath = function(start){
    var queue = {{r=start.r, c=start.c, path={}}};
    var visited = {};
    visited[start.r + "_" + start.c] = true;
    
    while(#queue > 0){
        var curr = ..table.remove(queue, 1);
        
        // 如果到达边缘,返回路径的第一步
        if(curr.r == 0 || curr.r == gridSize-1 || curr.c == 0 || curr.c == gridSize-1){
            return curr.path[1] || curr; 
        }
        
        var neighbors = getNeighbors(curr.r, curr.c);
        for(i=1; #neighbors){
            var n = neighbors[i];
            var key = n.r + "_" + n.c;
            if(!visited[key] && map[n.r][n.c] == 0){
                visited[key] = true;
                var newPath = ..table.clone(curr.path);
                ..table.push(newPath, n);
                ..table.push(queue, {r=n.r, c=n.c, path=newPath});
            }
        }
    }
    return null; // 无路可逃
}

// ==========================================
// 3. 绘图与逻辑交互
// ==========================================
var cellSize = 40;
var offsetX = 50;
var offsetY = 80;

winform.plus.onDrawForegroundEnd = function(graphics, rc){
    graphics.smoothingMode = 4;
    
    for(r=0; gridSize-1; 1){
        for(c=0; gridSize-1; 1){
            // 计算六边形布局的 X 偏移
            var x = c * cellSize + ( (r % 2 == 1) ? cellSize/2 : 0 ) + offsetX;
            var y = r * cellSize * 0.85 + offsetY;
            
            var brush;
            if(r == catPos.r && c == catPos.c){
                brush = gdip.solidBrush(0xFF000000); // 小猫是黑色
            } elseif(map[r][c] == 1){
                brush = gdip.solidBrush(0xFFFF6600); // 障碍物是橙色
            } else {
                brush = gdip.solidBrush(0xFFB0C4DE); // 空地是浅蓝色
            }
            
            graphics.fillEllipse(brush, x, y, cellSize-5, cellSize-5);
            brush.delete();
        }
    }
    
    var font = gdip.font("微软雅黑", 14);
    graphics.drawString("目标:圈住黑色小猫!别让它逃出边界。", font, ::RECTF(50, 20, 500, 50), , gdip.solidBrush(0xFF333333));
}

winform.plus.onMouseDown = function(wParam, lParam){
    var mx, my = win.getMessagePos(lParam);
    
    // 简单的碰撞检测:反推点击了哪个圆
    for(r=0; gridSize-1; 1){
        for(c=0; gridSize-1; 1){
            var x = c * cellSize + ( (r % 2 == 1) ? cellSize/2 : 0 ) + offsetX;
            var y = r * cellSize * 0.85 + offsetY;
            
            // 判断点击是否在圆内
            var dist = ..math.sqrt((mx - (x + cellSize/2))**2 + (my - (y + cellSize/2))**2);
            if(dist < cellSize/2){
                if(map[r][c] == 0 && !(r == catPos.r && c == catPos.c)){
                    map[r][c] = 1; // 放置障碍
                    
                    // 小猫移动
                    var nextStep = findPath(catPos);
                    if(nextStep){
                        catPos.r, catPos.c = nextStep.r, nextStep.c;
                        // 判断失败
                        if(catPos.r == 0 || catPos.r == gridSize-1 || catPos.c == 0 || catPos.c == gridSize-1){
                            win.msgbox("小猫逃走了!游戏结束。");
                            initMap(); catPos = {r=5, c=5};
                        }
                    } else {
                        win.msgbox("太棒了!你成功圈住了小猫!");
                        initMap(); catPos = {r=5, c=5};
                    }
                    winform.plus.redraw();
                }
                return;
            }
        }
    }
}

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


AI自己对它代码的注释:

游戏开发要点:

  1. 六边形布局算法:

    在代码中,x 的计算加入了 (r % 2 == 1) ? cellSize/2 : 0。这是为了让奇数行相对于偶数行错开半个身位,从而形成蜂窝状结构。这是“圈住小猫”游戏逻辑的核心,因为这种结构决定了每个点有 6 个邻居。

  2. BFS (广度优先搜索):

    代码中的 findPath 函数模拟了小猫的智商。它会扫描所有可能的路径,找到通往地图边缘($r=0, c=0$ 等)的最短路线。如果没有找到路径,说明玩家赢了。

  3. 坐标变换思路的延续:

    虽然这是 2D 游戏,但处理方式与你提供的 3D 代码非常相似:

    • 状态管理:使用 map 数组存储场景状态。

    • 坐标转换:将逻辑坐标 (r, c) 转换为屏幕绘图坐标 (x, y)

    • 交互响应:在 onMouseDown 中通过反向坐标计算来实现点击判定。

你可以直接运行这段代码,在界面上点击圆点来围堵那只“黑色小猫”!


最新回复 (3)
  • mfk 3天前
    0 2

  • 小肥羊 1天前
    0 3
    gemini3确实NB的,对aardio的支持也相当好。
  • shzhbook 16小时前
    0 4
    很久没看到大佬了,感谢分享。
返回
发新帖