-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsnake.c
More file actions
202 lines (186 loc) · 4.83 KB
/
snake.c
File metadata and controls
202 lines (186 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
descript:snake game use cursor
author:claude-4.5-haiku
use:10min
*/
// ==== 修正版:减少闪烁,for循环变量提前,速度300ms,蛇为*,果实为$,修复bug,高亮所有修改 ====
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#define WIDTH 40
#define HEIGHT 20
#define MAX_TAIL 200
enum Direction { STOP = 0, LEFT, RIGHT, UP, DOWN };
int x, y, fruitX, fruitY, score;
int tailX[MAX_TAIL], tailY[MAX_TAIL];
int nTail;
enum Direction dir;
int gameOver = 0;
// ==== 高亮: 使用缓冲区绘图减少闪烁 ====
char screen[HEIGHT + 2][WIDTH + 3]; // 屏幕缓冲行,每行多两用于边界
void generateFruit() {
int valid = 0;
int i;
while (!valid) {
fruitX = rand() % WIDTH;
fruitY = rand() % HEIGHT;
valid = 1;
if (fruitX == x && fruitY == y) {
valid = 0;
continue;
}
for (i = 0; i < nTail; i++) {
if (tailX[i] == fruitX && tailY[i] == fruitY) {
valid = 0;
break;
}
}
}
}
void setup() {
dir = RIGHT; // ==== 高亮: 修正,初始使蛇自动向右移动 ====
x = WIDTH / 2;
y = HEIGHT / 2;
srand((unsigned int)time(NULL));
generateFruit();
score = 0;
nTail = 0;
gameOver = 0;
}
void draw() {
int i, j, k;
// ==== 高亮: 使用缓冲区代替system("cls"),减少闪烁 ====
for (i = 0; i < HEIGHT + 2; i++) {
for (j = 0; j < WIDTH + 2; j++) {
screen[i][j] = ' ';
}
screen[i][WIDTH + 2 - 1] = 0; // 结尾
}
for (j = 0; j < WIDTH + 2; j++) {
screen[0][j] = '#';
screen[HEIGHT + 1][j] = '#';
}
for (i = 1; i <= HEIGHT; i++) {
screen[i][0] = '#';
screen[i][WIDTH + 1] = '#';
}
// ==== 高亮: 使用$显示果实 ====
screen[fruitY + 1][fruitX + 1] = '$';
// ==== 高亮: 用*显示蛇头 ====
screen[y + 1][x + 1] = '*';
// ==== 高亮: 用*显示蛇身 ====
for (k = 0; k < nTail; k++) {
screen[tailY[k] + 1][tailX[k] + 1] = '*';
}
// ==== 高亮: 直接设置光标到左上,减少闪烁 ====
COORD coord = { 0, 0 };
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, coord);
for (i = 0; i < HEIGHT + 2; i++) {
printf("%s\n", screen[i]);
}
printf("分数: %d\n", score);
}
void input() {
// ==== 高亮: 修复鼠标点击或方向键导致卡死问题,过滤特殊键 ====
if (_kbhit()) {
int ch = _getch();
if (ch == 224 || ch == 0) {
_getch(); // 忽略扩展码
return;
}
switch (ch) {
case 'a':
case 'A':
if (dir != RIGHT) dir = LEFT;
break;
case 'd':
case 'D':
if (dir != LEFT) dir = RIGHT;
break;
case 'w':
case 'W':
if (dir != DOWN) dir = UP;
break;
case 's':
case 'S':
if (dir != UP) dir = DOWN;
break;
case 'x':
case 'X':
gameOver = 1;
break;
}
}
}
void logic() {
int i;
// for (int i = nTail - 1; i > 0; i--) {
for (i = nTail - 1; i > 0; i--) { // ==== 高亮: 变量提前,支持旧标准 ====
tailX[i] = tailX[i - 1];
tailY[i] = tailY[i - 1];
}
if (nTail > 0) {
tailX[0] = x;
tailY[0] = y;
}
switch (dir) {
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) {
printf("游戏结束! 最终得分: %d\n", score);
gameOver = 1;
return;
}
for (i = 0; i < nTail; i++) {
if (tailX[i] == x && tailY[i] == y) {
printf("游戏结束! 最终得分: %d\n", score);
gameOver = 1;
return;
}
}
if (x == fruitX && y == fruitY) {
score += 10;
if (nTail < MAX_TAIL) nTail++;
generateFruit();
}
}
int main() {
int stepMillis = 300; // ==== 高亮: 速度300ms ====
// ==== 高亮: 隐藏光标 ====
CONSOLE_CURSOR_INFO cursorInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleCursorInfo(hOut, &cursorInfo);
cursorInfo.bVisible = FALSE;
SetConsoleCursorInfo(hOut, &cursorInfo);
setup();
COORD coord = { 0, 0 };
SetConsoleCursorPosition(hOut, coord);
while (!gameOver) {
draw();
input();
logic();
Sleep(stepMillis);
}
// ==== 高亮: 恢复光标可见 ====
cursorInfo.bVisible = TRUE;
SetConsoleCursorInfo(hOut, &cursorInfo);
printf("按任意键退出...\n");
_getch();
return 0;
}