如何实现网格的全方位环绕效果?(C语言代码问题求助)
问题分析
你的核心问题出在checkAffShips函数的碰撞检测逻辑上——当前代码只处理了风暴区域完全在网格内部的情况,没有考虑风暴超出网格边界后环绕到另一侧的场景。比如20×20网格中,风暴从x=18、宽度5时,应该覆盖18、19、0、1、2这些坐标,但现有范围判断current->x >= x && current->x < x + w无法识别跨边界的区域。
另外代码里还有两个基础bug必须先修正:
shipMovement里的条件判断用了赋值运算符=而非比较运算符==,会导致所有舰船强制往'U'方向移动main函数处理命令'3'时,重新定义了局部变量w和h,覆盖了全局的网格宽高参数
解决方案
1. 先修复基础bug
void shipMovement(int time, int grid_w, int grid_h) { Ship *current = head; while (current != NULL) { // 把赋值运算符=替换为比较运算符== if (current->direction == 'U') { current->y = (current->y + time) % grid_h; } else if (current->direction == 'D') { current->y = (current->y - time + grid_h) % grid_h; } else if (current->direction == 'L') { current->x = (current->x - time + grid_w) % grid_w; } else if (current->direction == 'R') { current->x = (current->x + time) % grid_w; } else { printf("Invalid Direction!\n"); } current = current->next; } } // main函数中命令'3'的修改部分 else if (userInput == '3') { int x, y, storm_w, storm_h; // 改用storm前缀命名,避免覆盖全局网格宽高 scanf("%d %d %d %d", &x, &y, &storm_w, &storm_h); char *affShips[1000]; int numAffShips = 0; // 传入全局的网格宽高参数 checkAffShips(x, y, storm_w, storm_h, w, h, affShips, &numAffShips); printf("%d\n", numAffShips); for (int i = 0; i < numAffShips; i++) { printf("%s\n", affShips[i]); free(affShips[i]); } }
2. 实现风暴环绕的碰撞检测
修改checkAffShips函数,先将所有坐标转换为网格内的有效范围,再分情况判断舰船是否处于跨边界的风暴区域:
void checkAffShips(int storm_x, int storm_y, int storm_w, int storm_h, int grid_w, int grid_h, char **affShips, int *numAffShips) { Ship *current = head; // 将风暴起始坐标转换为网格内的有效非负坐标 storm_x = (storm_x % grid_w + grid_w) % grid_w; storm_y = (storm_y % grid_h + grid_h) % grid_h; // 计算风暴原始结束位置(不考虑环绕) int storm_x_end = storm_x + storm_w; int storm_y_end = storm_y + storm_h; while (current != NULL) { // 确保舰船坐标在网格有效范围内 int ship_x = (current->x % grid_w + grid_w) % grid_w; int ship_y = (current->y % grid_h + grid_h) % grid_h; // 判断x方向是否在风暴区域 int x_in = 0; if (storm_x_end <= grid_w) { // 风暴x方向未跨边界,常规范围判断 x_in = (ship_x >= storm_x && ship_x < storm_x_end); } else { // 风暴x方向跨边界,覆盖[storm_x, grid_w) 和 [0, 剩余长度) x_in = (ship_x >= storm_x || ship_x < (storm_x_end - grid_w)); } // 判断y方向是否在风暴区域 int y_in = 0; if (storm_y_end <= grid_h) { // 风暴y方向未跨边界,常规范围判断 y_in = (ship_y >= storm_y && ship_y < storm_y_end); } else { // 风暴y方向跨边界,同理处理 y_in = (ship_y >= storm_y || ship_y < (storm_y_end - grid_h)); } // 若x和y都在风暴区域内,记录该舰船 if (x_in && y_in) { affShips[*numAffShips] = (char *)malloc(sizeof(char) * 21); strcpy(affShips[(*numAffShips)++], current->shipName); } current = current->next; } }
逻辑说明
- 坐标归一化:通过
(val % grid_size + grid_size) % grid_size将所有坐标转换为网格内的非负有效值,避免负数或超出范围的问题 - 跨边界判断:当风暴结束位置超过网格尺寸时,说明区域环绕到网格另一侧,此时舰船坐标只要落在「起始点到网格末尾」或「网格开头到剩余长度」的任一区间内,就算处于风暴中
内容的提问来源于stack exchange,提问作者Jordan Uhrmann
相关产品推荐
相关产品推荐

