2D游戏中复制地图指针用于洪水填充时的段错误排查问询
2D游戏路径验证问题的修复方案
核心错误定位
段错误的直接原因是两个关键问题:
map_copy内存分配不足:valid_path中ft_calloc(1, sizeof(map->map))仅分配了单个指针的内存,但需要容纳map->h行字符串指针,应该按地图高度分配数组空间。copy_map逻辑完全倒置:函数原本应该从原地图origin复制到目标copy,但代码里循环条件依赖未初始化的copy,且赋值方向反了,导致复制完全没执行。
分步修复代码
1. 修正copy_map函数
void copy_map(char **origin, char **copy, int height) { int i; i = 0; // 按地图高度逐行复制,避免依赖NULL终止符 while (i < height) { copy[i] = ft_strdup(origin[i]); i++; } copy[i] = NULL; }
2. 修复valid_path的内存分配与逻辑
int valid_path(t_map *map) { int y; int x; int i; // 分配足够容纳所有行指针的内存 map->map_copy = ft_calloc(map->h + 1, sizeof(char *)); if (!map->map_copy) closeprogram("Memory allocation failed\n"); y = map->playery; x = map->playerx; // 传入地图高度确保完整复制 copy_map(map->map, map->map_copy, map->h); // 重置计数,避免多次调用时累计错误 map->copy_ccount = 0; map->copy_ecount = 0; flood_fill(map, 'P', y, x); if (map->ccount != map->copy_ccount) closeprogram("Map cannot be solved: unreachable collectibles\n"); if (map->ecount != map->copy_ecount) closeprogram("Map cannot be solved: unreachable exit\n"); // 释放复制的地图,避免内存泄漏 i = 0; while (map->map_copy[i]) { free(map->map_copy[i]); i++; } free(map->map_copy); return (1); }
3. 给flood_fill添加边界检查
当前函数没有判断坐标是否超出地图范围,会导致越界访问,必须加上边界判断:
static void flood_fill(t_map *map, int paint, int y, int x) { // 坐标合法性检查:不能超出地图边界 if (y < 0 || y >= map->h || x < 0 || x >= map->w) return; // 遇到墙体直接返回 if (map->map_copy[y][x] == '1') return; if (map->map_copy[y][x] == 'C') { map->copy_ccount++; map->map_copy[y][x] = '0'; } else if (map->map_copy[y][x] == 'E') { map->copy_ecount++; map->map_copy[y][x] = '0'; } if (map->map_copy[y][x] == '0') { map->map_copy[y][x] = paint; flood_fill(map, paint, y, x + 1); flood_fill(map, paint, y, x - 1); flood_fill(map, paint, y + 1, x); flood_fill(map, paint, y - 1, x); } }
4. 修复read_map的宽度计算逻辑
原代码的宽度计算会导致无限循环,修正如下:
t_map *read_map(char *argv ) { t_map *new; int y; new = (t_map *) ft_calloc(1, sizeof(t_map)); new->fd = open(argv, O_RDONLY); new->h = 0; new->w = 0; y = 0; if (new->fd < 0) { ft_putstr("Map file does not exist\n"); exit (1); } while (get_next_line(new->fd)) new->h += 1; close (new->fd); new->map = (char **) ft_calloc(new->h + 1, sizeof(char *)); new->fd = open(argv, O_RDONLY); while (y < new->h) { new->map[y] = get_next_line(new->fd); y++; } // 正确计算地图宽度(假设所有行长度一致) while (new->map[0][new->w] != '\0') new->w++; close(new->fd); return (new); }
关于你的疑问
不需要重新打开地图文件复制内容。原地图已经加载到map->map中,直接复制这个二维数组是最高效的方式,重新读文件只会增加IO开销,还可能引入新的错误。
内容的提问来源于stack exchange,提问作者jmarks
相关产品推荐
相关产品推荐

