C语言新手求助:存储游戏玩家移动数组的最优实现方案
针对你的C语言玩家移动集合实现需求的解答
首先,咱们先明确核心需求:你需要一个Games结构,每个元素是玩家的移动整数数组。先帮你梳理下不同数据结构的适配性,再给你数组版本的完整实现代码。
一、数据结构选择:哪种最适合你的需求?
1. 数组(推荐用于便捷检索)
数组的最大优势是随机访问——你可以直接通过索引(比如第3个玩家的移动记录)瞬间定位到目标元素,检索复杂度是O(1),完全符合你要"便捷检索"的需求。唯一的小缺点是如果需要在中间插入/删除元素,需要移动后续数据,但如果你的场景是按顺序追加玩家记录,这个问题几乎可以忽略。
2. 栈
栈是后进先出(LIFO)结构,适合只需要访问最近添加的玩家移动记录的场景,但检索任意元素确实麻烦,必须从栈顶开始逐个遍历,复杂度O(n),不太适合需要频繁检索的需求。
3. 队列
队列是先进先出(FIFO)结构,适合按添加顺序处理玩家记录,但同样,检索任意元素也需要从头遍历,复杂度O(n),检索便捷性不如数组。
所以综合你的需求(存储集合+便捷检索),数组(二维数组或数组的数组)是最佳选择。
二、数组版本的完整实现代码
你之前的代码是一维数组的插入,现在需要改成二维数组(因为每个元素本身是数组)。下面是适配需求的完整代码,我会给你标注关键细节:
#include <stdio.h> #include <string.h> // 宏定义:根据你的实际需求调整大小 #define MAX_GAMES 10 // 最多存储10个玩家的移动记录 #define MAX_MOVES 20 // 每个玩家最多20次移动 #define UNUSED_MOVE -1 // 标记未使用的移动位置 // 定义Games结构:二维数组,每个元素是一个玩家的移动数组 int Games[MAX_GAMES][MAX_MOVES]; // 初始化整个Games结构:把所有移动位置标记为UNUSED_MOVE void initGames() { for (int game_idx = 0; game_idx < MAX_GAMES; game_idx++) { // 用memset快速初始化,也可以用循环逐个赋值 memset(Games[game_idx], UNUSED_MOVE, sizeof(Games[game_idx])); } } // 插入一个玩家的移动记录到Games中 // 参数:game_pos - 要插入的玩家位置(从0开始索引),moves - 玩家的移动数组,move_count - 移动次数 int insertGame(int game_pos, int *moves, int move_count) { // 先检查位置是否合法 if (game_pos < 0 || game_pos >= MAX_GAMES) { printf("Error: 玩家位置超出范围!\n"); return -1; } // 检查移动次数是否超过上限 if (move_count > MAX_MOVES) { printf("Error: 移动次数超过最大值!\n"); return -1; } // 把移动数组复制到Games的对应位置 memcpy(Games[game_pos], moves, move_count * sizeof(int)); // 把剩余位置标记为UNUSED_MOVE(如果move_count < MAX_MOVES) for (int i = move_count; i < MAX_MOVES; i++) { Games[game_pos][i] = UNUSED_MOVE; } return 0; } // 检索指定玩家的移动记录 void retrieveGame(int game_pos) { if (game_pos < 0 || game_pos >= MAX_GAMES) { printf("Error: 玩家位置超出范围!\n"); return; } printf("第%d个玩家的移动记录:", game_pos); for (int i = 0; i < MAX_MOVES; i++) { if (Games[game_pos][i] == UNUSED_MOVE) { break; // 遇到未使用的位置就停止 } printf("%d ", Games[game_pos][i]); } printf("\n"); } // 示例:根据移动值查找所有包含该值的玩家 void searchByMove(int target_move) { printf("包含移动值%d的玩家:", target_move); for (int game_idx = 0; game_idx < MAX_GAMES; game_idx++) { for (int move_idx = 0; move_idx < MAX_MOVES; move_idx++) { if (Games[game_idx][move_idx] == target_move) { printf("%d ", game_idx); break; // 找到一个就停止检查该玩家的其他移动 } if (Games[game_idx][move_idx] == UNUSED_MOVE) { break; } } } printf("\n"); } // 测试代码 int main() { // 初始化Games initGames(); // 准备两个玩家的移动数组 int player1_moves[] = {12, 13, 14}; int player2_moves[] = {5, 8, 10, 15}; // 插入到Games中 insertGame(0, player1_moves, 3); insertGame(1, player2_moves, 4); // 检索玩家0的记录 retrieveGame(0); // 检索玩家1的记录 retrieveGame(1); // 查找包含移动值14的玩家 searchByMove(14); return 0; }
代码关键细节说明:
- 二维数组定义:
int Games[MAX_GAMES][MAX_MOVES]直接实现了"数组的数组",每个Games[game_idx]就是一个玩家的移动数组。 - 初始化:用
memset快速初始化,或者循环赋值,标记未使用的位置为UNUSED_MOVE,方便后续判断移动记录的结束。 - 插入函数:用
memcpy批量复制移动数组,比循环赋值更高效;同时处理了边界检查,避免越界。 - 检索函数:支持直接通过玩家索引获取记录,也提供了根据移动值查找玩家的示例。
三、针对你现有代码的小纠正
你之前的insert函数有个小问题:循环结束后idx的值是pos-1,所以array[idx] = num实际上是把元素插到了pos-1的位置(如果你的pos是从1开始计数的话)。如果要让pos对应数组的索引(从0开始),应该调整循环条件:
void insert(int *array, int pos, int num) { if (pos < 0 || pos >= MAX) { printf("Error: 位置超出范围!\n"); return; } // 从最后一个元素开始往后移,直到pos位置 for (int idx = MAX - 1; idx > pos; idx--) { array[idx] = array[idx - 1]; } array[pos] = num; }
如果pos是从1开始的(比如用户输入的第1个位置),那需要把pos转换成pos-1再处理。
内容的提问来源于stack exchange,提问作者Valeri Vladimirov
相关产品推荐
相关产品推荐

