下载 App
《物种大陆》开发日志Day6
修改于10/169 浏览综合
2026.10.6 晴
今天天气晴朗,起个早,锻炼身体,先去爬了个400多米的紫金山,然后中午回来开始写代码。
今天的代码是重点是生成随机地块。要求是一共60个格子,一行10个,一共6行。分别生成不同的地形,地形包括:"草原", "森林", "湿地", "山脉", "沙漠", "雪地", "海洋",其中海洋为边缘修饰,不参与计算。其他6种地形,根据一定比例生成。其中60个地块,取30-45个地块作为可用的,其他都是海洋。这45个地块要从中心地带连续,随机生成。每次都生成不同的地形。先思考了2个小时,也没想到好的办法,于是就把要求描述好,问DEEPSEEK,5秒不到,DEEPSEEK就给写好了,虽然方法有一些问题,但是经过几轮调试,测试后,还是完成了这个功能。分享下代码如下:

public static List<DiKuai> GetRandomDiKuais(int count)
{
// 参数校验:count 限制在 30-40 之间
if (count < 30) count = 30;
if (count > 40) count = 40;
const int rows = 6;
const int cols = 10;
const int total = rows * cols; // 60
// 初始化 60 个格子,默认全部为海洋
var list = new List<DiKuai>(total);
for (int i = 1; i <= total; i++)
{
DiKuai dk = new DiKuai();
dk.id = i;
dk.type = DiKuaiType.HaiYang;
dk.pic = DiKuai.GetDiKuaiPicName(dk.type);
dk.name = DiKuai.GetDiKuaiName(dk.type);
dk.maxZhiWuXiShu = 1000000;
dk.curZhiWuXiShu = 1000000;
list.Add(dk);
}
// 通过 id 快速索引
var map = new DiKuai[total + 1]; // 1-based
foreach (var d in list) map[d.id] = d;
// 序号 -> (行, 列),行列从 0 开始
Func<int, (int r, int c)> toRC = id => ((id - 1) / cols, (id - 1) % cols);
// (行, 列) -> 序号
Func<int, int, int> toId = (r, c) => r * cols + c + 1;
var rand = new System.Random();
// 随机抽取陆地类型
// 权重大致:草原/森林/湿地 最大,山脉第二,沙漠/雪地最少
Func<int> randLandType = () =>
{
// 权重表:索引 0-5 对应 草原/森林/湿地/山脉/沙漠/雪地
// 权重和 = 100,可直接当作百分比
int[] weights = { 35, 35, 10, 10, 5, 5 };
int totalWeight = 0;
for (int i = 0; i < weights.Length; i++) totalWeight += weights[i]; // = 100
int r = rand.Next(totalWeight);
int acc = 0;
for (int i = 0; i < weights.Length; i++)
{
acc += weights[i];
if (r < acc) return i; // 返回 0-5,正好对应 DiKuaiType
}
return 0; // 兜底(草原)
};
// 把某个格子设为陆地,并完善所有字段
Action<int> setLand = id =>
{
var dk = map[id];
int landType = randLandType();
DiKuaiType type = (DiKuaiType)landType;
dk.type = type;
dk.pic = DiKuai.GetDiKuaiPicName(dk.type);
dk.name = DiKuai.GetDiKuaiName(dk.type);
dk.maxZhiWuXiShu = 1000000; // 陆地植被系数上限,可按需调整
dk.curZhiWuXiShu = 1000000; // 陆地初始植被系数,可按需调整
};
// 最中间的 4 个格子:25, 26, 35, 36 设为陆地
var landSet = new HashSet<int> { 25, 26, 35, 36 };
foreach (var id in landSet) setLand(id);
// 从已有陆地向外随机扩展,直到陆地数量达到 count
// 候选边界:与陆地相邻的海洋格子
var frontier = new HashSet<int>();
Action<int> addNeighbors = id =>
{
var (r, c) = toRC(id);
int[] dr = { -1, 1, 0, 0 };
int[] dc = { 0, 0, -1, 1 };
for (int k = 0; k < 4; k++)
{
int nr = r + dr[k], nc = c + dc[k];
if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
int nid = toId(nr, nc);
if (map[nid].type == DiKuaiType.HaiYang && !frontier.Contains(nid))
frontier.Add(nid);
}
};
foreach (var id in landSet) addNeighbors(id);
// 记录陆地扩展的范围,用于平衡方向(避免偏向某一侧)
// 用于统计左右上下扩展的格子数
int extendLeft = 0, extendRight = 0, extendUp = 0, extendDown = 0;
// 中心点(用于判断扩展方向)
const int centerCol = (cols - 1) / 2; // 4
const int centerRow = (rows - 1) / 2; // 2
while (landSet.Count < count && frontier.Count > 0)
{
// 按照方向偏差加权的随机挑选:往扩展较少的方向加权更大
// 计算候选格子的方向权重
var candidates = frontier.ToList();
// 计算左右上下的不平衡度
int diffLR = extendRight - extendLeft; // >0 表示偏右
int diffUD = extendDown - extendUp; // >0 表示偏下
// 给每个候选计算权重(越大越容易被选中)
var weights = new int[candidates.Count];
int totalW = 0;
for (int i = 0; i < candidates.Count; i++)
{
int cid = candidates[i];
var (r, c) = toRC(cid);
int w = 10; // 基础权重
// 如果向左扩展偏少,则左侧格子权重大
if (c < centerCol) w += Math.Max(0, diffLR) * 3;
// 如果向右扩展偏少,则右侧格子权重大
if (c > centerCol) w += Math.Max(0, -diffLR) * 3;
// 如果向上扩展偏少,则上方格子权重大
if (r < centerRow) w += Math.Max(0, diffUD) * 3;
// 如果向下扩展偏少,则下方格子权重大
if (r > centerRow) w += Math.Max(0, -diffUD) * 3;
weights[i] = w;
totalW += w;
}
// 加权随机挑选
int rnd = rand.Next(totalW);
int acc2 = 0;
int pickedIndex = 0;
for (int i = 0; i < candidates.Count; i++)
{
acc2 += weights[i];
if (rnd < acc2) { pickedIndex = i; break; }
}
int picked = candidates[pickedIndex];
frontier.Remove(picked);
// 统计方向扩展
var (pr, pc) = toRC(picked);
if (pc < centerCol) extendLeft++;
else if (pc > centerCol) extendRight++;
if (pr < centerRow) extendUp++;
else if (pr > centerRow) extendDown++;
setLand(picked);
landSet.Add(picked);
addNeighbors(picked);
}
return list;
}










