叱咤风云☞贪吃蛇

论初学C时一起做过的那些事

Hello,大家好,今天我们就来说一说,刚入门C语言做过的小游戏,本人小白白一枚,初次发文,望路过的大佬勿喷,有不足指出请与指正(0^0)

01游戏初衷

大家都有玩过贪吃蛇的小游戏,在智能手机还未问世的时候,手持诺基亚黑白手机玩个贪吃蛇、推箱子是多么的不亦乐乎,我们要想写一个贪吃蛇,我们得有一个大概的思路去逐个进行,我们大概的了解了下游戏本身,例如:蛇的身体,怎么让蛇动起来,还得有围墙,让蛇可以吃东西增加自身的长度等等。那么我们知道了大概的思路就差不多知道一个贪吃蛇的游戏是怎么实现的了,就是一个一个的小功能模块组装到一起进行的。
在这里插入图片描述
废话不多说,我们开始实战部分:如下

02代码区

头文件和源文件
这里我为了好区分没有把代码放到一个cpp文件里,那样自己看着看着就会懵逼了,最重要的是一定咬注释,不然到时候自己都看不懂#^ ^#

  • Music.h:内容如下
#pragma once
#include <windows.h>
#pragma comment(lib, "Winmm.lib")//For MCI(Media Control Interface,媒体控制接口)
void Music();
  • Music.cpp:内容如下
#include "Music.h"
void Music()
{
	mciSendString("play E:\\C_project\\Snake\\DZZ.mp3", NULL, 0, NULL);
}

  • 欢迎.h:内容如下
#pragma once
#define 开始游戏 1
#define 加载游戏 2
#define 游戏帮助 3
#define 关于 4
#define 退出游戏 5
void gotoxy(int x, int y);  //定位坐标打印
void Drawing();  //蛇身图形
void Option(); //游戏选项菜单
void Optionone();//游戏选项1
void Optiontwo();//游戏选项2
void Optionthree();//游戏选项3
void Optionfour();//游戏选项4
  • 欢迎.cpp:内容如下
