如何实现生成8个唯一随机坐标的C语言函数?
解决8x8网格中生成8个唯一随机坐标的问题
你的问题核心是确保生成的坐标完全不重复,原来的代码用rand()加上或减去偏移量取模的方式,本质上还是无法避免随机数碰撞,所以得换一种思路。下面给你两种可靠的实现方案,都能保证坐标唯一性:
方案一:预生成所有坐标 + Fisher-Yates洗牌(推荐)
这种方法最稳妥,尤其适合需要从全集中选取多个不重复元素的场景。思路是先把8x8网格里所有64个坐标都列出来,然后用Fisher-Yates算法打乱顺序,最后取前8个即可——绝对不会有重复。
代码实现
首先注意:srand(time(NULL))只需要在程序启动时调用一次,不要放在setCoordinations函数里,否则短时间内多次调用函数会因为time(NULL)返回相同秒数,导致生成完全一样的随机序列。
#include <stdio.h> #include <stdlib.h> #include <time.h> struct location { int x; int y; }; // Fisher-Yates洗牌算法,打乱坐标数组 void shuffle(struct location all_coords[], int total) { for (int i = total - 1; i > 0; i--) { int j = rand() % (i + 1); // 交换两个坐标 struct location temp = all_coords[i]; all_coords[i] = all_coords[j]; all_coords[j] = temp; } } void setCoordinations(struct location loc[]) { // 第一步:生成8x8网格里的所有坐标 struct location all_coords[64]; int index = 0; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { all_coords[index].x = x; all_coords[index].y = y; index++; } } // 第二步:打乱所有坐标 shuffle(all_coords, 64); // 第三步:取前8个唯一坐标赋值给loc数组 for (int i = 0; i < 8; i++) { loc[i] = all_coords[i]; } } // 测试用例 int main() { srand(time(NULL)); // 程序启动时只调用一次 struct location loc[8]; setCoordinations(loc); // 打印生成的坐标 for (int i = 0; i < 8; i++) { printf("坐标%d: (%d, %d)\n", i+1, loc[i].x, loc[i].y); } return 0; }
方案二:生成坐标后检查去重
如果不想预生成所有坐标,也可以每次生成一个随机坐标,然后和已经生成的坐标对比,重复就重新生成。这种方法适合需要的坐标数量远小于总数量的场景(这里8个其实也能用)。
代码实现
#include <stdio.h> #include <stdlib.h> #include <time.h> struct location { int x; int y; }; // 检查坐标是否已存在于loc数组中(前count个元素) int isDuplicate(struct location loc[], int count, struct location new_loc) { for (int i = 0; i < count; i++) { if (loc[i].x == new_loc.x && loc[i].y == new_loc.y) { return 1; // 重复返回1 } } return 0; // 不重复返回0 } void setCoordinations(struct location loc[]) { int count = 0; while (count < 8) { struct location new_loc; new_loc.x = rand() % 8; new_loc.y = rand() % 8; // 如果不重复,就加入数组 if (!isDuplicate(loc, count, new_loc)) { loc[count] = new_loc; count++; } } } // 测试用例 int main() { srand(time(NULL)); struct location loc[8]; setCoordinations(loc); for (int i = 0; i < 8; i++) { printf("坐标%d: (%d, %d)\n", i+1, loc[i].x, loc[i].y); } return 0; }
注意事项
- 一定要把
srand(time(NULL))放在程序入口(比如main函数开头),而不是setCoordinations函数内,否则短时间多次调用会生成重复的随机序列。 - 方案一的效率更高,因为Fisher-Yates洗牌是O(n)时间复杂度,而方案二在最坏情况下可能需要多次重复生成坐标(不过对于8个坐标来说几乎可以忽略)。
内容的提问来源于stack exchange,提问作者Dandan
相关产品推荐
相关产品推荐

