C语言实现贪吃蛇小游戏1.0
贪吃蛇游戏要有三个东西:边框、蛇、食物
还有两个灵魂的东西:光标的移动与按键监控
一、光标的移动
在我看来在控制台上移动光标画图是实现这个小游戏的灵魂了,在这之前我一直以为控制台上的输出只能一行一行地往下…
//功能:给到两个int参数,将控制台地光标移动到指定位置
void gotoxy(int x, int y) {
//调用win32 API去设置控制台的光标
//找到控制台的窗口
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
//光标的结构体
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(handle, coord);
}
二、边框:
规定地图的大小,用“· ”组成
void initmap() {
for (int i = 0; i <= LENGTHSIZE; i+=2) {
gotoxy(i, 0);
printf("·");
gotoxy(i, WIDETHSIZE);
printf("·");
}
for (int i = 0; i <= WIDETHSIZE; i++) {
gotoxy(0, i);
printf("·");
gotoxy(LENGTHSIZE, i);
printf("·");
}
}
代码第二行的i+=2是因为“·”符号占两个字符
三、蛇:
定义蛇的结构体
typedef struct {
int x[SNAKESIZE];
int y[SNAKESIZE];
int length;
int speed;
int position;
}Snake;
Snake snake;
初始化一条蛇
//游戏开始前生成一条蛇并初始化它各项属性
void initsnake() {
snake.length = 3;
snake.speed = 150;
snake.position = 'w';
snake.x[0] = LENGTHSIZE / 2;
snake.y[0] = WIDETHSIZE / 2;
gotoxy(snake.x[0], snake.y[0]);
printf("*");
for (int i = 1; i < snake.length; i++) {
printf("*");
snake.x[i] = snake.x[i - 1] + 1;
snake.y[i] = snake.y[i - 1];
}
}
蛇身:用“*”号表示,并用两个int数组存放每节蛇身的坐标
移动:擦去尾巴,添上头,
方向(按键操作):导入头文件conio.h,也是小游戏灵魂啊~
吃:增长一节
//对按键做出的反应
//w向上走,s向下,a向左,d向右
void keycope(int key) {
switch (key) {
case 'W':
case 'w':
snake.y[0]--;
break;
case 's':
case 'S':
snake.y[0]++;
break;
case 'D':
case 'd':
snake.x[0]++;
break;
case 'A':
case 'a':
snake.x[0]--;
break;
default:
break;
}
}
int snake_move() {
int key = snake.position;//无按键输入按原方向走
gotoxy(snake.x[snake.length - 1], snake.y[snake.length - 1]);
//保存蛇尾坐标,是为了如果吃到食物就长大一节,长大的那一节就放在这个坐标上
int endx = snake.x[snake.length - 1];
int endy = snake.y[snake.length - 1];
printf(" ");//删除/覆盖蛇尾
//按键监控
if (_kbhit()) {
fflush(stdin);
key = _getch();//把输入的按键保存下来
snake.position = key;//改变方向
}//有按键输入改变方向
for (int i = snake.length - 1; i > 0;i--) {
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
}
keycope(key);//改变蛇头坐标
gotoxy(snake.x[0], snake.y[0]);
printf("*");
gotoxy(LENGTHSIZE + 1, WIDETHSIZE + 1);
if (snake_eat()) {
snake.x[snake.length - 1] = endx;
snake.y[snake.length - 1] = endy;
gotoxy(endx, endy);
printf("*");
}//吃到吃的,长大
return 1;
}
速度:用函数Sleep(unsigned long)控制。其中,Sleep()里面的单位,是以毫秒为单位的。
int main() {
initmap();
do {
snake_move();
Sleep(snake.speed);//速度的设置
gotoxy(0,WIDETHSIZE+1);
for (int i = 0; i < snake.length - 1; i++)
printf("%d,%d ",snake.x[i], snake.y[i]);
printf("\n长度:%d",snake.length);
} while (gameover());
gotoxy(0, WIDETHSIZE + 1);
return 0;
}
四、食物:
用“@”表示随机生成(生成范围应该在地图内,且不能生成在蛇身上)
int food_app() {
int x, y;
do {
srand((unsigned)time(NULL));//播种
x = rand() % (LENGTHSIZE - 1) + 2;//表示生成1到WIDETHSIZE-1之间的随机数
y = rand() % (WIDETHSIZE - 1) + 1;
} while (!food_est(x, y));//判断食物在不在蛇身上
gotoxy(x, y);
printf("@");//放在循环外面,否则不符合条件的食物/光标也会显示
food.x = x;
food.y = y;
return 1;
}
五、结束:
1.胜利(蛇的长度达到设定值)
2.失败(撞墙/吃到自己)
嗯,我知道我的英语emm…
会不断学习的…
int gameover() {
//撞墙
if (snake.x[0] == 0 || snake.x[0] == LENGTHSIZE || snake.y[0] == WIDETHSIZE || snake.y[0] == 0) {
gotoxy(LENGTHSIZE / 2 - 8, WIDETHSIZE / 2);
printf("gameover! you fail!");
return 0;
}
//吃到自己
else if (!eatitself()) {
gotoxy(LENGTHSIZE / 2 - 8, WIDETHSIZE / 2);
printf("gameover! you eat yourself!");
return 0;
}
//胜利
else if (snake.length >= SNAKESIZE) {
gotoxy(LENGTHSIZE / 2 - 4, WIDETHSIZE / 2);
printf("you win!");
return 0;
}
else return 1;
}
六、完整代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<conio.h>
#define LENGTHSIZE 50
#define WIDETHSIZE 25
#define SNAKESIZE 30
///设计一个贪吃蛇小游戏/
typedef struct {
int x[SNAKESIZE];
int y[SNAKESIZE];
int length;
int speed;
int position;
}Snake;
Snake snake;
typedef struct {
int x;
int y;
}FOOD;
FOOD food;
//光标移动/
void gotoxy(int x, int y) {
//调用win32 API去设置控制台的光标
//找到控制台的窗口
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
//光标的结构体
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(handle, coord);
}
/画地图/
//初始化一条蛇
void initsnake() {
snake.length = 3;
snake.speed = 150;
snake.position = 'w';
snake.x[0] = LENGTHSIZE / 2;
snake.y[0] = WIDETHSIZE / 2;
gotoxy(snake.x[0], snake.y[0]);
printf("*");
for (int i = 1; i < snake.length; i++) {
printf("*");
snake.x[i] = snake.x[i - 1] + 1;
snake.y[i] = snake.y[i - 1];
}
}
//画吃的
//判断位置是否合法
int food_est(int x, int y) {
for (int i = 0; i < snake.length; i++)
if (snake.x[i] == x && snake.y[i] == y)
return 0;
return 1;
}
//生成食物
int food_app() {
int x, y;
do {
srand((unsigned)time(NULL));//播种
x = rand() % (LENGTHSIZE - 1) + 1;//表示生成1到WIDETHSIZE-1之间的随机数
y = rand() % (WIDETHSIZE - 1) + 1;
} while (!food_est(x, y));
gotoxy(x, y);
printf("@");//放在循环外面,否则不符合条件的食物/光标也会显示
food.x = x;
food.y = y;
return 1;
}
//圈地
void initmap() {
for (int i = 0; i <= LENGTHSIZE; i+=2) {
gotoxy(i, 0);
printf("·");
gotoxy(i, WIDETHSIZE);
printf("·");
}
for (int i = 0; i <= WIDETHSIZE; i++) {
gotoxy(0, i);
printf("·");
gotoxy(LENGTHSIZE, i);
printf("·");
}
initsnake();
food_app();
}
//对按键的反应
void keycope(int key) {
switch (key) {
case 'W':
case 'w':
snake.y[0]--;
break;
case 's':
case 'S':
snake.y[0]++;
break;
case 'D':
case 'd':
snake.x[0]++;
break;
case 'A':
case 'a':
snake.x[0]--;
break;
default:
break;
}
}
//长大
int snake_eat() {
if (food.x == snake.x[0] && food.y == snake.y[0]) {
snake.length++;
food_app();//继续生成食物
return 1;
}
else return 0;
}
//蛇的移动
int snake_move() {
int key = snake.position;//无按键输入按原方向走
gotoxy(snake.x[snake.length - 1], snake.y[snake.length - 1]);
//保存蛇尾坐标
int endx = snake.x[snake.length - 1];
int endy = snake.y[snake.length - 1];
printf(" ");//删除蛇尾
if (_kbhit()) {
fflush(stdin);
key = _getch();
snake.position = key;
}//有按键输入改变方向
for (int i = snake.length - 1; i > 0;i--) {
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
}
keycope(key);
gotoxy(snake.x[0], snake.y[0]);
printf("*");
gotoxy(LENGTHSIZE + 1, WIDETHSIZE + 1);
if (snake_eat()) {
snake.x[snake.length - 1] = endx;
snake.y[snake.length - 1] = endy;
gotoxy(endx, endy);
printf("*");
}//吃到吃的
return 1;
}
//游戏状态
int eatitself() {
for (int i = 1; i < snake.length; i++) {
if (snake.x[0] == snake.x[i]&& snake.y[0]==snake.y[i]) {
return 0;
}
}
return 1;
}
int gameover() {
//撞墙
if (snake.x[0] == 0 || snake.x[0] == LENGTHSIZE || snake.y[0] == WIDETHSIZE || snake.y[0] == 0) {
gotoxy(LENGTHSIZE / 2 - 8, WIDETHSIZE / 2);
printf("gameover! you fail!");
return 0;
}
//吃到自己
else if (!eatitself()) {
gotoxy(LENGTHSIZE / 2 - 8, WIDETHSIZE / 2);
printf("gameover! you eat yourself!");
return 0;
}
//胜利
else if (snake.length >= SNAKESIZE) {
gotoxy(LENGTHSIZE / 2 - 4, WIDETHSIZE / 2);
printf("you win!");
return 0;
}
else return 1;
}
int main() {
initmap();
do {
snake_move();
Sleep(snake.speed);
gotoxy(0,WIDETHSIZE+1);
printf("长度:%d",snake.length);
} while (gameover());
gotoxy(0, WIDETHSIZE + 1);
return 0;
}