贪吃蛇实现代码

//头文件GameSnake.h

#pragma once
//实现头文件的包含,贪吃蛇身子,贪吃蛇游戏,函数声明
#include <stdio.h>
#include <graphics.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
#include <stdlib.h>
#include <Windows.h>
#include <stdbool.h>
#include <locale.h>
#include <time.h>
#define WALL L'□'
#define BODY L'●' 
#define FOOD L'★' 

#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)

//蛇的初始位置
#define POS_X 34
#define POS_Y 12

//方向
enum DIRECTION {
	UP =1,
	DOWN,
	LEFT,
	RIGHT
};
enum STATUS {
	OK,  //正常游戏
	KILL_BY_WALL, //撞墙
	KILL_BY_SELF, //被自己杀死
	END_NORMAL  //正常结束
};

//蛇身节点
typedef struct SnakeNode {
	short x;
	short y;
	struct SnakeNode* next;
}SnakeNode,*pSnakeNode;

//贪吃蛇维护
typedef struct Snake {
	pSnakeNode SnakeHead;//贪吃蛇蛇身维护
	pSnakeNode pFood;//食物
	int FoodWeight;//食物分数
	int Score;//总分数
	int speed;
	int SleepTime;//每走一步休眠时间
	enum DIRECTION dir;//默认方向向上
	enum STATUS status;
}Snake,*pSnake;


void GameStart(pSnake ps);
void InitSnake(pSnake ps);
void CreateFood(pSnake ps);
void PrintHelpInfo(pSnake ps);
void GameRun(pSnake ps);
void SnakeMove(pSnake ps);
int NextIsFood(pSnakeNode nextnode, pSnake ps);
void EatFood(pSnakeNode nextnode, pSnake ps);
void NoFood(pSnakeNode nextnode, pSnake ps);
void GameEnd(pSnake ps);
int KillByWall(pSnake ps);
int KillBySelf(pSnake ps);
void SetPos(short x, short y);

//实现文件GameSnake.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "GameSnake.h"
void SetPos(short x, short y)
{
	COORD pos = { x,y };
	HANDLE hOutput = NULL;
	//获取句柄
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	//设置标准输出上光标的位置为pos
	SetConsoleCursorPosition(hOutput, pos);
}

void CreatMap()
{
	//首先定位到(0,0)
	SetPos(0, 0);
	int i = 0;
	//打印围墙		
	for (i = 0; i < 58; i += 2)
	{
		wprintf(L"%c", WALL);
	}
	SetPos(0, 26);
	for (i = 0; i < 58; i += 2)
	{
		wprintf(L"%c", WALL);
	}
	
	for (i = 1; i < 26; i++)
	{
		SetPos(0, i);
		wprintf(L"%c", WALL);
	}
	for (i = 1; i < 26; i++)
	{
		SetPos(56, i);
		wprintf(L"%c", WALL);
	}
}
void InitSnake(pSnake ps) {
	pSnakeNode pcur = NULL;
	for (int i = 0; i < 5; i++)
	{
		pcur = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (pcur == NULL)
		{
			perror("init malloc");
			exit(1);
		}
		pcur->x = POS_X +2 * i;
		pcur->y = POS_Y;
		pcur->next = NULL;

		if (ps->SnakeHead == NULL)
		{
			ps->SnakeHead = pcur;
		}
		else {
			pcur->next = ps->SnakeHead;
			ps->SnakeHead = pcur;
		}
		//SetPos(pcur->x, pcur->y);
		//wprintf(L"%c", BODY);
	}
	pcur = ps->SnakeHead;
	while (pcur) {
		SetPos(pcur->x, pcur->y);
        wprintf(L"%c", BODY);
		pcur = pcur->next;
	}
	ps->FoodWeight = 1;
	ps->Score = 0;
	ps->SleepTime = 200;
	ps->dir = RIGHT;
	ps->status = OK;
	ps->speed = 10;
}