//设置用户欢迎界面和选择
#include <Windows.h>
#include <stdio.h>
#include "全局颜色.h"
#include "欢迎.h"
#include "Music.h"
#include "判断输入.h"
//在某一个坐标的位置上,打印一串字符
void gotoxy(int x, int y)
{
	COORD pos = {x,y};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//这个句柄代表的就是控制台屏幕的输出接口
	SetConsoleCursorPosition(hOut, pos);
}
//显示snake的图画
void Drawing()
{
	Music();
	gotoxy(32, 4);
	color(12);
	printf("_______/");

	gotoxy(31, 4);
	color(2);
	printf("|");

	gotoxy(42, 4);
	color(10);
	printf("\\");

	gotoxy(32, 5);
	color(2);
	printf("\\______ "); //蛇嘴

	gotoxy(43, 5);
	color(10);
	printf("\\");

	gotoxy(34, 1);
	color(6);
	printf("/^\\/^\\"); //蛇眼睛

	gotoxy(34, 2);
	printf("|0_|0_|"); //蛇眼睛

	gotoxy(33, 2);
	color(2);
	printf("_");

	gotoxy(25, 3);
	color(12);
	printf("\\/");//蛇信

	gotoxy(31, 3);
	color(2);
	printf("/");

	gotoxy(37, 3);
	color(6);
	printf("\\_/");//蛇眼睛

	gotoxy(41, 3);
	color(10);
	printf("\\");

	gotoxy(26, 4);
	color(12);
	printf("\\_____");//舌头

	gotoxy(31, 4);
	color(10);
	printf("\\");

	gotoxy(32, 4);
	color(12);
	printf("_________/");

	gotoxy(38, 6);
	color(10);
	printf("&    &");

	gotoxy(37, 7);
	printf("&    &           &^&^&^&^&^&");

	gotoxy(36, 8);
	printf("&    &          &^          ^&");

	gotoxy(35, 9);
	printf("&    &         &^    &^&^&     &             _- * -_ _");

	gotoxy(34, 10);
	printf("&    &         &^   &^     ^&    &          &~         >");

	gotoxy(33, 11);
	printf("&    &^        &^   &^       ^&    &       &~      _ - *");

	gotoxy(33, 12);
	printf("&    &        &^   &^         ^&    &    &~      &~");

	gotoxy(34, 13);
	printf("&    &^&^&^&^    &^           ^&    &^&~      &~");

	gotoxy(35, 14);
	printf("&             &^               &           &~");

	gotoxy(36, 15);
	printf("~&~&~&~&~&~&~                  ~&~&~&~&~&~   ");

	gotoxy(40, 18);
	color(13);
	printf("* * * * * 欢 迎 进 入 游 戏  * * * * *\n");
}
//游戏选择菜单
void Option()
{
	system("mode con cols=100 lines=40");
	printf(" - - - - - - - - - - - - - - - -回-归-经-典-小-游-戏 - - - - - - - - - - - - - - - \n");
	printf("*                                                                                 *\n");
	color(10);
	printf("*                                -----------------                                *\n");
	printf("*                               丨1: 开 始 游 戏 丨                               *\n");
	printf("*                                -----------------                                *\n");
	color(9);
	printf("*                                -----------------                                *\n");
	printf("*                               丨2: 加 载 游 戏 丨                               *\n");
	printf("*                                -----------------                                *\n");
	color(11);
	printf("*                                -----------------                                *\n");
	printf("*                               丨3:游 戏 帮 助 丨                               *\n");
	printf("*                                -----------------                                *\n");
	color(13);
	printf("*                                -----------------                                *\n");
	printf("*                               丨4: 关    于   丨                               *\n");
	printf("*                                -----------------                                *\n");
	color(14);
	printf("*                                -----------------                                *\n");
	printf("*                               丨5:退 出 游 戏 丨                               *\n");
	printf("*                                -----------------                                *\n");
	printf(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - \n");
}
void Optionone()//游戏选项1,开始游戏
{
	Option2();
}
void Optiontwo()//游戏选项2,加载游戏记录
{

}
void Optionthree()//游戏选择3,游戏帮助(操作说明)
{
	system("mode con cols=100 lines=40");
	printf(" - - - - - - - - - - - - - - - -回-归-经-典-小-游-戏 - - - - - - - - - - - - - - - \n");
	printf("*                                                                                 *\n");
	printf("*                                -----------------                                *\n");
	printf("*                               丨3: 游 戏 帮 助 丨                               *\n");
	printf("*                                -----------------                                *\n");
	printf("*                         游戏控制:↑向上,↓向下,←向左,→向右                        *\n");
	printf("*                                                                                 *\n");
	printf("*                                                                                 *\n");
	printf(" - - - - - - - - - - - - - - - - -Version-1.0..1- - - - - - - - - - - - - - - -  - \n");
	system("pause");
	system("cls");
}
void Optionfour() //游戏选项4,关于游戏
{
	system("mode con cols=100 lines=40");
	printf(" - - - - - - - - - - - - - - - -回-归-经-典-小-游-戏 - - - - - - - - - - - - - - - \n");
	printf("*                                                                                 *\n");
	printf("*                                -----------------                                *\n");
	printf("*                               丨4:  关     于  丨                               *\n");
	printf("*                                -----------------                                *\n");
	printf("* 作为全球发行量最大的游戏,贪吃蛇没有如今移动游戏那么炫目,但却长盛不衰,并深得  *\n");
	printf("* 玩家所喜爱,它的成功秘诀其实也很简单。贪吃蛇游戏是一款经典的益智游戏,有PC和手机*\n");
	printf("* 等多平台版本。既简单又耐玩。该游戏通过控制蛇头方向吃果,从而使得蛇变得越来越长。*\n");
	printf(" - - - - - - - - - - - - - - - - -Version-1.0..1- - - - - - - - - - - - - - - -  - \n");
	system("pause");
	system("cls");
}
  • 判断输入.h:内容如下
#pragma once
//声明全部函数//
void Pos(); //设置光标
void creatMap();//创建地图
void initSnake();//创建蛇身
int biteSelf();//判断咬到自己
void createFood();//随机食物
void cantCrossWall();//不能穿墙
void snakeMove();//蛇移动
void pause();//暂停
void runGame();//游戏控制
void initGame();//开始界面
void endGame();//结束游戏
void gameStart();//初始化游戏
void Option2();//整体运行
  • 判断输入.cpp:内容如下
#include<stdio.h>
#include<time.h>
#include<windows.h>
#include<stdlib.h>

#define U 1
#define D 2
#define L 3 
#define R 4       //蛇的状态,U:上 ;D:下;L:左 R:右

typedef struct SNAKE //蛇身的一个节点
{
	int x;
	int y;
	struct SNAKE* next;
}snake;

//全局变量//
int score = 0, add = 10;//总得分与每次吃食物得分。
int status, sleeptime = 200;//每次运行的时间间隔
snake* head, * food;//蛇头指针,食物指针
snake* q;//遍历蛇的时候用到的指针
int endGamestatus = 0; //游戏结束的情况,1:撞到墙;2:咬到自己;3:主动退出游戏。


void Pos(int x, int y)//设置光标位置
{
	COORD pos;
	HANDLE hOutput;
	pos.X = x;
	pos.Y = y;
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄
	SetConsoleCursorPosition(hOutput, pos);
}

void creatMap()//创建地图
{
	int i;
	for (i = 0; i < 58; i += 2)//打印上下边框
	{
		Pos(i, 0);
		printf("■");//一个方块占两个位置
		Pos(i, 26);
		printf("■");
	}
	for (i = 1; i < 26; i++)//打印左右边框
	{
		Pos(0, i);
		printf("■");
		Pos(56, i);
		printf("■");
	}
}

void initSnake()//初始化蛇身
{
	snake* tail;
	int i;
	tail = (snake*)malloc(sizeof(snake));//从蛇尾开始,头插法,以x,y设定开始的位置//
	tail->x = 24;
	tail->y = 5;
	tail->next = NULL;
	for (i = 1; i <= 4; i++)//初始长度为4
	{
		head = (snake*)malloc(sizeof(snake));
		head->next = tail;
		head->x = 24 + 2 * i;
		head->y = 5;
		tail = head;
	}
	while (tail != NULL)//从头到为,输出蛇身
	{
		Pos(tail->x, tail->y);
		printf("■");
		tail = tail->next;
	}
}
//??
int biteSelf()//判断是否咬到了自己
{
	snake* self;
	self = head->next;
	while (self != NULL)
	{
		if (self->x == head->x && self->y == head->y)
		{
			return 1;
		}
		self = self->next;
	}
	return 0;
}

void createFood()//随机出现食物
{
	snake* food_1;
	srand((unsigned)time(NULL));//为了防止每次产生的随机数相同,种子设置为time
	food_1 = (snake*)malloc(sizeof(snake));
	while ((food_1->x % 2) != 0)    //保证其为偶数,使得食物能与蛇头对其
	{
		food_1->x = rand() % 52 + 2;
	}
	food_1->y = rand() % 24 + 1;
	q = head;
	while (q->next == NULL)
	{
		if (q->x == food_1->x && q->y == food_1->y) //判断蛇身是否与食物重合
		{
			free(food_1);
			createFood();
		}
		q = q->next;
	}
	Pos(food_1->x, food_1->y);
	food = food_1;
	printf("■");
}

void endGame()//结束游戏
{

	system("cls");
	Pos(24, 12);
	if (endGamestatus == 1)
	{
		printf("对不起,撞到墙了。游戏结束.");
	}
	else if (endGamestatus == 2)
	{
		printf("对不起,咬到自己了。游戏结束.");
	}
	else if (endGamestatus == 3)
	{
		printf("您的已经结束了游戏。");
	}
	Pos(24, 13);
	printf("您的得分是%d\n", score);
	while (getchar() != 'y')
	{
		printf("输入y退出?[y]");
	}
	exit(0);
}

void cantCrossWall()//不能穿墙
{
	if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)
	{
		endGamestatus = 1;
		endGame();
	}
}

