C语言实现贪吃蛇

贪吃蛇是我们耳熟能详的游戏,游戏思路很简单,我们操纵一条蛇在屏幕上游走寻找食物,当吃到食物时蛇就会变长,当蛇头碰到墙壁或者自己的身体时,此时蛇就会死亡,而游戏也就结束了。

那么我们设计游戏的时候,需要注意三点:

(1)及时刷新蛇的位置

(2)蛇吃到食物时,蛇的身体会变长,同时及时刷新新的食物

(3)蛇在遇到墙壁和自己的身体时会死亡

直接看代码:

#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#include<math.h>
#include<time.h>

//设置蛇的活动范围为L
#define L 20 

//绘制游戏界面时,蛇的和食物的代号
#define SNAKE 1
#define FOOD  2

//定义蛇的结构体
struct Snake {
	int x;
	int y;
	Snake* next;
};

//初始化蛇链表,length为链表长度
Snake* InitSnake(int length);
//释放蛇链表
void FreeSnake(Snake* head);
//刷新蛇的位置
void SnakeMove(int x, int y, Snake* head);
//更新食物的位置
void RefreshFood(int* x, int* y, Snake* head);
//绘制游戏界面
bool DrewMap(int score,Snake* head, int foodx, int foody);

int main() {
	//蛇头位置
	int headx = L/2;
	int heady = L/2;

	//下一次的移动方向
	int movex = 0;
	int movey = 1;

	//食物的位置
	int foodx = 0;
	int foody = 0;

	//获得分数
	int score = 0;

	//初始化蛇
	Snake* head = InitSnake(5);

	//初始化食物位置
	srand((unsigned)time(NULL));
	RefreshFood(&foodx, &foody, head);

	//更新游戏界面
	DrewMap(score,head, foodx, foody);

	while (1) {
		//判断是否敲击键盘
		if (_kbhit()) {
			//更新移动方向
			switch (_getch()) {
			case 'a':
				movex = 0;
				movey = -1;
				break;
			case 's':
				movex = 1;
				movey = 0;
				break;
			case 'd':
				movex = 0;
				movey = 1;
				break;
			case 'w':
				movex = -1;
				movey = 0;
				break;
			default:
				break;
			}
		}

		//更新蛇头位置
		headx += movex;
		heady += movey;

		//判断蛇是否吃到食物
		if (headx == foodx && heady == foody) {
			++score;
			//吃到食物时,在链表中插入食物所在位置的节点
			Snake *node = (Snake*)malloc(sizeof(Snake));
			node->x = headx;
			node->y = heady;
			node->next = head->next;
			head->next = node;

			//刷新食物出现位置
			RefreshFood(&foodx, &foody, head);
		}else {
			SnakeMove(headx, heady, head);
		}

		//休眠,也就是控制蛇的速度
		Sleep(500/sqrt(score+1));

		//清屏
		system("cls");

		//绘制游戏界面并判断是否结束游戏
		if (!DrewMap(score,head, foodx, foody)) {
			break;
		}
	}

	FreeSnake(head);
	printf("YOU DIE!\n");
	system("pause");
}

//刷新蛇的位置
//思路:中间的节点都不变,把最后一位节点放到链表开头并且更新x,y
void SnakeMove(int x, int y, Snake* head) {
	Snake* p = head;
	while (p->next->next != NULL) {
		p = p->next;
	}
	p->next->next = head->next;
	head->next = p->next;
	p->next = NULL;
	head->next->x = x;
	head->next->y = y;
}

//刷新食物,确保食物出现的位置不在蛇身上以及墙壁上
void RefreshFood(int* x, int* y, Snake* head) {
	while (1) {
		Snake* p = head;
		*x = rand() % (L - 2) + 1;
		*y = rand() % (L - 2) + 1;

		while (p != NULL) {
			if (p->x == *x&&p->y == *y) {
				break;
			}
			p = p->next;
		}

		if (p != NULL) {
			continue;
		}
		break;
	}
}

//初始化蛇,产生长度为length+1的链表,返回的头指针不存放数据
Snake* InitSnake(int length) {
	Snake* re = (Snake*)malloc(sizeof(Snake));
	re->next = NULL;

	while (length-- > 0) {
		Snake* node = (Snake*)malloc(sizeof(Snake));
		node->x = L / 2 - length;
		node->y = L / 2;
		node->next = re->next;
		re->next = node;
	}

	return re;
}

//游戏结束后,释放链表
void FreeSnake(Snake* head) {
	if (head==NULL){
		return;
	}

	FreeSnake(head->next);
	free(head);
}

//绘制游戏界面,同时检测是否需要结束游戏
bool DrewMap(int score,Snake* head, int foodx, int foody) {
	int map[L][L] = { 0 };
	Snake *p = head->next;
	while (p != NULL) {
		//判断蛇是否碰到墙壁或者咬到自己
		if (map[p->x][p->y] == SNAKE || p->x<1 || p->y<1 || p->x >= L - 1 || p->y >= L - 1) {
			return false;
		}
		map[p->x][p->y] = SNAKE;
		p = p->next;
	}
	map[foodx][foody] = FOOD;

	//绘制界面
	printf("Score:%d\n", score * 10);
	for (int i = 0; i < L; i++) {
		for (int j = 0; j < L; j++) {
			if (i == 0 || j == 0 || i == L - 1 || j == L - 1) printf("##");//墙壁
			else if (map[i][j] == SNAKE) printf("@@");//蛇
			else if (map[i][j] == FOOD) printf("$$");//食物
			else printf("  ");
		}
		printf("\n");
	}
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值