void Welcome() {
	SetPos(40, 12);
	printf("欢迎来到我的游戏场地!");
	SetPos(40, 13);
	printf("贪吃蛇小游戏!!!!!");
	SetPos(40, 20);
	system("pause");
	system("cls");
	SetPos(30, 13);
	printf("用W.A.S.D分别控制蛇的方向");
	SetPos(30, 14);
	printf("Q为加速,E为减速,加速可以获得更多的道哦");
	SetPos(38, 20);
	system("pause");
	system("cls");
}

void CreateFood(pSnake ps)
{
	//确保食物会出现在2的倍数上且食物不在墙里
	//所以食物的x>2并且y>1
	//采用时间戳随机获得0到54的数字和0到27的数字
	int x = 0;
	int y = 0;
again:
	do
	{
		x = rand() % 53 + 2;
		y = rand() % 25 + 1;
	} while (x % 2 != 0);
	//食物不在蛇肚子里
	pSnakeNode pcur = ps->SnakeHead;
	while (pcur) {
		if (pcur->x == x && pcur->y == y)
		{
			goto again;
		}
		pcur = pcur->next;
	}
	//创建食物
	pSnakeNode Food = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (Food == NULL)
	{
		perror("malloc food");
		exit(1);
	}
	else {
		Food->x = x;
		Food->y = y;
		SetPos(x, y);
		wprintf(L"%c", FOOD);
		ps->pFood = Food;
	}
}
void PrintHelpInfo(pSnake ps)
{
	SetPos(60, 10);
	printf("请遵守以下规则.");
	SetPos(60, 11);
	printf("用W.A.S.D控制蛇的方向, Q为加速,E为减速.");
	SetPos(60, 12);
	printf("ESC :退出游戏.space:暂停游戏.");
	SetPos(60, 13);
	printf("务必记住不要撞墙也不要咬到自己!!");
}
int NextIsFood(pSnakeNode nextnode, pSnake ps)
{
	return (nextnode->x == ps->pFood->x) && (nextnode->y == ps->pFood->y);
}
void EatFood(pSnakeNode nextnode, pSnake ps)
{
	//将食物节点头插到🐍,原位置变为空白
	nextnode->next = ps->SnakeHead;
	ps->SnakeHead = nextnode;
	pSnakeNode cur = ps->SnakeHead;
	//打印蛇
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	//加分
	ps->Score += ps->FoodWeight;
	//释放食物节点
	free(ps->pFood);
	CreateFood(ps);
}
void NoFood(pSnakeNode nextnode, pSnake ps)
{
	//头插法
	nextnode->next = ps->SnakeHead;
	ps->SnakeHead = nextnode;
	pSnakeNode cur = ps->SnakeHead;
	//打印蛇
	while (cur->next->next)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", BODY);
		cur = cur->next;
	}
	//最后⼀个位置打印空格,然后释放节点
	SetPos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;
}

