Compare commits

...

No commits in common. 'main' and 'fc0b6f0e86886a2b80a4ca00a25a175aa89f65cf' have entirely different histories.

@ -1,2 +0,0 @@
# 123

992
test.c

@ -0,0 +1,992 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <math.h>
#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;
}
}

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save