C++结合SDL2开发生命游戏时相邻存活细胞计数问题求助
现有代码存在的核心问题
- 边界检查逻辑完全错误:你当前判断
it+1 != board.back()完全无法识别行末尾的情况,比如当前细胞是某一行最后一个元素,it+1是下一行第一个元素,本来就不属于邻居,你的判断逻辑识别不了这个场景,同理行首元素it-1会取到上一行最后一个元素,也不是合法邻居。 - 访问顺序错误:所有判断都是先访问迭代器指向的
isAlive()方法,再做边界校验,一旦迭代器越界,直接触发非法访问崩溃,边界校验必须放在成员访问之前。 - 邻居数量不全:8个相邻细胞你只判断了6个,缺少左上、左下两个斜向的邻居判断。
- 状态更新逻辑时序错误:你边计算邻居边调用
survive()修改细胞存活状态,会导致同一轮次后面遍历的细胞计算邻居时,用到已经更新后的状态,不符合生命游戏「所有细胞同步更新」的规则,而且算完直接resetNeighbors()也会导致其他细胞计算邻居时拿不到正确值。
修复方案
推荐先把迭代器转成数组索引,用坐标判断边界比直接操作迭代器更直观不易错,示例代码如下:
// 先计算所有细胞的邻居数,不要提前更新状态 size_t idx = std::distance(board.begin(), it); int x = idx % numOfCols; int y = idx / numOfCols; int totalRows = board.size() / numOfCols; // 8个方向的坐标偏移 const int dirs[8][2] = {{-1,-1}, {0,-1}, {1,-1}, {-1,0}, {1,0}, {-1,1}, {0,1}, {1,1}}; int aliveCount = 0; for(int i=0; i<8; i++){ int nx = x + dirs[i][0]; int ny = y + dirs[i][1]; // 先判断坐标是否在合法范围内 if(nx >=0 && nx < numOfCols && ny >=0 && ny < totalRows){ size_t nIdx = ny * numOfCols + nx; if(board[nIdx]->isAlive()){ aliveCount++; } } } it->setAliveNeighbors(aliveCount); // 所有细胞的邻居数都计算完成后,再统一遍历调用survive()更新状态,最后再统一resetNeighbors()
额外优化建议:如果不需要频繁增删细胞,直接用vector<Cell>存储对象比存指针更高效,缓存友好性更好,也能避免指针管理的额外开销。
内容的提问来源于stack exchange,提问作者Asmir Zukić
相关产品推荐
相关产品推荐