void SnakeMove(pSnake ps)
{
	//创建下一个节点
	pSnakeNode nextnode = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (nextnode == NULL)
	{
		perror("malloc nextnode");
		exit(1);
	}
	//确定下一个节点的坐标,根据蛇头方向和dir方向确定
	switch (ps->dir)
	{
	case UP:
		nextnode->x = ps->SnakeHead->x;
		nextnode->y = ps->SnakeHead->y-1;
		break;
	case DOWN:
		nextnode->x = ps->SnakeHead->x;
		nextnode->y = ps->SnakeHead->y+1;
		break;
	case RIGHT:
		nextnode->x = ps->SnakeHead->x+2;
		nextnode->y = ps->SnakeHead->y;
		break;
	case LEFT:
		nextnode->x = ps->SnakeHead->x-2;
		nextnode->y = ps->SnakeHead->y;
		break;
	}
	//如果下一个就是食物
	if(NextIsFood(nextnode, ps))
	{
		EatFood(nextnode,ps);
	}
	else//如果没有⻝物
	{
		NoFood(nextnode, ps);
	}
	KillByWall(ps);
	KillBySelf(ps);
}
void pause()
{
	while (1)
	{
		Sleep(300);
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
	}
}
void GameStart(pSnake ps)
{
	//开始游戏首先先把基本场地搞出来
	system("mode con cols=100 lines=30");
	system("title 贪吃蛇");
	//精细化游戏场地
	//1.先把光标隐藏
	/// 获取标准输出的句柄(⽤来标识不同设备的数值)
	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	//影藏光标操作
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
	CursorInfo.bVisible = false; //隐藏控制台光标
	SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态

	//打印欢迎界面
	Welcome();
	//创建游戏场地
	CreatMap();
	//创建🐍身
	InitSnake(ps);
	//创建食物
	CreateFood(ps);
	//打印提示信息
	PrintHelpInfo(ps);
	
}
int KillByWall(pSnake ps)
{
	if ((ps->SnakeHead->x == 0)
		|| (ps->SnakeHead->x == 56)
		|| (ps->SnakeHead->y == 0)
		|| (ps->SnakeHead->y == 26))
	{
		ps->status = KILL_BY_WALL;
		return 1;
	}
	return 0;
}
int KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->SnakeHead->next;
	while (cur)
	{
		if ((ps->SnakeHead->x == cur->x)
			&& (ps->SnakeHead->y == cur->y))
		{
			ps->status = KILL_BY_SELF;
			return 1;
		}
		cur = cur->next;
	}
	return 0;
}
void GameRun(pSnake ps)
{
	//移动🐍
	do {
		SetPos(60, 15);
		printf("您当前的速度为:%d.", ps->speed);
		SetPos(60, 16);
		printf("可获得的道的数量:%d.",ps->FoodWeight);
		SetPos(60, 17);
		printf("您当前的道的数量为:%d.", ps->Score);
		if (KEY_PRESS(0x57) && ps->dir != DOWN)
		{
			ps->dir = UP;
		}
		else if (KEY_PRESS(0x53) && ps->dir != UP)
		{
			ps->dir = DOWN;
		}
		else if (KEY_PRESS(0x41) && ps->dir != RIGHT)
		{
			ps->dir = LEFT;
		}
		else if (KEY_PRESS(0x44) && ps->dir != LEFT)
		{
			ps->dir = RIGHT;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			pause();
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			ps->status = END_NORMAL;
			break;
		}
		else if (KEY_PRESS(0x51))
		{
			if (ps->SleepTime >= 50)
			{
				ps->speed += 2;
				ps->SleepTime -= 30;
				ps->FoodWeight += 2;
			}
		}
		else if (KEY_PRESS(0x45))
		{
			if (ps->SleepTime < 300)
			{
				ps->speed -= 2;
				ps->SleepTime += 30;
				ps->FoodWeight -= 2;
				if (ps->SleepTime == 350)
				{
					ps->FoodWeight = 1;
				}
			}
		}
		//蛇每次⼀定之间要休眠的时间,时间短,蛇移动速度就
		Sleep(ps->SleepTime);
		SnakeMove(ps);
	} while (ps->status==OK);
}
void GameEnd(pSnake ps)
{
	pSnakeNode cur = ps->SnakeHead;
	SetPos(24, 12);
	switch (ps->status)
	{
	case END_NORMAL:
		printf("您主动退出游戏\n");
		break;
	case KILL_BY_SELF:
		printf("您撞上自己了 ,游戏结束!\n");
		break;
	case KILL_BY_WALL:
		printf("您撞墙了,游戏结束!\n");
		break;
	}

	//释放蛇身的节点
	while (cur)
	{
		pSnakeNode del = cur;
		cur = cur->next;
		free(del);
	}
	//释放食物
	free(ps->pFood);
	
}

//测试文件test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "GameSnake.h"
#include <graphics.h>
void Game()
{
	int ch = 0;
	srand((unsigned int)time(NULL));
	setlocale(LC_ALL, "");
	Snake snake = { 0 };
	do {
		GameStart(&snake);
		GameRun(&snake);
		GameEnd(&snake);
		SetPos(20, 15);
		printf("还要在来一次吗?(Y/N)");
		ch = getchar();
		getchar();//清理'\n'
	} while (ch=='Y'||ch=='y');


}
int main()
{
	/*initgraph(1024, 494);
	loadimage(0, L"src/bg.jpg");
	mciSendString(L"play src/bg.mp3 repeat", 0, 0, 0);
	system("pause");*/
	Game();
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值