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

如何用Python随机生成ASCII艺术风格的陆地地形?

解决ASCII地形生成偏科问题的几种方法

嘿,我看你写的代码遇到了挺典型的问题——生成的地形要么全是水域要么全是陆地,根本达不到混合分布的预期。其实问题核心在于你那套概率调整逻辑:每次根据上一个tile直接大幅修改waterChance,会形成极端的累积偏向。比如第一次随机到水,waterChance加10,下一次生成水的概率更高,接着又加10,循环下去整个地图直接变成水世界;要是第一个tile是陆地,概率会持续降低,最后全是陆地。

下面给你几个实用的解决思路,从简单到进阶都有:

方法一:平滑局部影响+概率边界限制

这个方法保留你“相邻tile影响地形”的思路,但调整幅度更小,同时给概率加个边界,不让它跑偏:

from random import randint

water = "."
land = "#"
base_water_chance = 40  # 基础概率,决定整体水/陆比例
width = 40
height = 20
level = []

for i in range(height):
    level.append([])
    for j in range(width):
        current_water_chance = base_water_chance
        
        # 参考左边的tile(同一行已生成的前一个),小幅调整概率
        if j > 0:
            if level[i][j-1] == water:
                current_water_chance += 5
            else:
                current_water_chance -= 5
        
        # 参考上方的tile(上一行同列),进一步调整
        if i > 0:
            if level[i-1][j] == water:
                current_water_chance += 5
            else:
                current_water_chance -= 5
        
        # 把概率锁在0-100之间,避免极端值
        current_water_chance = max(0, min(100, current_water_chance))
        
        # 随机生成当前tile
        tile = water if randint(1, 100) <= current_water_chance else land
        level[i].append(tile)

# 打印生成的地形
for row in level:
    print("".join(row))

为什么这能行?

  • 每次调整幅度只有±5,不会一下子把概率拉到极端
  • 同时参考左右和上下的tile,地形连贯性更好
  • 基础概率base_water_chance可以直接控制整体水/陆比例,比如设为50就是大致对半分

方法二:用Perlin Noise生成自然地形

如果想要更真实、像现实中湖泊山脉那样的地形,试试经典的分形噪声(Perlin Noise),这是游戏里生成地形的常用方法:

首先需要安装noise库:

pip install noise

然后运行下面的代码:

import noise
import random

water = "."
land = "#"
width = 40
height = 20
scale = 5.0  # 控制地形粗糙程度:值越小越细碎,越大越平缓
water_threshold = 0.0  # 噪声值低于这个数是水,高于是陆地

# 随机种子,保证每次生成的地形不一样
random.seed()
seed = random.randint(0, 1000)

level = []
for y in range(height):
    row = []
    for x in range(width):
        # 生成Perlin噪声值,范围大概在-1到1之间
        noise_val = noise.pnoise2(x/scale, y/scale, octaves=3, seed=seed)
        # 根据阈值判断是水还是陆地
        row.append(water if noise_val < water_threshold else land)
    level.append(row)

# 打印地形
for row in level:
    print("".join(row))

怎么调整比例?

  • 调water_threshold:比如设为-0.2会增加陆地面积,设为0.2会增加水域面积
  • 调scale:值越大,地形的区块越大,比如设为10会生成更大的湖泊或陆地

方法三:极简版全局概率+局部微调

如果你不想改太多代码,也可以用这个简单方案——每次基于基础概率调整,而不是在上一次的调整值上累积:

from random import randint

water = "."
land = "#"
base_water_chance = 40
width = 40
height = 20
level = []

for i in range(height):
    level.append([])
    for j in range(width):
        current_chance = base_water_chance
        # 只参考左边的tile,小幅微调概率,不累积
        if j > 0:
            if level[i][j-1] == water:
                current_chance += 15
            else:
                current_chance -= 15
        # 限制概率在20-80之间,避免极端
        current_chance = max(20, min(80, current_chance))
        tile = water if randint(1,100) <= current_chance else land
        level[i].append(tile)

for row in level:
    print("".join(row))

这个方案最贴近你原来的代码逻辑,但去掉了概率累积的问题,生成的地形会有自然的小块分布。

内容的提问来源于stack exchange,提问作者Jordan Baron

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:33:17