C语言学习必须实战,并且学完语法后就必须立即用实战来巩固。一般需要10来个比较复杂的程序才能掌握C语言。今天就教大家第一个小程序,贪食蛇。
首先上代码
一、代码
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <unistd.h>
#include <time.h>#define WIDTH 20
#define HEIGHT 10int score = 0;
int gameover;
int x, y, fruitX, fruitY, flag;int tailX[100], tailY[100];
int nTail;void setup() {gameover = 0;// 初始化蛇的位置x = WIDTH / 2;y = HEIGHT / 2;// 初始化食物的位置fruitX = rand() % WIDTH;fruitY = rand() % HEIGHT;
}void draw() {clear(); // 清屏for (int i = 0; i < WIDTH + 2; i++)printw("#");printw("\n");for (int i = 0; i < HEIGHT; i++) {for (int j = 0; j < WIDTH; j++) {if (j == 0)printw("#"); // 左墙if (i == y && j == x)printw("O"); // 蛇头else if (i == fruitY && j == fruitX)printw("F"); // 食物else {int isTail = 0;for (int k = 0; k < nTail; k++) {if (tailX[k] == j && tailY[k] == i) {printw("o"); // 蛇身isTail = 1;}}if (!isTail)printw(" ");}if (j == WIDTH - 1)printw("#"); // 右墙}printw("\n");}for (int i = 0; i < WIDTH + 2; i++)printw("#");printw("\n");printw("Score:%d", score);refresh(); // 刷新屏幕
}void input() {int ch = getch(); // 获取键盘输入switch (ch) {case 'a':flag = 1;break;case 'd':flag = 2;break;case 'w':flag = 3;break;case 's':flag = 4;break;case 'x':gameover = 1;break;}
}void algorithm() {usleep(100000); // 休眠,控制蛇的速度int prevX = tailX[0];int prevY = tailY[0];int prev2X, prev2Y;tailX[0] = x;tailY[0] = y;for (int i = 1; i < nTail; i++) {prev2X = tailX[i];prev2Y = tailY[i];tailX[i] = prevX;tailY[i] = prevY;prevX = prev2X;prevY = prev2Y;}switch (flag) {case 1:x--;break;case 2:x++;break;case 3:y--;break;case 4:y++;break;default:break;}// 判断是否碰到墙if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT)gameover = 1;// 判断是否吃到食物if (x == fruitX && y == fruitY) {score += 10;fruitX = rand() % WIDTH;fruitY = rand() % HEIGHT;nTail++;}
}int main() {srand(time(NULL)); // 设置随机数种子initscr(); // 初始化 curseskeypad(stdscr, TRUE); // 启用键盘输入nodelay(stdscr, TRUE); // 非阻塞输入noecho(); // 关闭回显setup();while (!gameover) {draw();input();algorithm();}endwin(); // 关闭 cursesreturn 0;
}
二、编译
代码的运行平台是ubuntu,代码用到了curses库,需要提前安装:
sudo apt-get install libncurses5-dev
然后用下面命令编译
gcc snake_game.c -o snake_game -lncurses
执行程序:
./snake_game
注意!如果速度过快,就会结束,直接跳出程序到控制台,如何修改速度下面会讲到。
三、编程指导
-
初始化 (
setup
函数):gameover
: 游戏结束标志。x
和y
: 蛇头的初始坐标。fruitX
和fruitY
: 食物的初始坐标。flag
: 用于存储用户输入的方向。score
: 记录游戏得分。nTail
: 蛇身的长度。tailX
和tailY
: 用于存储蛇身各部分的坐标。
-
游戏主循环:
while (!gameover) {draw();input();algorithm(); }
游戏在一个无限循环中进行,直到
gameover
变为真。在每次循环中,先绘制游戏画面,然后处理用户输入,最后执行游戏逻辑。 -
输入处理 (
input
函数):- 使用
getch
函数获取键盘输入。 - 根据用户输入的键值设置
flag
的值,表示蛇移动的方向。 - 'a': 左,'d': 右,'w': 上,'s': 下,'x': 退出游戏。
- 使用
-
游戏逻辑 (
algorithm
函数):- 使用
usleep
函数添加一点延迟,以控制蛇的速度。(如果速度过快,游戏会很快结束,需要添加延时) - 更新蛇身的位置。
- 根据用户输入的方向移动蛇头。
- 判断是否碰到墙,如果是则游戏结束。
- 判断是否吃到食物,如果是则增加得分,重新生成食物,增加蛇身的长度。
- 使用
-
绘制 (
draw
函数):- 使用
clear
函数清空屏幕。 - 使用
printw
函数输出字符。 - 使用
refresh
函数刷新屏幕。 - 输出游戏画面,包括墙、蛇头、食物和蛇身。
- 输出得分信息。
- 使用
-
初始化和关闭 curses (
initscr
和endwin
函数):initscr
: 初始化 curses 库。keypad
: 启用键盘输入。nodelay
: 设置非阻塞输入。noecho
: 关闭回显。endwin
: 关闭 curses 库。
-
编译和运行:
- 使用
gcc
编译器编译程序,并链接ncurses
库。 - 运行生成的可执行文件。
- 使用
四、继续完善
这段贪食蛇游戏代码已经基本完成了一个简单的实现,但仍然有一些方面可以改进和完善,具体包括:
-
边界检查:
当蛇头移动到边界时,游戏会结束。可以考虑在边界处实现蛇穿越的效果,即从一侧穿越到另一侧。 -
游戏难度递增:
目前游戏的难度保持不变,可以考虑逐渐增加蛇的移动速度或者加快食物的生成速度,使得游戏更具挑战性。 -
碰撞检测:
目前只有边界碰撞检测和食物碰撞检测,可以考虑添加对蛇头与蛇身碰撞的检测,以防止游戏结束。 -
游戏结束提示:
当游戏结束时,可以输出更友好的提示信息,告诉玩家是因为碰到墙还是碰到自己身体而导致游戏结束。 -
代码结构和模块化:
将代码进一步模块化,使得各部分功能更清晰、易读、易于维护。可以考虑将一些功能性代码抽象成函数。 -
用户界面交互:
添加开始界面和游戏结束后的界面,以提供更良好的用户体验。 -
更多游戏元素:
考虑添加更多的游戏元素,如障碍物、特殊道具等,以增加游戏的趣味性和多样性。
这些功能给大家作为练习去实现。