You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求更优随机数生成器(RNG)以优化过程化洞穴生成效果

搞定过程化洞穴生成的细碎噪点问题

嘿,我来帮你解决这个洞穴生成的困扰!其实你当前的核心问题不只是RNG的用法,更关键的是只做了初始随机填充,没执行细胞自动机的迭代规则——这才是生成连贯洞穴纹理的核心。咱们一步步来修复:

1. 先修正Random的错误用法

你在initialiseMap的x循环里每次都新建Random实例,这会因为系统时钟的精度限制,导致多个Random用相同的种子初始化,生成重复的随机序列。正确的做法是只创建一次Random实例:

public static Boolean[,] initialiseMap() {
    Boolean[,] map = new Boolean[width, height];
    // 只初始化一次随机数生成器
    Random rng = new Random();
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            double random = rng.NextDouble(); // 这里你之前拼写错了doube,要改成double
            if (random < chanceToStartAlive) {
                map[x,y] = true;
            }
        }
    }
    return map;
}

另外注意代码里的小拼写错误:doube random要改成double random,不然会编译报错。

2. 添加细胞自动机迭代步骤(重中之重)

你想要的那种连贯洞穴纹理,是通过细胞自动机迭代生成的——简单说就是反复根据邻域单元格的状态来更新当前单元格,把细碎噪点平滑成连贯区域。典型的洞穴生成规则如下:

  • 遍历每个单元格,统计它3x3邻域内的“存活”(白色)单元格数量
  • 存活单元格:如果邻域存活数少于3则死亡(消除孤立点)
  • 死亡单元格:如果邻域存活数多于4则复活(形成连贯的洞穴区域)

添加下面的迭代和辅助方法:

// 执行一次细胞自动机迭代
public static Boolean[,] iterateMap(Boolean[,] oldMap) {
    Boolean[,] newMap = new Boolean[width, height];
    // 跳过边界,避免数组越界
    for (int x = 1; x < width - 1; x++) {
        for (int y = 1; y < height - 1; y++) {
            int aliveNeighbors = countAliveNeighbors(oldMap, x, y);
            // 根据规则更新单元格状态
            if (oldMap[x, y]) {
                // 存活单元格:邻域存活数≥3才保留
                newMap[x, y] = aliveNeighbors >= 3;
            } else {
                // 死亡单元格:邻域存活数>4则复活
                newMap[x, y] = aliveNeighbors > 4;
            }
        }
    }
    // 把边界设为死亡(黑色),避免边缘出现奇怪的纹理
    for (int x = 0; x < width; x++) {
        newMap[x, 0] = false;
        newMap[x, height - 1] = false;
    }
    for (int y = 0; y < height; y++) {
        newMap[0, y] = false;
        newMap[width - 1, y] = false;
    }
    return newMap;
}

// 统计3x3邻域内的存活单元格数量
public static int countAliveNeighbors(Boolean[,] map, int x, int y) {
    int count = 0;
    for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
            // 跳过当前单元格本身
            if (i == 0 && j == 0) continue;
            if (map[x + i, y + j]) {
                count++;
            }
        }
    }
    return count;
}

3. 修改Main方法执行迭代

生成初始地图后,执行4-8次迭代(次数可以自己调整,一般4次就能得到不错的效果):

static void Main(string[] args) {
    Boolean[,] map = initialiseMap();
    // 执行4次迭代,你可以试试调整次数看效果
    for (int i = 0; i < 4; i++) {
        map = iterateMap(map);
    }
    Bitmap bmp = createImage(map);
    bmp.Save("C:\\Users\\radu\\Documents\\Sync\\Licenta\\chamber.png");
}

4. 关于更优的RNG(可选)

如果确实需要更高质量的随机数(比如避免伪随机的周期性),可以考虑这些选项:

  • 使用System.Security.Cryptography.RandomNumberGenerator生成加密安全的随机数,但对于洞穴生成来说,正确使用的普通Random已经完全足够
  • 第三方库比如MathNet.Numerics提供的随机数生成器,但一般没必要,除非你需要极端高质量的随机分布

额外小修复

你的createImage方法里有个多余的Console.Write('\n');,这会导致控制台输出大量空行,建议删掉它。

这样修改后,生成的地图就会从细碎噪点变成连贯的洞穴纹理,和你想要的效果一致啦!

内容的提问来源于stack exchange,提问作者radu nicolae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:15:42