void snakeMove()//蛇前进,上U,下D,左L,右R
{
	snake* nexthead;
	cantCrossWall();

	nexthead = (snake*)malloc(sizeof(snake));
	if (status == U)
	{
		nexthead->x = head->x;
		nexthead->y = head->y - 1;
		if (nexthead->x == food->x && nexthead->y == food->y)//如果下一个有食物//
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                                               //如果没有食物//
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			Pos(q->next->x, q->next->y);
			printf("  ");
			free(q->next);
			q->next = NULL;
		}
	}
	if (status == D)
	{
		nexthead->x = head->x;
		nexthead->y = head->y + 1;
		if (nexthead->x == food->x && nexthead->y == food->y)  //有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                               //没有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			Pos(q->next->x, q->next->y);
			printf("  ");
			free(q->next);
			q->next = NULL;
		}
	}
	if (status == L)
	{
		nexthead->x = head->x - 2;
		nexthead->y = head->y;
		if (nexthead->x == food->x && nexthead->y == food->y)//有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                                //没有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			Pos(q->next->x, q->next->y);
			printf("  ");
			free(q->next);
			q->next = NULL;
		}
	}
	if (status == R)
	{
		nexthead->x = head->x + 2;
		nexthead->y = head->y;
		if (nexthead->x == food->x && nexthead->y == food->y)//有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			score = score + add;
			createFood();
		}
		else                                         //没有食物
		{
			nexthead->next = head;
			head = nexthead;
			q = head;
			while (q->next->next != NULL)
			{
				Pos(q->x, q->y);
				printf("■");
				q = q->next;
			}
			Pos(q->next->x, q->next->y);
			printf("  ");
			free(q->next);
			q->next = NULL;
		}
	}
	if (biteSelf() == 1)       //判断是否会咬到自己
	{
		endGamestatus = 2;
		endGame();
	}
}

void pause()//暂停
{
	while (1)
	{
		Sleep(300);
		if (GetAsyncKeyState(VK_SPACE))
		{
			break;
		}

	}
}

