Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions GluttonousSnake/snake_std_fluent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#pragma warning(disable : 4996)
#define W 28
#define H W
#define S (W * H)

void set_cursor(int x, int y) {
COORD pos = { (short)x, (short)y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

void print_at(int r, int c, const char *ch) {
set_cursor(c * 2, r);
printf("%s", ch);
}

int main() {
char o[S * 2 + W + 3], *c = o;
int m[S + 1], q[S], l = 0, r = 4, d = 1, p, a, i;
for (i = l; i <= r; ++i) q[i] = S;
for (i = 0; i < S; c += 2, ++i % W || (*c++ = '\n')) {
m[i] = !(i / W % (H - 1) && i % W % (W - 1));
m[i] ? (*c = '[', c[1] = ']') : (*c = c[1] = ' ');
}
p = W / 2 * (H + 1) - d, a = p + d, o[S * 2 + W + 2] = '\0';
system("cls");
printf("%s", o);
print_at(a / W, a % W, "00");
for (srand((unsigned)time(0)); i = 1; _sleep(100)) {
if (_kbhit() && (i = _getch() & 95)) {
if (i == 'A' && d != 1) d = -1;
else if (i == 'D' && d != -1) d = 1;
else if (i == 'W' && d != W) d = -W;
else if (i == 'S' && d != -W) d = W;
}
int t = p;
p += d;
if (m[p] && p != q[l + 1] || i == 27) {
printf("Game over!\n");
_sleep(1000);
break;
}
if (p == a) {
for (a = rand() % S; m[a]; a = (a + 1) % S) {}
print_at(a / W, a % W, "00");
*(c = o + a * 2 + a / W) = '0', c[1] = '0';
} else {
m[i = q[l = (l + 1) % S]] = 0;
print_at(i / W, i % W, " ");
*(c = o + i * 2 + i / W) = ' ', c[1] = ' ';
}
m[q[r] = p] = 1, r = (r + 1) % S;
print_at(p / W, p % W, "()");
*(c = o + p * 2 + p / W) = '(', c[1] = ')';
}
}
38 changes: 38 additions & 0 deletions GluttonousSnake/snake_std_with_cmt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <conio.h> // 引入conio.h库,用于控制台输入输出(如键盘检测和清屏)
#include <stdio.h>
#include <stdlib.h> // 引入stdlib.h库,用于随机数生成和系统命令(如rand、system)
#include <time.h>
#pragma warning(disable : 4996) // 禁用4996号警告,允许使用如_getch等被认为已弃用的函数
#define W 30 // 定义游戏网格宽度为28
#define H W // 定义游戏网格高度等于宽度(28)
#define S (W * H) // 定义网格总格子数(28 * 28 = 784)
int main() {
char o[S * 2 + W + 1], *c = o; // 定义显示缓冲区o(每个格子占2字符,W中行每行加换行符,再加终止符),c为指向缓冲区的指针
int m[S + 1], q[S], l = 0, r = 4, d = 1, p, a, i; // m:一维数组(其实用二维数组更方便)标识地图格子状态(0=空,1=蛇身/墙),q:蛇身数组(预留蛇覆盖整个地图的空间),l:蛇尾尾索引,r:蛇头索引,d:方向(1=右),p:蛇头位置,a:苹果位置,i:循环变量
for (i = l; i <= r; ++i) q[i] = S; // 初始化蛇身队列前5个元素为无效位置S(900),表示初始蛇长5
for (i = 0; i < S; c += 2, ++i % W || (*c++ = '\n')) { // 循环遍历900个格子,初始化显示缓冲区和地图
m[i] = !(i / W % (H - 1) && i % W % (W - 1)); // 设置地图数组状态m:边界(首行、末行、首列、末列)为1(墙),内部为0(空);具体逻辑:i / W 计算行号,i % W 计算列号。i / W % (H - 1) 检查是否为首行(0)或末行(29):行号除以29取余,若为0(行0或29),则为边界。i % W % (W - 1) 检查是否为首列(0)或末列(29):列号除以29取余,若为0,则为边界。
m[i] ? (*c = '[', c[1] = ']') : (*c = c[1] = ' '); // 根据m[i]设置显示字符:墙为"[]",空为" "
}
p = W / 2 * (H + 1) - d, a = p + d, c[-1] = '\0'; // 设置蛇头位置p(第15行,第14列,接近中心),苹果位置a,缓冲区以空字符终止
for (srand((unsigned)time(0)); i = 1; _sleep(100)) { // 使用当前时间初始化随机种子,进入帧率为10的主循环(每次循环画一次图即一帧(帧率也体现为速度)),这里开始i用于读入键盘输入(节约行数写在for里面)
if (_kbhit() && (i = _getch() & 95)) { // 检查键盘输入,获取输入字符并转为大写(A=65,D=68,W=87,S=83)
if (i == 'A' && d != 1) d = -1; // 按A且当前方向非右(禁止180度掉头),设置方向为左(-1)
else if (i == 'D' && d != -1) d = 1; // 按D且当前方向非左,设置方向为右(1)
else if (i == 'W' && d != W) d = -W; // 按W且当前方向非下,设置方向为上(-W)
else if (i == 'S' && d != -W) d = W; // 按S且当前方向非上,设置方向为下(W)
}
if (m[p += d] && p != q[l + 1] || i == 27) break; // 移动蛇头(p += d,这样是为了减少行数写在里面),若撞墙或蛇身(m[p]=1且非苹果)或按ESC(27),退出循环
if (p == a) { // 若蛇头到达苹果位置
for (a = rand() % S; m[a]; a = (a + 1) % S) {} // 一直随机生成新苹果位置,知道确保在空闲格子(m[a]=0)生成
*(c = o + a * 2 + a / W) = '0', c[1] = '0'; // 在新苹果位置显示"00"
} else { // 若未吃到苹果
m[i = q[l = (l + 1) % S]] = 0; // 清除蛇尾位置(m[i]=0),更新队列尾索引l,因为这一帧结束时蛇尾一定不在当前位置了,而蛇身不动
*(c = o + i * 2 + i / W) = ' ', c[1] = ' '; // 在蛇尾位置显示空白" "
}
m[q[r] = p] = 1, r = (r + 1) % S; // 另外蛇头会更新位置,将新蛇头位置加入队列,标记地图m为1,更新队列头索引r
*(c = o + p * 2 + p / W) = '(', c[1] = ')'; // 在蛇头位置显示"()"
system("cls"), printf(o); // 清屏并打印整个游戏画面
}
printf("\nGame over!\n"); // 游戏结束,打印提示信息
}