PAYATHON 2026

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 复制颜色的条件下,每种颜色会保持连通。修正随机范围后,四个方向和全部单元格都可以被选中,但这不保证八个区域面积相等。

备注:内容仅供参考。