void runGame()//控制游戏        
{

	Pos(64, 15);
	printf("不能穿墙,不能咬到自己\n");
	Pos(64, 16);
	printf("用↑.↓.←.→分别控制蛇的移动.");
	Pos(64, 17);
	printf("F1 为加速,F2 为减速\n");
	Pos(64, 18);
	printf("ESC :退出游戏.space:暂停游戏.");
	Pos(64, 20);
	printf("贪吃蛇研究中心 QQ:934512345");
	status = R;
	while (1)
	{
		Pos(64, 10);
		printf("得分:%d  ", score);
		Pos(64, 11);
		printf("每个食物得分:%d分", add);
		if (GetAsyncKeyState(VK_UP) && status != D)
		{
			status = U;
		}
		else if (GetAsyncKeyState(VK_DOWN) && status != U)
		{
			status = D;
		}
		else if (GetAsyncKeyState(VK_LEFT) && status != R)
		{
			status = L;
		}
		else if (GetAsyncKeyState(VK_RIGHT) && status != L)
		{
			status = R;
		}
		else if (GetAsyncKeyState(VK_SPACE))
		{
			pause();
		}
		else if (GetAsyncKeyState(VK_ESCAPE))
		{
			endGamestatus = 3;
			break;
		}
		else if (GetAsyncKeyState(VK_F1))
		{
			if (sleeptime >= 50)
			{
				sleeptime = sleeptime - 30;
				add = add + 2;
				if (sleeptime == 320)
				{
					add = 2;//防止减到1之后再加回来有错
				}
			}
		}
		else if (GetAsyncKeyState(VK_F2))
		{
			if (sleeptime < 350)
			{
				sleeptime = sleeptime + 30;
				add = add - 2;
				if (sleeptime == 350)
				{
					add = 1;  //保证最低分为1
				}
			}
		}
		Sleep(sleeptime);
		snakeMove();
	}
}

void initGame()//开始界面
{
	Pos(40, 12);

	system("title 贪吃蛇研究中心   QQ:934512345");
	printf("欢迎来到贪食蛇游戏!");
	Pos(40, 25);
	printf("              贪吃蛇研究中心  QQ:934512345\n");
	system("pause");
	system("cls");
	Pos(25, 12);
	printf("用↑.↓.←.→分别控制蛇的移动, F1 为加速,2 为减速\n");
	Pos(25, 13);
	printf("加速将能得到更高的分数。\n");
	system("pause");
	system("cls");
}



void gameStart()//游戏初始化
{
	system("mode con cols=100 lines=30");
	initGame();
	creatMap();
	initSnake();
	createFood();
}

void Option2()  //整体运行
{
	gameStart();
	runGame();
	endGame();
}
  • 全局颜色.h:内容如下
#pragma once
/***********定义全局显示颜色*******************/
void color(const unsigned short color1);
  • 全局颜色.cpp:内容如下
#include <Windows.h>
/***********定义全局显示颜色*******************/
void color(const unsigned short color1)
{
	if (color1 > 0 && color1 <= 15)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color1);
	}
	else
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
	}
}
//对应的颜色码表:
/*
0 = 黑色 8 = 灰色
1 = 蓝色 9 = 淡蓝色
2 = 绿色 10 = 淡绿色
3 = 浅绿色 11 = 淡浅绿色
4 = 红色 12 = 淡红色
5 = 紫色 13 = 淡紫色
6 = 黄色 14 = 淡黄色
7 = 白色 15 = 亮白色
*/

最后功能组装部分snake.cpp

  • snake.cpp:内容如下
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include "Music.h"
#include "欢迎.h"
#include "全局颜色.h"
#include "判断输入.h"
int main(void)
{
	Music();//加载欢迎界面音乐
	Drawing(); //用户欢迎界面Snake图形
	Sleep(2000);
	int CD = 0;//定义一个菜单交互的CD变量
	int TC = 1;//定义一个退出时的变量TC
	while (TC)
	{
		Option(); //菜单选项	
		printf("请输入1-5选项:");
		scanf_s("%d", &CD);

		switch (CD)
		{
		case 开始游戏:Optionone(); break;
		case 加载游戏:Optiontwo(); break;
		case 游戏帮助:Optionthree(); break;
		case 关于:Optionfour(); break;
		case 退出游戏: 
		{
			TC = 0;//把TC变量赋值为0,使得while条件为假终止程序
			printf("更多精彩请关注ASstart    O^O\n");
			system("pause");
			system("cls");			
		}; break;
		default: {printf("输入错误,请重新输入:"); }break;
		}
	}
	return 0;
}

代码部分到此结束(^ ^)

03运行截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其实功能模块2部分还没有完成,就是游戏存档这一块,欢迎各位大佬指正不足之处!!!

注:本文章中部分代码借鉴自他处,如有侵权请联系我删除

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值