当碰到墙壁后,游戏画面停止,按r可以跳转welcome界面,但不能正确显示打印的如gameover等文字,请修改代码
时间: 2024-10-18 08:20:24 浏览: 27
为了修复游戏中碰到墙壁后按 `R` 锅重启时无法正确显示 `Game Over` 文字的问题,需要确保在重新启动游戏之前完全清除并重新初始化所有相关资源和状态。以下是修改后的代码:
### 修改点:
1. **确保在重新启动游戏前清除所有图形资源**。
2. **确保在重新启动游戏前重置所有游戏状态**。
### 修改后的代码:
```c
#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#define Interval 20
#define Width 30
#define Height 30
#define Wall -1
#define Empty 0
#define Body 1
#define Head 2
#define Food 3
typedef struct {
int row;
int col;
} Snake;
int grid[600 / Interval][600 / Interval] = {0};
int speed = Interval;
int len = 3;
int dir = 3; // 默认向左
Snake snake[Width * Height];
bool food_exist = false;
Snake snake_food = {0};
enum Dir { UP, RIGHT, DOWN, LEFT };
enum Difficulty { EASY, MEDIUM, HARD };
int score = 0;
int vect[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
bool game_over = false;
int sleep_time = 0;
int difficulty = MEDIUM;
int mode;
void draw_Wall();
void init_game(int mode);
void init_snake();
void draw_food();
void draw_snake();
void prod_food();
void move(int dir);
void begin_game(int mode);
void KeyEvent();
void eat_food();
void judge_border();
void inc_len(int dir);
void judge_gameover();
void draw_end();
void draw_welcome();
int choose();
void init_grid();
int main() {
initgraph(Interval * Width, Interval * Height);
int selected_mode = choose();
if (selected_mode != -1) {
begin_game(selected_mode); // 根据选中的模式开始游戏
}
getch();
closegraph();
return 0;
}
void draw_welcome(int current_mode) {
PIMAGE img = newimage();
getimage(img, "Background.png");
putimage(0, 0, img);
setfillcolor(GREEN);
setfontbkcolor(WHITE);
setfont(20, 0, "楷体");
const char* str = "按下s以开始游戏";
outtextxy(Height / 2 * Interval - 90, Width / 2 * Interval + 120, str);
const char* easy_str = "按下e选择简单模式";
outtextxy(Height / 2 * Interval - 90, Width / 2 * Interval + 150, easy_str);
const char* medium_str = "按下m选择中等模式";
outtextxy(Height / 2 * Interval - 90, Width / 2 * Interval + 180, medium_str);
const char* hard_str = "按下h选择困难模式";
outtextxy(Height / 2 * Interval - 90, Width / 2 * Interval + 210, hard_str);
const char* mode_str;
switch (current_mode) {
case 1:
mode_str = "当前模式:简单";
break;
case 2:
mode_str = "当前模式:中等";
break;
case 3:
mode_str = "当前模式:困难";
break;
default:
mode_str = "当前模式:未选择";
break;
}
outtextxy(Height / 2 * Interval - 90, Width / 2 * Interval + 240, mode_str);
delimage(img);
}
int choose() {
key_msg msg;
int current_mode = 0; // 初始模式设为未选择
bool flag = true;
while (is_run() && flag) {
draw_welcome(current_mode);
delay_fps(60);
if (kbhit()) {
msg = getkey();
switch (msg.key) {
case 's':
case 'S':
if (current_mode != 0) {
flag = false;
return current_mode;
}
break;
case 'e':
case 'E':
current_mode = 1; // 简单模式
break;
case 'm':
case 'M':
current_mode = 2; // 中等模式
break;
case 'h':
case 'H':
current_mode = 3; // 困难模式
break;
}
}
}
return -1; // 返回-1表示没有有效选择
}
void begin_game(int mode) {
init_game(mode); // 初始化游戏时传入模式
while (is_run()) {
cleardevice();
draw_snake();
if (!food_exist) {
inc_len(dir);
prod_food();
}
move(dir);
judge_gameover();
if (game_over) {
draw_end();
break;
}
eat_food();
KeyEvent();
Sleep(speed); // 使用速度变量来控制延迟时间
}
}
void inc_len(int dir) {
int x = vect[dir][0];
int y = vect[dir][1];
snake[len].row = snake[len - 1].row + y;
snake[len].col = snake[len - 1].col + x;
len++;
grid[snake[len - 1].row][snake[len - 1].col] = Body;
}
void judge_border() {
if (snake[0].row < 0 || snake[0].row >= Height || snake[0].col < 0 || snake[0].col >= Width) {
game_over = true;
}
}
void init_game(int mode) {
for (int i = 0; i < Width; i++) {
grid[i][0] = Wall;
grid[0][i] = Wall;
grid[i][Height - 1] = Wall;
grid[Width - 1][i] = Wall;
}
game_over = false;
food_exist = false;
ege_enable_aa(true);
setbkcolor(EGERGB(116, 206, 222));
setcolor(GREEN);
switch (mode) {
case 1: // 简单模式
speed = 120;
break;
case 2: // 中等模式
speed = 80;
break;
case 3: // 困难模式
speed = 50;
break;
}
init_snake();
prod_food();
len = 3;
init_grid();
score = 0;
dir = LEFT; // 重置方向为默认值(向左)
}
void draw_Wall() {
PIMAGE img = newimage();
getimage(img, "Wall.png");
for (int i = 0; i < Width; i++) {
putimage(0, Interval * i, img);
putimage(Interval * i, 0, img);
putimage(Interval * i, (Height - 1) * Interval, img);
putimage((Width - 1) * Interval, Interval * i, img);
}
for (int i = 0; i < Width; i++) {
line(i * Interval, 0, i * Interval, (Width) * Interval);
line(0, i * Interval, (Width) * Interval, i * Interval);
}
delimage(img);
}
void init_snake() {
len = 3;
grid[Height / 2][Width / 2] = Head;
grid[Height / 2][Width / 2 + 1] = Body;
grid[Height / 2 + 1][Width / 2 + 1] = Body;
snake[0].row = Height / 2;
snake[0].col = Width / 2;
snake[1].row = Height / 2;
snake[1].col = Width / 2 + 1;
snake[2].row = Height / 2 + 1;
snake[2].col = Width / 2 + 1;
}
void draw_snake() {
draw_Wall();
for (int i = 0; i < len; i++) {
PIMAGE img = newimage();
if (i == 0) {
switch (dir) {
case UP:
getimage(img, "Headup.png");
break;
case DOWN:
getimage(img, "Headdown.png");
break;
case LEFT:
getimage(img, "Headleft.png");
break;
case RIGHT:
getimage(img, "Headright.png");
break;
}
} else {
getimage(img, "Snake.png");
}
putimage(snake[i].col * Interval, snake[i].row * Interval, img);
delimage(img);
}
if (food_exist) {
draw_food();
}
}
void draw_food() {
PIMAGE img = newimage();
getimage(img, "Food.png");
putimage(snake_food.col * Interval, snake_food.row * Interval, img);
delimage(img);
}
void prod_food() {
randomize();
int row, col;
do {
col = rand() % (Width - 2) + 1; // 避开两侧墙
row = rand() % (Height - 2) + 1; // 避开顶部与底部墙
} while (grid[row][col] != Empty);
snake_food.row = row;
snake_food.col = col;
food_exist = true;
}
void move(int dir) {
int x = vect[dir][0];
int y = vect[dir][1];
grid[snake[len - 1].row][snake[len - 1].col] = Empty;
for (int i = len - 1; i > 0; i--) {
snake[i] = snake[i - 1];
}
snake[0].row += y;
snake[0].col += x;
grid[snake[0].row][snake[0].col] = Head;
for (int i = 1; i < len; i++) {
grid[snake[i].row][snake[i].col] = Body;
}
judge_gameover();
}
void judge_gameover() {
if (snake[0].row < 0 || snake[0].row >= Height || snake[0].col < 0 || snake[0].col >= Width || grid[snake[0].row][snake[0].col] == Body) {
game_over = true;
}
}
void draw_end() {
cleardevice();
setbkcolor(EGERGB(116, 222, 222));
char str[4][30] = {{"Game Over"}, {"Score:"}, {NULL}, {"Press R to restart"}};
sprintf(str[1], "Score: %d", score);
setfont(40, 0, "楷体");
for (int i = 0; i < 4; i++) {
outtextxy(Height / 2 * Interval - 70, Width / 2 * Interval + 50 * i, str[i]);
}
key_msg msg;
bool flag = true;
while (flag) {
if (kbhit()) {
msg = getkey();
if (msg.key == 'r' || msg.key == 'R') {
flag = false;
game_over = false; // 游戏不再处于结束状态
closegraph(); // 关闭当前图形窗口
initgraph(Interval * Width, Interval * Height); // 重新打开图形窗口
int selected_mode = choose(); // 等待用户选择是否开始游戏
if (selected_mode != -1) {
init_game(selected_mode); // 重新初始化游戏
begin_game(selected_mode); // 如果用户选择开始游戏,则开始游戏
}
} else if (msg.key == key_esc && msg.msg == key_msg_down) {
flag = false;
}
}
}
}
void init_grid() {
for (int i = 0; i < Width; i++) {
for (int j = 0; j < Height; j++) {
grid[i][j] = 0;
}
}
}
void eat_food() {
if (snake[0].row == snake_food.row && snake[0].col == snake_food.col) {
score += 1;
food_exist = false;
}
}
void KeyEvent() {
key_msg msg;
while (kbhit()) {
msg = getkey();
int key = msg.key;
switch (key) {
case 'w':
case 'W':
if (dir != DOWN) dir = UP;
break;
case 'd':
case 'D':
if (dir != LEFT) dir = RIGHT;
break;
case 's':
case 'S':
if (dir != UP) dir = DOWN;
break;
case 'a':
case 'A':
if (dir != RIGHT) dir = LEFT;
break;
}
}
}
```
### 解释:
1. **`draw_end()` 函数**:在检测到用户按 `R` 重启游戏时,先关闭当前图形窗口 (`closegraph()`),然后重新打开一个新的图形窗口 (`initgraph()`),再调用 `choose()` 函数等待用户选择新的游戏模式,并重新初始化游戏状态。
2. **`init_game()` 函数**:确保每次重新开始游戏时,所有游戏状态都被正确重置,包括网格、蛇的位置、食物的存在状态等。
这样修改后,当你在游戏中碰壁并按 `R` 重启时,应该能够正确显示 `Game Over` 和其他相关信息。
阅读全文