#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #define ROW 22 // 游戏区行数 #define COL 42 // 游戏区列数 #define KONG 0 // 标记空 #define WALL 1 // 标记墙 #define FOOD 2 // 标记普通食物 #define HEAD 3 // 标记蛇头 #define BODY 4 // 标记蛇身 #define OBSTACLE 5 // 标记障碍物 #define SPECIAL_FOOD 6 // 标记特殊食物 #define UP 72 // 方向键:上 #define DOWN 80 // 方向键:下 #define LEFT 75 // 方向键:左 #define RIGHT 77 // 方向键:右 #define SPACE 32 // 暂停 #define ESC 27 // 退出 #define ENTER 13 // 回车键 // 蛇头 struct Snake { int len; // 记录蛇身长度 int x; // 蛇头横坐标 int y; // 蛇头纵坐标 } snake; // 蛇身 struct Body { int x; // 蛇身横坐标 int y; // 蛇身纵坐标 } body[ROW * COL]; // 开辟足以存储蛇身的结构体数组 int face[ROW][COL]; // 标记游戏区各个位置的状态 // 隐藏光标 void HideCursor(); // 光标跳转 void CursorJump(int x, int y); // 初始化界面 void InitInterface(); // 颜色设置 void color(int c); // 从文件读取最高分 void ReadGrade(); // 更新最高分到文件 void WriteGrade(); // 初始化蛇 void InitSnake(); // 随机生成食物 void RandFood(); // 随机生成障碍物 void RandObstacles(int count); // 判断得分与结束 int JudgeFunc(int x, int y); // 修改:返回游戏状态 // 打印蛇与覆盖蛇 void DrawSnake(int flag); // 移动蛇 void MoveSnake(int x, int y); // 执行按键 void run(int x, int y); // 游戏主体逻辑函数 void Game(); // 显示开始菜单 void ShowMenu(); // 显示游戏结束界面 void ShowGameOver(); // 显示帮助信息 void ShowHelp(); // 改变游戏速度 void ChangeSpeed(int delta); // 添加特殊食物 void AddSpecialFood(); // 移除特殊食物 void RemoveSpecialFood(); // 绘制游戏边框 void DrawBorder(); // 更新分数显示 void UpdateScoreDisplay(); // 移动障碍物 void MoveObstacles(); // 保存游戏 void SaveGame(); // 加载游戏 void LoadGame(); int max, grade; // 全局变量 int game_speed = 300; // 游戏速度(毫秒)- 修改:降低初始速度 int obstacles_mode = 0; // 障碍物模式:0-无,1-固定障碍物,2-移动障碍物 int obstacles_count = 0; // 当前障碍物数量 int special_food_active = 0; // 特殊食物是否激活 int special_food_x, special_food_y; // 特殊食物位置 int game_paused = 0; // 游戏是否暂停 int game_started = 0; // 游戏是否开始 int pass_wall = 0; // 是否开启穿墙模式 time_t start_time; // 游戏开始时间 int last_move_time; // 上一次移动障碍物的时间 int special_food_timer = 0; // 特殊食物计时器 int main() { max = 0, grade = 0; // 初始化变量 system("title 贪吃蛇完美版"); // 设置cmd窗口的名字 system("mode con cols=84 lines=23"); // 设置cmd窗口的大小 HideCursor(); // 隐藏光标 ReadGrade(); // 从文件读取最高分到max变量 while (1) { ShowMenu(); // 显示开始菜单 InitInterface(); // 初始化界面 InitSnake(); // 初始化蛇 srand((unsigned int)time(NULL)); // 设置随机数生成起点 RandFood(); // 随机生成食物 if (obstacles_mode == 1 || obstacles_mode == 2) { RandObstacles(10); // 生成10个障碍物 } DrawSnake(1); // 打印蛇 Game(); // 开始游戏 // 游戏结束后询问是否返回主菜单 char ch; CursorJump(COL, ROW / 2 + 6); printf("返回主菜单?(y/n):"); ch = _getch(); if (ch == 'n' || ch == 'N') { break; } // 重置游戏状态 game_speed = 300; // 重置为初始速度 obstacles_mode = 0; obstacles_count = 0; special_food_active = 0; game_paused = 0; game_started = 0; pass_wall = 0; grade = 0; special_food_timer = 0; system("cls"); } return 0; } // 隐藏光标 void HideCursor() { CONSOLE_CURSOR_INFO curInfo; curInfo.dwSize = 1; curInfo.bVisible = FALSE; HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorInfo(handle, &curInfo); } // 光标跳转 void CursorJump(int x, int y) { COORD pos; pos.X = x; pos.Y = y; HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(handle, pos); } // 绘制游戏边框 void DrawBorder() { color(6); // 土黄色边框 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (j == 0 || j == COL - 1) { face[i][j] = WALL; CursorJump(2 * j, i); printf("■"); } else if (i == 0 || i == ROW - 1) { face[i][j] = WALL; CursorJump(2 * j, i); printf("■"); } else { face[i][j] = KONG; } } } } // 初始化界面 void InitInterface() { // 清空游戏区域 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { face[i][j] = KONG; } } // 绘制边框 DrawBorder(); // 绘制分数和状态信息 color(7); // 白色 CursorJump(0, ROW); printf("当前得分: %d", grade); CursorJump(COL, ROW); printf("最高得分: %d", max); CursorJump(COL * 2 - 10, ROW); printf("速度: %d", 4000 / game_speed); // 显示控制提示 CursorJump(0, ROW + 1); printf("控制: ←→↑↓ 移动 | SPACE 暂停 | ESC 退出 | S 保存 | L 加载"); } // 更新分数显示 void UpdateScoreDisplay() { color(7); CursorJump(10, ROW); printf("%d", grade); CursorJump(COL + 10, ROW); printf("%d", max); CursorJump(COL * 2 - 4, ROW); printf("%d", 4000 / game_speed); } // 颜色设置 void color(int c) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); } // 从文件读取最高分 void ReadGrade() { FILE* pf = fopen("snake_max_score.dat", "rb"); if (pf == NULL) { pf = fopen("snake_max_score.dat", "wb"); if (pf) { fwrite(&max, sizeof(int), 1, pf); fclose(pf); pf = fopen("snake_max_score.dat", "rb"); } } if (pf) { fread(&max, sizeof(int), 1, pf); fclose(pf); } } // 更新最高分到文件 void WriteGrade() { FILE* pf = fopen("snake_max_score.dat", "wb"); if (pf) { fwrite(&max, sizeof(int), 1, pf); fclose(pf); } } // 初始化蛇 void InitSnake() { snake.len = 2; snake.x = COL / 2; snake.y = ROW / 2; body[0].x = COL / 2 - 1; body[0].y = ROW / 2; body[1].x = COL / 2 - 2; body[1].y = ROW / 2; face[snake.y][snake.x] = HEAD; face[body[0].y][body[0].x] = BODY; face[body[1].y][body[1].x] = BODY; } // 随机生成食物 void RandFood() { int i, j, attempts = 0; do { i = rand() % (ROW - 2) + 1; j = rand() % (COL - 2) + 1; attempts++; if (attempts > 100) return; // 防止死循环 } while (face[i][j] != KONG); face[i][j] = FOOD; color(12); // 红色 CursorJump(2 * j, i); printf("●"); } // 随机生成障碍物 void RandObstacles(int count) { for (int c = 0; c < count; c++) { int i, j, attempts = 0; do { i = rand() % (ROW - 2) + 1; j = rand() % (COL - 2) + 1; attempts++; if (attempts > 100) return; } while (face[i][j] != KONG); face[i][j] = OBSTACLE; color(8); // 灰色 CursorJump(2 * j, i); printf("■"); obstacles_count++; } } // 移动障碍物 void MoveObstacles() { static int move_count = 0; move_count++; // 每10次移动一次障碍物 if (obstacles_mode == 2 && move_count % 10 == 0) { // 创建临时障碍物数组 int temp_obs[ROW * COL][2]; int count = 0; // 收集所有障碍物位置 for (int i = 1; i < ROW - 1; i++) { for (int j = 1; j < COL - 1; j++) { if (face[i][j] == OBSTACLE) { temp_obs[count][0] = i; temp_obs[count][1] = j; count++; } } } // 移动每个障碍物 for (int idx = 0; idx < count; idx++) { int i = temp_obs[idx][0]; int j = temp_obs[idx][1]; // 随机选择移动方向 int dir = rand() % 4; int ni = i, nj = j; switch (dir) { case 0: ni--; break; // 上 case 1: ni++; break; // 下 case 2: nj--; break; // 左 case 3: nj++; break; // 右 } // 检查目标位置是否有效 if (ni > 0 && ni < ROW - 1 && nj > 0 && nj < COL - 1 && face[ni][nj] == KONG) { // 清除原位置 face[i][j] = KONG; CursorJump(2 * j, i); printf(" "); // 设置新位置 face[ni][nj] = OBSTACLE; color(8); CursorJump(2 * nj, ni); printf("■"); } } } } // 添加特殊食物 void AddSpecialFood() { if (special_food_active) return; int i, j, attempts = 0; do { i = rand() % (ROW - 2) + 1; j = rand() % (COL - 2) + 1; attempts++; if (attempts > 100) return; } while (face[i][j] != KONG); face[i][j] = SPECIAL_FOOD; special_food_x = j; special_food_y = i; special_food_active = 1; special_food_timer = 0; color(14); // 黄色 CursorJump(2 * j, i); printf("★"); } // 移除特殊食物 void RemoveSpecialFood() { if (!special_food_active) return; face[special_food_y][special_food_x] = KONG; special_food_active = 0; CursorJump(2 * special_food_x, special_food_y); printf(" "); } // 判断得分与结束 (修改:返回游戏状态) int JudgeFunc(int x, int y) { int new_x = snake.x + x; int new_y = snake.y + y; // 穿墙模式处理 if (pass_wall) { if (new_x == 0) new_x = COL - 2; else if (new_x == COL - 1) new_x = 1; if (new_y == 0) new_y = ROW - 2; else if (new_y == ROW - 1) new_y = 1; } // 检查边界 if (new_x <= 0 || new_x >= COL - 1 || new_y <= 0 || new_y >= ROW - 1) { if (!pass_wall) // 非穿墙模式撞墙结束游戏 { return 1; // 游戏结束 } } // 检查新位置 switch (face[new_y][new_x]) { case FOOD: snake.len++; grade += 10; UpdateScoreDisplay(); RandFood(); // 每100分增加一个特殊食物 if (grade % 100 == 0 && !special_food_active) { AddSpecialFood(); } return 0; // 继续游戏 case SPECIAL_FOOD: grade += 50; UpdateScoreDisplay(); RemoveSpecialFood(); // 增加游戏速度 if (game_speed > 500) { ChangeSpeed(-200); } return 0; // 继续游戏 case OBSTACLE: case BODY: return 1; // 游戏结束 default: return 0; // 继续游戏 } } // 打印蛇与覆盖蛇 void DrawSnake(int flag) { if (flag == 1) // 打印蛇 { color(10); // 绿色蛇头 CursorJump(2 * snake.x, snake.y); printf("■"); for (int i = 0; i < snake.len; i++) { // 蛇身颜色渐变 color(2 + (i % 6)); CursorJump(2 * body[i].x, body[i].y); printf("□"); } } else // 覆盖蛇 { if (body[snake.len - 1].x != 0) { CursorJump(2 * body[snake.len - 1].x, body[snake.len - 1].y); printf(" "); } } } // 移动蛇 void MoveSnake(int x, int y) { DrawSnake(0); face[body[snake.len - 1].y][body[snake.len - 1].x] = KONG; face[snake.y][snake.x] = BODY; // 更新蛇身位置 for (int i = snake.len - 1; i > 0; i--) { body[i].x = body[i - 1].x; body[i].y = body[i - 1].y; } body[0].x = snake.x; body[0].y = snake.y; // 更新蛇头位置 snake.x += x; snake.y += y; // 穿墙处理 if (pass_wall) { if (snake.x == 0) snake.x = COL - 2; else if (snake.x == COL - 1) snake.x = 1; if (snake.y == 0) snake.y = ROW - 2; else if (snake.y == ROW - 1) snake.y = 1; } // 标记新的蛇头位置 face[snake.y][snake.x] = HEAD; DrawSnake(1); } // 改变游戏速度 void ChangeSpeed(int delta) { game_speed += delta; if (game_speed < 100) game_speed = 100; // 设置最小速度 if (game_speed > 1000) game_speed = 1000; // 设置最大速度 UpdateScoreDisplay(); } // 保存游戏 void SaveGame() { FILE* pf = fopen("snake_save.dat", "wb"); if (pf == NULL) return; // 保存游戏状态 fwrite(&grade, sizeof(int), 1, pf); fwrite(&snake, sizeof(struct Snake), 1, pf); fwrite(body, sizeof(struct Body), snake.len, pf); fwrite(face, sizeof(int), ROW * COL, pf); fwrite(&obstacles_mode, sizeof(int), 1, pf); fwrite(&pass_wall, sizeof(int), 1, pf); fwrite(&game_speed, sizeof(int), 1, pf); fwrite(&special_food_active, sizeof(int), 1, pf); if (special_food_active) { fwrite(&special_food_x, sizeof(int), 1, pf); fwrite(&special_food_y, sizeof(int), 1, pf); } fclose(pf); // 提示保存成功 CursorJump(COL, ROW + 2); color(10); printf("游戏已保存!"); Sleep(1000); CursorJump(COL, ROW + 2); printf(" "); } // 加载游戏 void LoadGame() { FILE* pf = fopen("snake_save.dat", "rb"); if (pf == NULL) return; // 清除当前游戏状态 system("cls"); InitInterface(); // 加载游戏状态 fread(&grade, sizeof(int), 1, pf); fread(&snake, sizeof(struct Snake), 1, pf); fread(body, sizeof(struct Body), snake.len, pf); fread(face, sizeof(int), ROW * COL, pf); fread(&obstacles_mode, sizeof(int), 1, pf); fread(&pass_wall, sizeof(int), 1, pf); fread(&game_speed, sizeof(int), 1, pf); fread(&special_food_active, sizeof(int), 1, pf); if (special_food_active) { fread(&special_food_x, sizeof(int), 1, pf); fread(&special_food_y, sizeof(int), 1, pf); } fclose(pf); // 重新绘制游戏界面 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { switch (face[i][j]) { case WALL: color(6); CursorJump(2 * j, i); printf("■"); break; case FOOD: color(12); CursorJump(2 * j, i); printf("●"); break; case OBSTACLE: color(8); CursorJump(2 * j, i); printf("■"); break; case SPECIAL_FOOD: color(14); CursorJump(2 * j, i); printf("★"); break; default: break; } } } DrawSnake(1); UpdateScoreDisplay(); // 提示加载成功 CursorJump(COL, ROW + 2); color(10); printf("游戏已加载!"); Sleep(1000); CursorJump(COL, ROW + 2); printf(" "); } // 显示帮助信息 void ShowHelp() { system("cls"); color(11); // 浅蓝色 CursorJump(COL / 2 - 10, 2); printf("========== 贪吃蛇游戏帮助 =========="); color(10); // 绿色 CursorJump(COL / 4, 4); printf("控制方式:"); CursorJump(COL / 4, 5); printf("方向键: 控制蛇的移动方向"); CursorJump(COL / 4, 6); printf("空格键: 暂停/继续游戏"); CursorJump(COL / 4, 7); printf("ESC键: 退出游戏"); CursorJump(COL / 4, 8); printf("S键: 保存游戏"); CursorJump(COL / 4, 9); printf("L键: 加载游戏"); CursorJump(COL / 4, 11); printf("游戏规则:"); CursorJump(COL / 4, 12); printf("1. 吃到红色食物 ● 得10分,蛇身变长"); CursorJump(COL / 4, 13); printf("2. 吃到黄色食物 ★ 得50分,增加速度"); CursorJump(COL / 4, 14); printf("3. 撞到墙壁、障碍物或自身游戏结束"); CursorJump(COL / 4, 16); printf("特殊功能:"); CursorJump(COL / 4, 17); printf("穿墙模式: 可以穿过墙壁"); CursorJump(COL / 4, 18); printf("障碍物模式: 无、固定障碍物、移动障碍物"); color(14); // 黄色 CursorJump(COL / 2 - 10, ROW - 2); printf("按任意键返回主菜单..."); _getch(); // 添加等待按键 } // 显示游戏结束界面 void ShowGameOver() { system("cls"); color(12); // 红色 CursorJump(COL / 2 - 10, ROW / 2 - 3); // 计算游戏时间 time_t end_time = time(NULL); int game_time = (int)difftime(end_time, start_time); int minutes = game_time / 60; int seconds = game_time % 60; // 显示得分信息 if (grade > max) { printf("恭喜打破记录!新纪录: %d", grade); max = grade; WriteGrade(); } else if (grade == max) { printf("平最高记录!得分: %d", grade); } else { printf("当前得分: %d (最高: %d)", grade, max); } // 显示游戏信息 CursorJump(COL / 2 - 10, ROW / 2); printf("游戏时间: %02d:%02d", minutes, seconds); CursorJump(COL / 2 - 10, ROW / 2 + 2); printf("G A M E O V E R"); // 显示选项 color(14); // 黄色 CursorJump(COL / 2 - 10, ROW / 2 + 4); printf("按任意键返回主菜单..."); _getch(); // 添加等待按键 } // 游戏主体逻辑函数 void Game() { // 游戏主循环 int key = 0; int dx = 1, dy = 0; // 初始向右移动 int last_dx = dx, last_dy = dy; // 记录上一次移动方向 int game_over = 0; // 游戏结束标志 DWORD last_move_time = GetTickCount(); // 记录上次移动时间 while (!game_over) { // 处理输入 if (_kbhit()) { key = _getch(); switch (key) { case UP: if (last_dy == 0) { dx = 0; dy = -1; } break; case DOWN: if (last_dy == 0) { dx = 0; dy = 1; } break; case LEFT: if (last_dx == 0) { dx = -1; dy = 0; } break; case RIGHT: if (last_dx == 0) { dx = 1; dy = 0; } break; case SPACE: game_paused = !game_paused; if (game_paused) { CursorJump(COL, ROW + 2); color(12); printf("游戏暂停中..."); } else { CursorJump(COL, ROW + 2); printf(" "); } break; case ESC: return; // 退出游戏 case 's': case 'S': SaveGame(); break; case 'l': case 'L': LoadGame(); break; } } if (game_paused) { Sleep(100); continue; } // 更新特殊食物计时器 if (special_food_active) { special_food_timer++; if (special_food_timer > 100) { RemoveSpecialFood(); } } // 移动障碍物 if (obstacles_mode == 2) { DWORD current_time = GetTickCount(); if (current_time - last_move_time > 500) { // 每500毫秒移动一次 MoveObstacles(); last_move_time = current_time; } } // 定时移动蛇 DWORD current_time = GetTickCount(); if (current_time - last_move_time > game_speed) { last_move_time = current_time; // 判断是否结束 if (JudgeFunc(dx, dy)) { game_over = 1; continue; } // 移动蛇 MoveSnake(dx, dy); // 保存当前移动方向 last_dx = dx; last_dy = dy; } // 小延迟,减少CPU占用 Sleep(10); } // 游戏结束处理 ShowGameOver(); } // 显示开始菜单 void ShowMenu() { system("cls"); color(11); CursorJump(COL / 2 - 5, ROW / 4); printf(" 小张版贪吃蛇"); color(10); CursorJump(COL / 2 - 5, ROW / 4 + 2); printf("1. 开始游戏"); CursorJump(COL / 2 - 5, ROW / 4 + 3); printf("2. 游戏设置"); CursorJump(COL / 2 - 5, ROW / 4 + 4); printf("3. 游戏帮助"); CursorJump(COL / 2 - 5, ROW / 4 + 5); printf("4. 退出游戏"); color(14); CursorJump(COL / 2 - 5, ROW / 4 + 7); printf("请选择: "); char choice = _getch(); switch (choice) { case '1': // 开始游戏 game_started = 1; start_time = time(NULL); break; case '2': // 游戏设置 { system("cls"); color(11); CursorJump(COL / 2 - 5, ROW / 4); printf("★ 游戏设置 ★"); int setting = 1; while (setting) { color(10); CursorJump(COL / 2 - 10, ROW / 4 + 2); printf("a. 游戏速度: %d", 4000 / game_speed); CursorJump(COL / 2 - 10, ROW / 4 + 3); printf("b. 障碍物模式: %s", obstacles_mode == 0 ? "无" : obstacles_mode == 1 ? "固定障碍物" : "移动障碍物"); CursorJump(COL / 2 - 10, ROW / 4 + 4); printf("c. 穿墙模式: %s", pass_wall ? "开启" : "关闭"); CursorJump(COL / 2 - 10, ROW / 4 + 5); printf("d. 返回主菜单"); color(14); CursorJump(COL / 2 - 10, ROW / 4 + 7); printf("请选择: "); char option = _getch(); switch (option) { case 'a': // 调整速度 system("cls"); color(11); CursorJump(COL / 2 - 5, ROW / 4); printf("★ 设置游戏速度 ★"); color(10); CursorJump(COL / 2 - 10, ROW / 4 + 2); printf("当前速度: %d", 4000 / game_speed); CursorJump(COL / 2 - 10, ROW / 4 + 3); printf("按 + 加速,按 - 减速"); CursorJump(COL / 2 - 10, ROW / 4 + 4); printf("按回车返回"); while (1) { char speedKey = _getch(); if (speedKey == '+') ChangeSpeed(-100); else if (speedKey == '-') ChangeSpeed(100); else if (speedKey == ENTER) break; CursorJump(COL / 2, ROW / 4 + 2); printf("%d ", 4000 / game_speed); } system("cls"); break; case 'b': // 障碍物模式 obstacles_mode = (obstacles_mode + 1) % 3; break; case 'c': // 穿墙模式 pass_wall = !pass_wall; break; case 'd': // 返回 setting = 0; break; } } system("cls"); ShowMenu(); break; } case '3': // 游戏帮助 ShowHelp(); system("cls"); ShowMenu(); break; case '4': // 退出游戏 exit(0); default: ShowMenu(); break; } }