寻求更优随机数生成器(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
相关产品推荐
相关产品推荐

