小游戏:贪吃蛇

news2024/9/24 3:21:55

🎁个人主页:我们的五年

🔍系列专栏:贪吃蛇

🌷追光的人,终会万丈光芒

 

 

目录

🏝1.头文件:

 🏝2.实现文件:

🏝3.测试文件 :


 

 前言:这个在学习C语言的对知识点进行巩固的一个小游戏,后面也会持续带来一下小游戏。喜欢的帖子们可以点点关注。

相关系列文章:贪吃蛇
 

🏝1.头文件:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<locale.h>
#include<windows.h>
#include<time.h>

#define POS_X 24
#define POS_Y 5
#define WALL L'□'
#define BODY L'●'
#define FOOD L'●'

//类型声明

//蛇的方向
enum DIECTION {
	UP = 1,
	DOWN,
	LEFT,
	RIGHT
};

//贪吃蛇的状态
// 正常,撞墙,撞到自己,正常退出。

enum GAME_STATUS
{
	OK,            //正常
	KILL_BY_WALL,  //撞墙
	KILL_BY_SLEF,  //撞到自己
	END_NORMAL     //正常退出
};
//蛇身节点
typedef struct SnakeNode {

	short x;
	short y;
	struct SncakeNode* next;
}SnakeNode,* pSnakeNode;

//贪吃蛇
typedef struct Snake {

	pSnakeNode _pSnake;  //指向蛇头的指针
	pSnakeNode _pFood;   //指向食物的指针
	enum DIRECTION _dir; //蛇的方向
	enum GAME_STATUS _status; //游戏状态
	int _food_weight;    //食物分数
	int _score;          //总成绩
	int _sleep_time;
}Snake,* pSnake;

//函数声明

//函数初始化
void GameStart(pSnake snake);

//欢迎界面打印
void WelcomeToGame();

//初始化蛇
void InitSnake(pSnake ps);

//创建食物
void CreateFood(pSnake ps);

//游戏运行
void GameRun(pSnake ps);

int NextIsFood(pSnakeNode pn, pSnake ps);

void SnakeMove(pSnake ps);

void EatFood(pSnakeNode pn, pSnake ps);

void NotFood(pSnakeNode pn, pSnake ps);

void KillByWall(pSnake ps);

void KillBySelf(pSnake ps);

void Game_End(pSnake ps);

 🏝2.实现文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"snake.h"

void SetPos(short x, short y)
{
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(houtput, pos);
}
void WelcomeToGame()
{
	SetPos(35, 13);
	wprintf(L"欢迎来到贪吃蛇小游戏\n");
	SetPos(37, 20);
	system("pause");
	system("cls");

	SetPos(35, 8);wprintf(L"按↑向上移动");
	SetPos(35, 9);wprintf(L"按↓向下移动");
	SetPos(35, 10);wprintf(L"按←向左移动");
	SetPos(35, 11);wprintf(L"按→向右移动");
	SetPos(35, 12);wprintf(L"按F3减速");
	SetPos(35, 13);wprintf(L"按F4加速");
	SetPos(35, 14); wprintf(L"加速可以得到更高的分数");
	SetPos(35, 18);
	system("pause");
	system("cls");

}

CreateMap()
{
	//上
	for (int i = 0; i < 29; i++)
		wprintf(L"%lc", L'□');
	//下
	SetPos(0, 26);
	for (int i = 0; i < 29; i++)
		wprintf(L"%lc", L'□');
	//左
	for (int i = 1; i <=25; i++)
	{
		SetPos(0, i);
		wprintf(L"%lc\n", L'□');
	}
	//右
	for (int i = 1; i <= 25; i++)
	{
		SetPos(56, i);
		wprintf(L"%lc\n", L'□');
	}
}

