贪吃蛇 (C语言实现)

1.贪吃蛇的头文件和所需函数声明

代码中已给出注释,参考代码就可以了

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>

void welcome();  //欢迎界面 
void border();  //创建边界 
void Pos(int x, int y);  //改变控制台光标位置 
void getRandomPos(int* x, int* y);  //获取随机坐标
void initSnake();  //蛇的初始化
void createFood();  //生成食物
int inSnake(int x, int y);  //判断(x, y)是否在蛇上,1表示在,0表示不在 
void snakeMove();  //蛇的移动 
int getDirection();  //获取移动方向,0、1、2、3分别代表上、下、左、右 

typedef struct Node {
	int x;
	int y;
	Node* next;
}node;

//全局变量
node* head;  //蛇头
node food;  //食物 
int reCreateFood;  //判断食物是否被吃掉
int fail;  //如果蛇头碰到蛇身或边界则失败 
int score, add = 10;  //定义分数和每个食物的分数 
int dx[4] = { 0, 0, -1, 1 }, dy[4] = { -1, 1, 0, 0 };  //(dx[0], dy[0])为(0, 1),即代表“上”
int d = -1;  //表示蛇前进的方向,与上一行对应,0为上,1为下,2为左,3为右
//开局时初始化为-1,表示还未按方向键 

}
语法说明
标题文本样式列表图片链接目录代码片表格注脚注释自定义列表LaTeX 数学公式插入甘特图插入UML图插入Mermaid流程图插入Flowchart流程图插入类图快捷键
目录复制

2.主函数实现

int main() {
	welcome();  //欢迎界面 
	border();  //创建边界 
	initSnake();  //蛇的初始化 
	createFood();  //生成食物 

	//fail != 0就一直进行 
	while (1) {
		if (fail) break;
		//食物被吃掉需要重新生成 
		if (reCreateFood) {
			createFood();
			reCreateFood = 0;
		}
		snakeMove();  //蛇的移动 
		Sleep(500);  //程序暂停500毫秒,注释掉运行一下就懂了
		//获取新的方向 
		d = getDirection();
	}

	//这个也是注释掉对比一下就懂了 
	Pos(0, 24);
	printf("\n");

	return 0;
}

3.欢迎界面

void welcome() {
	system("mode con cols=100 lines=30");
	system("cls");

	Pos(38, 6);
	printf("欢迎来到贪吃蛇游戏\n");
	Pos(38, 8);
	printf("↑↓←→控制方向\n");
	Pos(45, 10);
	printf("ESC 退出\n");
	Pos(42, 12);
	printf("Enter 开始\n");
	getchar();
	system("cls");
}

4.改变控制台光标位置

void Pos(int x, int y) {
	COORD pos;  //位置坐标 
	pos.X = x;
	pos.Y = y;

	HANDLE handleOutput = GetStdHandle(STD_OUTPUT_HANDLE);  //获取输出句柄 
	SetConsoleCursorPosition(handleOutput, pos);   //定位 
}

5.创建边界

void border() {  //创建以(0, 0), (59, 25)为顶点的矩形边界
	for (int i = 0; i < 60; i++) {
		Pos(i, 0);  //上行 
		printf("▇");
		Pos(i, 25);  //下行 
		printf("▇");
	}

	for (int i = 1; i < 25; i++) {
		Pos(0, i);  //左列 
		printf("▇");
		Pos(59, i);  //右列 
		printf("▇");
	}
}

6.获取随机坐标

void getRandomPos(int* x, int* y) {
	srand((unsigned int)time(NULL));
	*x = rand() % 58 + 1;
	*y = rand() % 24 + 1;
}

7.蛇的初始化

void initSnake() {
	head = (node*)malloc(sizeof(node));
	//保证在边界内
	head->x = rand() % 58 + 1;
	head->y = rand() % 24 + 1;
	head->next = NULL;

	Pos(head->x, head->y);
	printf("*");
}

8.生成食物

void createFood() {
	int x, y;
	getRandomPos(&x, &y);
	if (inSnake(x, y)) createFood();  //重新生成
	food.x = x;
	food.y = y;
	Pos(x, y);
	printf("$");
}

9.判断(x, y)是否在蛇上

int inSnake(int x, int y) {
	node* p = head->next;
	while (p) {  //从头遍历蛇身 
		if (x == p->x && y == p->y)
			return 1;
		p = p->next;
	}
	return 0;
}

10.蛇的移动

void snakeMove() {
	//刚开局未按方向键的情况 
	if (d == -1)
		while (d == -1) d = getDirection();

	node* newHead = (node*)malloc(sizeof(node));
	newHead->x = head->x + dx[d];
	newHead->y = head->y + dy[d];
	newHead->next = head;
	head = newHead;

	node* p = head;
	if (inSnake(p->x, p->y) || (p->x == 0 || p->x == 59 || p->y == 0 || p->y == 25))
		fail = 1;
	else if (p->x != food.x || p->y != food.y) {
		Pos(p->x, p->y);
		printf("*");

		while (p->next->next) p = p->next;
		Pos(p->next->x, p->next->y);
		printf(" ");
		p->next = NULL;
	}
	else {
		reCreateFood = 1;
		score += add;
		Pos(p->x, p->y);
		printf("*");
	}
	Pos(61, 25);
	printf("您的得分为:%d", score);
}

11.获取移动方向

