C# 随机区域生长算法为何无法向左扩展?
数据小陈
原因是 Random.Next 的上界不包含在结果中
代码中的两处随机范围都少取了一个值,修正这两行即可:
int cell = rand.Next(1, size * size + 1);
// 后面的 switch 使用这个范围
switch (rand.Next(1, 5))
Random.Next(minValue, maxValue) 返回的整数满足:
minValue <= 返回值 < maxValue
原来的 rand.Next(1, 4) 只会返回 1、2、3,不会返回 4。因此,代表向左扩展的 case 4 从未执行。
为什么左右边界的异常每次都会出现
按照当前方向编号,算法实际能选择的方向只有上、右、下:
- 最右列的数字向右没有可用位置,又无法选择向左的分支,因此只能沿最右列上下扩展。
- 其他列的数字需要向左扩展才能进入最左列,但向左扩展不会发生,所以无法进入最左列。
- 向上和向下的分支都能被选中,因此上下方向看起来正常。
向左扩展的概率始终为 0,增加随机运行次数也不会改变这一点。
单元格抽样也有同样的边界问题
当 size == 8 时:
rand.Next(1, size * size)
只会返回 1~63。你的 CellToCoords 使用从 1 开始的单元格编号,编号 64 对应 (8, 8),所以右下角永远不会被选为扩展起点。
右下角仍可能被相邻单元格填色,但填色后不会主动向外扩展。这一处也需要修正:
int cell = rand.Next(1, size * size + 1);
对于 1~64 的输入,现有 CellToCoords 的转换逻辑与使用范围一致,无需为这次问题修改它。
如果希望省去字符串拼接和拆分,可以将坐标选择部分替换为:
int cell = rand.Next(0, size * size);
int row = cell / size + 1;
int col = cell % size + 1;
这里使用从 0 开始的编号,范围为 0~63,同样能覆盖所有 64 个实际使用的单元格。两种编号方式任选一种,保持范围与转换公式配套即可。
修正后还需要注意什么
每次调用 ExpandColors() 不一定都会填入一个单元格。如果选到未着色的起点、越界方向或已经着色的邻居,本次调用就不会有进展。因此,不能把调用次数当作填色次数,也不应假设会在固定次数内填满。
仍需保留现有边界检查:外围下标 0 和 9 不属于目标区域,不能因为数组中存在这些位置,就允许它们参与扩展。
在初始数字各出现一次、只向上下左右相邻的 0 复制颜色的条件下,每种颜色会保持连通。修正随机范围后,四个方向和全部单元格都可以被选中,但这不保证八个区域面积相等。
备注:内容仅供参考。