void InitSnake(pSnake ps)
{
	int i = 0;
	pSnakeNode cur = NULL;
	for (; i < 5; i++)
	{
		cur = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (cur == NULL)
		{
			perror("InitSnake::malloc()");
			return;
		}
		cur->next = NULL;
		cur->x = POS_X + 2 * i;
		cur->y = POS_Y;

		//头插法
		if (ps->_pSnake==NULL)
		{
			ps->_pSnake = cur;
		}
		else
		{
			cur->next = ps->_pSnake;
			ps->_pSnake = cur;
		}
	}

	cur = ps->_pSnake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	ps->_dir = RIGHT;	//默认向右
	ps->_score = 0;
	ps->_status = OK;
	ps->_food_weight = 10;
	ps->_sleep_time = 200;
	//设置贪吃蛇属性
}
void CreateFood(pSnake ps)
{
	int x = 0;
	int y = 0;

	//生成食物的坐标是2的倍数
	//且在方框里面
again:
	do
	{
		x = rand() % 53 + 2;
		y = rand() % 25 + 1;
	} while (x % 2 != 0);

	//x,y的坐标不能和蛇身冲突
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		if (x==cur->x && y==cur->y)
		{
			goto again;
		}
		cur = cur->next;
	}
	//创建食物的节点
	pSnakeNode pFood=(pSnakeNode)malloc(sizeof(SnakeNode));
	if (pFood == NULL)
	{
		perror("CreateFood()::malloc");
		return;
	}
	pFood->x = x;
	pFood->y = y;
	pFood->next = NULL;

	SetPos(x, y);
	wprintf(L"%lc",FOOD );
	ps->_pFood = pFood;
}

void GameStart(pSnake ps)
{
	//0.设置窗口大小,光标影藏
	system("mode con cols=100 lines=30");//设置窗口大小为100列,30行
	system("title 贪吃蛇");  //设置窗口名字为:贪吃蛇
	//影藏光标
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cursor;
	GetConsoleCursorInfo(houtput, &cursor);
	cursor.bVisible = false;
	SetConsoleCursorInfo(houtput, &cursor);

	//1.打印欢迎界面
	//功能介绍
	WelcomeToGame();
	
	//2.绘制地图
	CreateMap();

	//3.创建蛇
	InitSnake(ps);

	//4.创建食物
	CreateFood(ps);

	SetPos(64, 13);
	wprintf(L"0.用↑←→↓控制蛇的移动");
	SetPos(64, 14);
	wprintf(L"1.不能穿墙,不能咬到自己");
	SetPos(64, 15);
	wprintf(L"2.F3减速,F4加速");
	SetPos(64, 16);
	wprintf(L"3.exc退出游戏");
	SetPos(64, 17);
	wprintf(L"4.按空格暂停游戏");

}
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1)?1:0)
void Pause()
{
	while (1)
	{
		Sleep(100);
		if(KEY_PRESS(VK_SPACE))
			break;
	}
}

void EatFood(pSnakeNode pn, pSnake ps)
{
	//头插
	ps->_pFood->next = ps->_pSnake;
	ps->_pSnake = ps->_pFood;
	//释放下一个节点;
	free(pn);
	pn = NULL;
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc\n", BODY);
		cur = cur->next;
	}
	ps->_score += ps->_food_weight;
	CreateFood(ps);
}


void NotFood(pSnakeNode pn, pSnake ps)
{
	pn->next = ps->_pSnake;
	ps->_pSnake = pn;
	pSnakeNode cur = ps->_pSnake;
	pSnakeNode prev = ps->_pSnake;
	while (cur->next)
	{		
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		prev = cur;
		cur = cur->next;
	}
	prev->next = NULL;
	SetPos(cur->x, cur->y);
	wprintf(L"  ");
	free(cur);
	cur = NULL;
}

int NextIsFood(pSnakeNode pn,pSnake ps)
{
	return (pn->x == ps->_pFood->x && pn->y == ps->_pFood->y);
}

void KillByWall(pSnake ps)
{
	if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56
		|| ps->_pSnake->y == 0 || ps->_pSnake->y == 26)
	{
		ps->_status = KILL_BY_WALL;
	}
}

void KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->_pSnake->next;
	while (cur)
	{
		
		if (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y)
		{
			ps->_status = KILL_BY_SLEF;
			break;
		}
		cur=cur->next;
	}
}
void SnakeMove(pSnake ps)
{
	pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pNextNode == NULL)
	{
		perror("SnakeMove()::malloc");
		return;
	}
	switch (ps->_dir)
	{
	case UP:
		pNextNode->x = ps->_pSnake->x;
		pNextNode->y = ps->_pSnake->y - 1;
		break;
	case DOWN:
		pNextNode->x = ps->_pSnake->x;
		pNextNode->y = ps->_pSnake->y + 1;
		break;
	case LEFT:
		pNextNode->x = ps->_pSnake->x-2;
		pNextNode->y = ps->_pSnake->y;
		break;
	case RIGHT:
		pNextNode->x = ps->_pSnake->x+2;
		pNextNode->y = ps->_pSnake->y;
		break;
	}
	if (NextIsFood(pNextNode,ps))
	{
		EatFood(pNextNode,ps);
	}
	else
	{
		NotFood(pNextNode,ps);
	}

	//撞到自己
	KillByWall(ps);

	//撞墙
	KillBySelf(ps);
}

void Game_End(pSnake ps)
{
	SetPos(24, 12);
	switch (ps->_status)
	{
	case KILL_BY_SLEF:
		printf("你撞到了自己,游戏结束\n");
		break;
	case KILL_BY_WALL:
		printf("你撞到墙了,游戏结束\n");
		break;
	case END_NORMAL:
		printf("你主动结束了游戏\n");
		break;
	}
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		pSnakeNode del = cur;
		cur = cur->next;
		free(del);
	}
}
void GameRun(pSnake ps)
{
	//打印帮助信息
	do
	{
		//打印总分数和食物的分值
		SetPos(64, 8);
		wprintf(L"总分数:%3d\n",ps->_score);
		SetPos(64, 9);
		wprintf(L"当前食物分数:%2d",ps->_food_weight);
		if (KEY_PRESS(VK_UP)&&ps->_dir!=DOWN)
		{
			ps->_dir = UP;
		}
		else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
		{
			ps->_dir = DOWN;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
		{
			ps->_dir = LEFT;
		}
		else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT)
		{
			ps->_dir = RIGHT;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			//暂停
			Pause();
		}
		else if (KEY_PRESS(VK_F3))
		{
			//减速
			if (ps->_sleep_time < 320)
			{
				ps->_sleep_time += 30;
				ps->_food_weight -= 2;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			//加速
			if (ps->_sleep_time > 80)
			{
				ps->_sleep_time -= 30;
				ps->_food_weight += 2;
			}
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			//退出
			ps->_status = END_NORMAL;
		}
	//贪吃蛇走一步
	SnakeMove(ps);
	Sleep(ps->_sleep_time);
	} while (ps->_status == OK);
}

🏝3.测试文件 :

#define _CRT_SECURE_NO_WARNINGS 1
#include"snake.h"

//完成的是对游戏的测试
void test()
{
	int ch;
	do
	{
		//创建贪吃蛇
		Snake snake = { 0 };

		//初始化游戏
		GameStart(&snake);

		//运行游戏
		GameRun(&snake);

		//结束游戏—善后工作
		Game_End(&snake);
		SetPos(20, 13);
		printf("游戏结束,再来一局吗?Y/N");
		SetPos(20, 14);
		ch=getchar();
		while(getchar()!='\n');
	} while (ch == 'y' || ch == 'Y');
	SetPos(0, 26);
}
int main()
{
	//设置适配本地环境
	setlocale(LC_ALL, "");
	srand((unsigned int)time(NULL));
	test();
	return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1616228.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32自动光控窗帘程序+Proteus仿真图 H桥L298驱动电机

目录 1、前言 2、仿真图 3、源程序 资料下载地址&#xff1a;STM32自动光控窗帘程序Proteus仿真图 H桥L298驱动电机 1、前言 基于STM32F103设计的智能光控窗帘&#xff0c;包含STM32芯片、光敏电阻、LCD1602显示屏、电机驱动控制模块等。 备注&#xff1a;通过ARM内部的…

网络安全数字孪生:一种新颖的汽车软件解决方案

摘要 随着汽车行业转变为数据驱动的业务&#xff0c;软件在车辆的开发和维护中发挥了核心作用。随着软件数量的增加&#xff0c;相应的网络安全风险、责任和监管也随之增加&#xff0c;传统方法变得不再适用于这类任务。相应的结果是整车厂和供应商都在努力应对汽车软件日益增加…

CAS和synchronized原理

synchronized与CAS Synchronized 原理加锁工作过程一些优化 CAS实现原子类 小结 Synchronized 原理 synchronized 既可以是乐观锁, 也可以是悲观锁.synchronized 既可以是轻量级锁, 也可以是重量级锁.synchronized 重量级锁是由系统的互斥锁实现的; 轻量级锁是基于自旋锁实现的…

Windows 安全中心:页面不可用 你的 IT 管理员已限制对此应用的某些区域的访问,并且你尝试访问的项目不可用。有关详细信息,请与 IT 支持人员联系。

问题 1&#xff1a;Windows 安全中心提示&#xff1a;【页面不可用 你的 IT 管理员已限制对此应用的某些区域的访问&#xff0c;并且你尝试访问的项目不可用。有关详细信息&#xff0c;请与 IT 支持人员联系。】 修复 Microsoft.SecHealthUI 方法 1&#xff1a;命令自动重装安…

linq select 和selectMany的区别

Select 和 SelectMany 都是 LINQ 查询方法&#xff0c;但它们之间有一些区别。 Select 方法用于从集合中选择特定的属性或对集合中的元素进行转换&#xff0c;并返回一个新的集合。例如&#xff1a; var numbers new List<int> { 1, 2, 3, 4, 5 }; var squaredNumbers…

sc2024项目consul

1. 什么是consul HashiCorp Consul是一款服务网络解决方案&#xff0c;可让团队管理服务之间以及内部部署和多云环境及运行时的安全网络连接。consul提供服务发现、服务治理、流量管理和对网络基础设施设备的自动更新。(添加链接描述)Consul使用Go语言开发 2. 功能 多数据中…

【PCL】教程global_hypothesis_verification 通过验证模型假设来实现 3D 对象识别与位姿估计...

测试程序1 milk.pcd milk_cartoon_all_small_clorox.pcd 终端输出1&#xff1a; Model total points: 12575; Selected Keypoints: 193 Scene total points: 307200; Selected Keypoints: 7739 [pcl::SHOTEstimation::computeFeature] The local reference frame is not valid!…

windows驱动开发-内存概述

“90%的程序问题都是由内存引起的&#xff0c;剩下的10%是使用内存引起的&#xff01;”这是一句非常经典的论证&#xff0c;实际上&#xff0c;在程序开发中&#xff0c;内存问题就是最大的问题&#xff0c;没有之一。 现代的计算机体系中&#xff0c;内存承载了太多的功能&a…

解决“该扩展程序未列在 Chrome 网上应用店中,并可能是在您不知情的情况下添加的”的方法

一、问题 安装插件出现时“该扩展程序未列在 Chrome 网上应用店中&#xff0c;并可能是在您不知情的情况下添加的” 二、解决方法 1、把需要安装的第三方插件&#xff0c;后缀.crx 改成 .rar&#xff0c;然后解压&#xff0c;得到一个文件夹 2、再打开chrome://extensions/谷歌…

Visual Studio Code使用

目录 1.python的调试 2.c的运行 方法1&#xff1a; 方法2&#xff1a; 3.c的调试 3.1调试方法一&#xff1a;先生成执行文件&#xff0c;再调试 3.2调试方法二&#xff1a;同时生成执行文件&#xff0c;调试 4.tasks.json 与launch.json文件的参考 4.1C生成执行文件tas…

linux之进程通信

目录 一、进程通信介绍 1.目的 2.发展 3.进程通信是什么&#xff0c;怎么通信&#xff1f; 二、管道 1.介绍 2.匿名管道 1.单向通信管道原理 2.代码实现 3.管道特征 4.管道的四种情况 5.管道的应用场景 使用管道实现一个简易版本的进程池 3.命名管道 1.思考 2.…

燃冬之yum、vim和你

了解了很多指令和权限&#xff0c;搞点真枪实弹来瞅瞅 学Linux不是天天就在那掰扯指令玩&#xff0c;也不是就研究那个权限 准备好迎接Linux相关工具的使用了么码农桑~ yum 软件包 什么是软件包呢&#xff1f; 首先来举个生活中常见点的例子&#xff1a;比如我的手机是华为…

PLC无线通讯技术在汽车喷涂车间机械手臂上的应用

一、项目背景 在汽车生产装配工艺中&#xff0c;机械臂目前已经广泛地应用于装配、搬运等工业生产中&#xff0c;在机械臂系列产品中&#xff0c;汽车喷漆自动控制喷涂机械装置以其独特的优势&#xff0c;能够根据油漆喷涂量的大小&#xff0c;严格控制喷嘴与喷漆面之间距离等…

【函数式接口使用✈️✈️】配合策略模式实现文件处理的案例

目录 &#x1f378;前言 &#x1f37b;一、功能描述 &#x1f37a;二、面向对象设计模式 &#x1f379;三、策略模式 &#x1f366;四、策略 VS 面向对象 &#x1f368;章末 &#x1f378;前言 小伙伴们大家好&#xff0c;上周初步了解了下函数式接口&#xff0c;Consume…

「最没存在感」港姐冠军入行10年不受捧,与相恋4年男友分手

昨日&#xff08;4月21日&#xff09;一众歌手艺人齐集红馆举行《全港运动全城跃动第九届全港运动会开幕礼》录影&#xff0c;TVB亦派出不少的歌手艺人小花表演。其中一部分是邵珮诗与黄婧灵大跳拉丁舞&#xff0c;同属身材丰满的二人跳起上来视觉极夸张。 而平常经常露出姣好身…

powershell@命令行提示符样式配置自定义@pwsh重写prompt显示电量内存时间等信息

文章目录 abstract流行的powershell prompt模块示例 powershell原生修改Prompt函数配置文档Prompt命令来自哪里 简单修改带上电量和时间的Prompt 复杂修改预览FAQ:没有必要修改相关仓库地址样式选择平衡样式花哨样式响应性能 小结 abstract 在 PowerShell 中&#xff0c;可以通…

【git】git ignore如何添加core/config.py忽略

在Git中&#xff0c;.gitignore文件用于指定不被Git追踪的文件和文件夹。要添加core/config.py文件到.gitignore中&#xff0c;你需要编辑.gitignore文件并添加以下行&#xff1a; core/config.py这行表示Git应该忽略名为config.py的文件&#xff0c;它位于core目录下。确保在…

Codeforces Round 821 (Div. 2) D2. Zero-One

题目 #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e5 5, inf 1e18, maxm 4e4 5; const int N 1e6;c…

vue项目前端axios跨域请求处理问题

在我的服务器里面新建了一个txt文档&#xff0c;但在vue项目里面对这个文档发起请求的时候因为是ip地址请求&#xff0c;跨域请求失败&#xff0c;在配置了vue.config.js的请求代理后得以解决 报错示例&#xff1a; 解决方法&#xff1a; 1、在vue.config.js中配置跨越请求代…

microk8s拉取pause镜像卡住

前几天嫌服务器上镜像太多占空间&#xff0c;全部删掉了&#xff0c;今天看到 microk8s 更新了 1.30 版本&#xff0c;果断更新&#xff0c;结果集群跑不起来了。 先通过 microk8s.kubectl get pods --all-namespaces 命令看看 pod 状态。 如上图可以看到&#xff0c;所有的业…