int getDirection() {
	//不能往反方向走 
	if ((GetAsyncKeyState(VK_UP) & 0x8000) && d != 1) d = 0;
	else if ((GetAsyncKeyState(VK_DOWN) & 0x8000) && d != 0) d = 1;
	else if ((GetAsyncKeyState(VK_LEFT) & 0x8000) && d != 3) d = 2;
	else if ((GetAsyncKeyState(VK_RIGHT) & 0x8000) && d != 2) d = 3;
	return d;
}

12.完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>

void welcome();  //欢迎界面 
void border();  //创建边界 
void Pos(int x, int y);  //改变控制台光标位置 
void getRandomPos(int* x, int* y);  //获取随机坐标
void initSnake();  //蛇的初始化
void createFood();  //生成食物
int inSnake(int x, int y);  //判断(x, y)是否在蛇上,1表示在,0表示不在 
void snakeMove();  //蛇的移动 
int getDirection();  //获取移动方向,0、1、2、3分别代表上、下、左、右 

typedef struct Node {
	int x;
	int y;
	Node* next;
}node;

//全局变量
node* head;  //蛇头
node food;  //食物 
int reCreateFood;  //判断食物是否被吃掉
int fail;  //如果蛇头碰到蛇身或边界则失败 
int score, add = 10;  //定义分数和每个食物的分数 
int dx[4] = { 0, 0, -1, 1 }, dy[4] = { -1, 1, 0, 0 };  //(dx[0], dy[0])为(0, 1),即代表“上”
int d = -1;  //表示蛇前进的方向,与上一行对应,0为上,1为下,2为左,3为右
//开局时初始化为-1,表示还未按方向键 

int main() {
	welcome();  //欢迎界面 
	border();  //创建边界 
	initSnake();  //蛇的初始化 
	createFood();  //生成食物 

	//fail != 0就一直进行 
	while (1) {
		if (fail) break;
		//食物被吃掉需要重新生成 
		if (reCreateFood) {
			createFood();
			reCreateFood = 0;
		}
		snakeMove();  //蛇的移动 
		Sleep(500);  //程序暂停500毫秒,注释掉运行一下就懂了
		//获取新的方向 
		d = getDirection();
	}

	//这个也是注释掉对比一下就懂了 
	Pos(0, 24);
	printf("\n");

	return 0;
}

void welcome() {
	system("mode con cols=100 lines=30");
	system("cls");

	Pos(38, 6);
	printf("欢迎来到贪吃蛇游戏\n");
	Pos(38, 8);
	printf("↑↓←→控制方向\n");
	Pos(45, 10);
	printf("ESC 退出\n");
	Pos(42, 12);
	printf("Enter 开始\n");
	getchar();
	system("cls");
}

void border() {  //创建以(0, 0), (59, 25)为顶点的矩形边界
	for (int i = 0; i < 60; i++) {
		Pos(i, 0);  //上行 
		printf("▇");
		Pos(i, 25);  //下行 
		printf("▇");
	}

	for (int i = 1; i < 25; i++) {
		Pos(0, i);  //左列 
		printf("▇");
		Pos(59, i);  //右列 
		printf("▇");
	}
}

void Pos(int x, int y) {
	COORD pos;  //位置坐标 
	pos.X = x;
	pos.Y = y;

	HANDLE handleOutput = GetStdHandle(STD_OUTPUT_HANDLE);  //获取输出句柄 
	SetConsoleCursorPosition(handleOutput, pos);   //定位 
}

void getRandomPos(int* x, int* y) {
	srand((unsigned int)time(NULL));
	*x = rand() % 58 + 1;
	*y = rand() % 24 + 1;
}

void initSnake() {
	head = (node*)malloc(sizeof(node));
	//保证在边界内
	head->x = rand() % 58 + 1;
	head->y = rand() % 24 + 1;
	head->next = NULL;

	Pos(head->x, head->y);
	printf("*");
}

void createFood() {
	int x, y;
	getRandomPos(&x, &y);
	if (inSnake(x, y)) createFood();  //重新生成
	food.x = x;
	food.y = y;
	Pos(x, y);
	printf("$");
}

int inSnake(int x, int y) {
	node* p = head->next;
	while (p) {  //从头遍历蛇身 
		if (x == p->x && y == p->y)
			return 1;
		p = p->next;
	}
	return 0;
}

void snakeMove() {
	//刚开局未按方向键的情况 
	if (d == -1)
		while (d == -1) d = getDirection();

	node* newHead = (node*)malloc(sizeof(node));
	newHead->x = head->x + dx[d];
	newHead->y = head->y + dy[d];
	newHead->next = head;
	head = newHead;

	node* p = head;
	if (inSnake(p->x, p->y) || (p->x == 0 || p->x == 59 || p->y == 0 || p->y == 25))
		fail = 1;
	else if (p->x != food.x || p->y != food.y) {
		Pos(p->x, p->y);
		printf("*");

		while (p->next->next) p = p->next;
		Pos(p->next->x, p->next->y);
		printf(" ");
		p->next = NULL;
	}
	else {
		reCreateFood = 1;
		score += add;
		Pos(p->x, p->y);
		printf("*");
	}
	Pos(61, 25);
	printf("您的得分为:%d", score);
}

int getDirection() {
	//不能往反方向走 
	if ((GetAsyncKeyState(VK_UP) & 0x8000) && d != 1) d = 0;
	else if ((GetAsyncKeyState(VK_DOWN) & 0x8000) && d != 0) d = 1;
	else if ((GetAsyncKeyState(VK_LEFT) & 0x8000) && d != 3) d = 2;
	else if ((GetAsyncKeyState(VK_RIGHT) & 0x8000) && d != 2) d = 3;
	return d;
}

13.结果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值