- 地图:一个二维数组表示的地图,包含玩家、宝藏、陷阱和空地。
- 玩家:可以在地图上移动(上下左右)。
- 目标:找到宝藏,同时避开陷阱。
- 交互:通过键盘输入控制玩家移动。
- 状态:显示当前步数、游戏状态(进行中/胜利/失败)。
游戏设计
地图元素
我们可以用不同的字符来表示地图上的不同元素:

(图片来源网络,侵删)
P: 玩家T: 宝藏X: 陷阱- 空地
- 边界(可选,用于限制玩家移动范围)
游戏逻辑
- 初始化地图,随机放置玩家、宝藏和陷阱。
- 显示初始地图和游戏信息(如步数)。
- 进入一个循环,等待玩家输入方向键(W, A, S, D 或方向键)。
- 根据输入更新玩家位置。
- 检查玩家新位置的内容:
- 如果是 ,则正常移动,步数+1。
- 如果是
T,则玩家获胜,游戏结束。 - 如果是
X,则玩家失败,游戏结束。
- 更新地图显示和游戏信息,然后继续循环。
C 语言代码实现
下面是一个完整的、可运行的 C 语言代码,你可以直接复制到你的 C 编译器(如 GCC, Clang, MSVC)中运行。
#include <stdio.h>
#include <stdlib.h> // 用于 rand() 和 srand()
#include <time.h> // 用于 time()
#include <conio.h> // 用于 _kbhit() 和 _getch() (Windows平台)
// #include <unistd.h> // 用于 usleep() (Linux/macOS平台)
// #include <termios.h> // 用于设置终端为无缓冲模式 (Linux/macOS平台)
// 定义地图大小
#define MAP_WIDTH 10
#define MAP_HEIGHT 8
// 定义地图元素
#define PLAYER 'P'
#define TREASURE 'T'
#define TRAP 'X'
#define EMPTY '.'
#define BOUNDARY '#'
// 函数声明
void initializeMap(char map[MAP_HEIGHT][MAP_WIDTH], int *playerX, int *playerY);
void printMap(char map[MAP_HEIGHT][MAP_WIDTH], int steps);
void clearScreen();
int main() {
// 初始化随机数种子,确保每次运行地图都不同
srand((unsigned int)time(NULL));
char map[MAP_HEIGHT][MAP_WIDTH];
int playerX, playerY;
int steps = 0;
char input;
// 初始化游戏
initializeMap(map, &playerX, &playerY);
clearScreen();
// 游戏主循环
while (1) {
printMap(map, steps);
// 检查是否按下了键
if (_kbhit()) {
input = _getch(); // 获取按键,不显示在控制台
// 计算新位置
int newX = playerX;
int newY = playerY;
switch (input) {
case 'w': // 上
case 'W':
case 72: // 上箭头
newY--;
break;
case 's': // 下
case 'S':
case 80: // 下箭头
newY++;
break;
case 'a': // 左
case 'A':
case 75: // 左箭头
newX--;
break;
case 'd': // 右
case 'D':
case 77: // 右箭头
newX++;
break;
case 'q': // 退出游戏
case 'Q':
printf("\n游戏已退出,感谢游玩!\n");
return 0;
default:
continue; // 按了其他键,忽略
}
// 检查新位置是否有效(不能是边界)
if (map[newY][newX] != BOUNDARY) {
// 清除旧位置的玩家标记
map[playerY][playerX] = EMPTY;
// 检查新位置的内容
if (map[newY][newX] == TREASURE) {
printf("\n恭喜!你找到了宝藏!\n");
printf("你总共用了 %d 步,\n", steps + 1);
return 0; // 游戏胜利,退出
} else if (map[newY][newX] == TRAP) {
printf("\n哎呀!你踩到了陷阱!游戏结束,\n");
printf("你总共用了 %d 步,\n", steps + 1);
return 0; // 游戏失败,退出
}
// 更新玩家位置
playerX = newX;
playerY = newY;
map[playerY][playerX] = PLAYER;
steps++;
}
}
// 短暂暂停,避免CPU占用过高
// Windows: Sleep(100);
// Linux/macOS: usleep(100000);
}
return 0;
}
/**
* @brief 初始化地图,放置玩家、宝藏和陷阱
* @param map 二维数组地图
* @param playerX 玩家的X坐标(输出参数)
* @param playerY 玩家的Y坐标(输出参数)
*/
void initializeMap(char map[MAP_HEIGHT][MAP_WIDTH], int *playerX, int *playerY) {
// 1. 填充地图为空地
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
map[y][x] = EMPTY;
}
}
// 2. 设置边界
for (int x = 0; x < MAP_WIDTH; x++) {
map[0][x] = BOUNDARY;
map[MAP_HEIGHT - 1][x] = BOUNDARY;
}
for (int y = 0; y < MAP_HEIGHT; y++) {
map[y][0] = BOUNDARY;
map[y][MAP_WIDTH - 1] = BOUNDARY;
}
// 3. 随机放置玩家
*playerX = rand() % (MAP_WIDTH - 2) + 1;
*playerY = rand() % (MAP_HEIGHT - 2) + 1;
map[*playerY][*playerX] = PLAYER;
// 4. 随机放置宝藏 (确保不与玩家重叠)
int treasureX, treasureY;
do {
treasureX = rand() % (MAP_WIDTH - 2) + 1;
treasureY = rand() % (MAP_HEIGHT - 2) + 1;
} while (treasureX == *playerX && treasureY == *playerY);
map[treasureY][treasureX] = TREASURE;
// 5. 随机放置陷阱 (确保不与玩家和宝藏重叠)
int numTraps = 5; // 陷阱数量
for (int i = 0; i < numTraps; i++) {
int trapX, trapY;
do {
trapX = rand() % (MAP_WIDTH - 2) + 1;
trapY = rand() % (MAP_HEIGHT - 2) + 1;
} while (map[trapY][trapX] != EMPTY); // 只能放在空地上
map[trapY][trapX] = TRAP;
}
}
/**
* @brief 打印当前地图和游戏信息
* @param map 二维数组地图
* @param steps 当前步数
*/
void printMap(char map[MAP_HEIGHT][MAP_WIDTH], int steps) {
clearScreen();
printf("===== 寻宝游戏 =====\n");
printf("使用 W/A/S/D 或方向键移动,Q 退出,\n");
printf("P=玩家, T=宝藏, X=陷阱, #=边界\n");
printf("当前步数: %d\n\n", steps);
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
printf("%c ", map[y][x]);
}
printf("\n");
}
}
/**
* @brief 清空控制台屏幕
*/
void clearScreen() {
// Windows系统
system("cls");
// Linux/macOS系统
// system("clear");
}
如何编译和运行
- 保存代码:将上面的代码保存为一个文件,
treasure_hunt.c。 - 编译:
- 如果你使用的是 GCC (在 Linux, macOS 或 Windows 的 MinGW/Cygwin 中),打开终端或命令提示符,输入:
gcc treasure_hunt.c -o treasure_hunt
- 如果你使用的是 Visual Studio,创建一个新的 C++ 控制台项目,并将代码粘贴到
.c文件中,然后生成并运行。
- 如果你使用的是 GCC (在 Linux, macOS 或 Windows 的 MinGW/Cygwin 中),打开终端或命令提示符,输入:
- 运行:
- 在终端或命令提示符中,输入:
./treasure_hunt
- 在 Visual Studio 中,直接按
F5或点击“开始调试”按钮。
- 在终端或命令提示符中,输入:
代码解释
#include:引入标准库和特定平台的库。stdio.h:用于输入输出,如printf。stdlib.h:用于rand(生成随机数)和srand(设置随机种子)。time.h:用于time函数,为srand提供一个变化的种子。conio.h:这是 Windows 平台特有的头文件,提供了_kbhit()(检查是否有按键)和_getch()(获取一个按键)这两个非常有用的函数,可以实现“无回显”的键盘输入,让游戏体验更好。
#define:定义常量,方便修改地图大小和元素符号。main()函数:游戏的主入口。srand((unsigned int)time(NULL));:初始化随机数生成器。time(NULL)返回当前时间的秒数,作为种子,确保每次运行程序时地图布局都不同。initializeMap():调用函数来设置游戏初始状态。while(1):一个无限循环,代表游戏持续进行,直到玩家获胜、失败或主动退出。_kbhit()和_getch():这是游戏交互的核心。_kbhit()检查用户是否按下了键盘上的任意键,如果按下了,_getch()就会读取这个键的值,并且不会把字符显示在屏幕上。switch(input):根据玩家按下的键,更新玩家将要移动到的newX和newY坐标。- 边界检查:
if (map[newY][newX] != BOUNDARY)确保玩家不能穿过墙壁。 - 移动逻辑:
map[playerY][playerX] = EMPTY;:将玩家原来的位置变为空地。if (map[newY][newX] == TREASURE):判断新位置是否是宝藏。if (map[newY][newX] == TRAP):判断新位置是否是陷阱。- 如果是普通空地,则更新玩家坐标
playerX,playerY,并在新位置画上玩家map[playerY][playerX] = PLAYER。
initializeMap()函数:- 首先用
EMPTY填满整个地图。 - 然后用
BOUNDARY画出地图的边框。 - 使用
rand()随机生成玩家、宝藏和陷阱的坐标,注意,放置宝藏和陷阱时,使用do-while循环确保它们不会出现在同一个位置,也不会和玩家重叠。
- 首先用
printMap()函数:- 首先调用
clearScreen()清空屏幕,使每次显示的地图都是“刷新”过的,不会留下上一次的痕迹。 - 然后打印游戏标题、操作说明和当前步数。
- 通过两层嵌套的
for循环,将二维地图数组的内容逐行逐个字符地打印出来。
- 首先调用
clearScreen()函数:- 使用
system("cls")命令来清空 Windows 控制台,如果你在 Linux 或 macOS 上,需要使用system("clear")。
- 使用
跨平台兼容性说明
上面的代码使用了 conio.h,这在 Windows 上是完美工作的,如果你想在 Linux 或 macOS 上运行,你需要做以下修改:
- 注释掉
#include <conio.h>。 - 替换输入检测部分:Linux/macOS 没有原生的
_kbhit()和_getch(),你需要自己实现类似的功能,通常需要设置终端为“无缓冲”模式。
一个跨平台的替代方案是使用 ncurses 库,这是一个功能强大的终端屏幕处理库,可以非常方便地处理键盘输入和屏幕绘制,但使用 ncurses 需要额外安装库,并且代码会稍微复杂一些。
对于这个简单的示例,直接使用 scanf 或 getchar 会因为需要按回车而体验不佳,如果你主要在 Windows 上开发,当前代码是最好的选择,如果你希望代码能在所有平台上流畅运行,学习 ncurses 是一个很好的方向。

(图片来源网络,侵删)

(图片来源网络,侵删)
