用C语言数组编写贪吃蛇

以下是观看B站up主后整理的笔记,点击进入老师的视频

一.制作开始界面

void one_interface() {
	printf("\n\n\n");
	printf("\t\t\t\t\t\t--------------------\n");
	printf("\n");
	printf("\t\t\t\t\t\t欢迎来到贪吃蛇游戏\n");
	printf("\n");
	printf("\t\t\t\t\t\t请按下空格进入游戏\n");
	printf("\n");
	printf("   \t\t\t\t\t      根据 w a s d方向键控制\n");
	printf("--------------------------------------------------------------------------------------------------------------\n");
}

二.制作音乐播放器

注:音频必须时wav,且要和可执行程序放在一起在这里插入图片描述

#include<mmsystem.h>//音频头文件
#pragma comment(lib, "WINMM.LIB")//音频必加
void myPlaySound()
{
	PlaySound("1.wav", NULL, SND_FILENAME | SND_ASYNC);
}

三.制作空格进入游戏界面

#include<conio.h>//_getch头文件
void _space()
{
	while (1)
	{
		char charSpace;
		charSpace = _getch();//输入自动读进charSpace
		if (' ' == charSpace)
		{
			break;
		}
	}
}

四.制作关闭音乐

void stop_MyPlaySound()
{ 
	PlaySound( NULL,0,0);
}

五.制作游戏界面

(1)另取一个头文件head.h:将数组myArray[20][42]放进去,然后在源文件里获取头文件#include"head.h"

char myArray[20][42] = { "■■■■■■■■■■■■■■■■■■■■\n",//一个■占用两字节
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■                                    ■\n",
							 "■■■■■■■■■■■■■■■■■■■■\n" };

(2)在源文件输出

void two_interface()
{
	int i = 0;
		for (i = 0;i < 20; i++)
		{
			printf(myArray[i]);
		}
}

六.制作蛇身位置

(1)定义坐标(2)定义方向 enum { East = 2, South = 1, West = -2, North =- 1 };//枚举方向
疑惑点:为什么y是行, x ∗ 2 x\ast2 x2是列。
答:将myArray数组用坐标表示,y的数就相当于行数,由于方块占两字节,所以x的数等于 x ∗ 2 x\ast2 x2
ArraySnake[20][3]的数组

yx*2enum蛇头
yx*2+2enum蛇身
yx*2+4enum蛇尾

head.h中定义int arraySnake[x_pos][3] = { 0 };

//蛇的坐标
void set_snakePos()
{
	int x=-1,y=-1;//设置坐标
	srand((unsigned int)time (NULL));//获得随机数
	x = rand() % 14+3;
	y = rand() % 14+3;
	//设置🐍的数组
	arraySnake[0][0] = y;//行
	arraySnake[0][1] = x*2;//列
	arraySnake[0][2] = West;
	//蛇头
	arraySnake[1][0] = y;
	arraySnake[1][1] = x*2+2;
	arraySnake[1][2] = West;
	//蛇身
	arraySnake[2][0] = y;
	arraySnake[2][1] = x*2+4;
	arraySnake[2][2] = West;
	//蛇尾
	set_snake();
}

七.制作蛇身

myArray[20][42]数组

myArray[y][x*2]myArray[y][x*2+4]myArray[y][x*2+6]
y行x*2列y行x*2+4列y行x*2+6列

通过数组形成一条这样子的蛇:◆◆◆

#pragma warning (disable : 4996)//strncpy不安全,得加上
//蛇身
void set_snake()
{
	for (int i = 0; arraySnake[i][0] != 0; i++)
	{
		strncpy(&myArray[arraySnake[i][0]][arraySnake[i][1]], "◆",2 );//拷贝
	}
}

八.制作蛇跑

解释:因为x_pos值二十,所以只能取0~19的下标,然后从第19个数开始遍历,等到获取有效数字就向前移动,否则过滤掉。

y x ∗ 2 x*2 x2方向
19

head.h中定义int snakeDir = West;

void set_snakeRun()
{
	int i = x_pos - 1;
	set_direction();
	delete_ophiurid();//删除原来的蛇
	
	for (i;i>=1;i--)
	{
		//过滤掉非法🐍
		if (0 == arraySnake[i][1])
		{
			continue;
		}
		//把前一个结点的值,赋值给当前结点
		arraySnake[i][0] = arraySnake[i-1][0];//行
		arraySnake[i][1] = arraySnake[i-1][1];//列
		arraySnake[i][2] = arraySnake[i-1][2];//方向
	}
	//初始向西移动
	arraySnake[0][2] = snakeDir;
	if (West== arraySnake[0][2]||East== arraySnake[0][2])
	{
		arraySnake[0][1] += arraySnake[0][2];//列加二或减二
	}
	else
	{
		arraySnake[0][0] += arraySnake[0][2];//行加二或减二
	}
	set_snake();
	
}

解析:
   原本蛇是◆◆◆这样子的,然后蛇头向前移两字节,原来蛇头不变,蛇身变成蛇头,蛇尾不变(如果设置拷贝的蛇头是‘’█‘’,那么蛇出来是█ █ █ ◆)

刚开始

蛇头
蛇身
蛇尾

arraySnake数组移动下标后:
解析:就相当域蛇身获取了蛇头元素,蛇尾获取了蛇身的元素

蛇头
蛇头
蛇身
蛇尾

坐标加2,myArray 数组移动后
然后放到main函数里面while(1)循环,坐标x一直加2,蛇头一直向前

蛇头
蛇头
蛇头
蛇身

九.制作消去蛇尾

注意:先消去蛇尾在跑set_snakeRun()
原因:把旧蛇换成空格,那么画新蛇的时候就刚好吧原来蛇头蛇身的位置覆盖掉,消去蛇尾

//消除尾节点
void delete_ophiurid()
{
	for (int i = 0; arraySnake[i][0] != 0; i++)
	{
		strncpy(&myArray[arraySnake[i][0]][arraySnake[i][1]], "  ", 2);//空两格,因为正方体是占两个节点
	}
}

十.制作按键移动方向

知识点:short 两字节,高字节0000 0010(可以一直按返回!0),低字节 0000 0001(只要按一下就一直返回1)
先在head.h里设置一个全局变量snakeDir=East;
然后在第八步骤设置方向那里设置snakeDir=arraySnake[0][2].

void set_direction()
{
	//_getch同步检测:必须得输入才能运行,每次循环都得输入
	if (GetAsyncKeyState('W'))//异步检测:如果输入字母就改变阿,不输入就跳过这个函数🐍继续动
	{
		if (South != arraySnake[0][2])//如果蛇头不向南移动,才可以点击s键向北,否则无效
		{
			snakeDir = North;
		}
	}
	else if (GetAsyncKeyState('A'))
	{
		if (East != arraySnake[0][2])
		{
			snakeDir = West;
		}
	}
	else if (GetAsyncKeyState('S'))
	{
		if (North != arraySnake[0][2])
		{
			snakeDir = South;
		}
	}
	else if (GetAsyncKeyState('D'))
	{
		if (West != arraySnake[0][2])
		{
			snakeDir = East;
		}
	}
}

十一.蛇死亡

head.h中定义#define true 1 #define false 0

bool set_snakeDead()
{
	
	if (East == arraySnake[0][2] || West == arraySnake[0][2])
	{
		if ( 0 == strncmp(&myArray[arraySnake[0][0]][arraySnake[0][1] + arraySnake[0][2]], "■", 2))
		{
			return false;
		}
		else if(0 == strncmp(&myArray[arraySnake[0][0] + arraySnake[0][2]][arraySnake[0][1]], "◆", 2))
		{
			return false;
		}
	}
	else
	{
		if ( 0 == strncmp(&myArray[arraySnake[0][0] + arraySnake[0][2]][arraySnake[0][1]], "■", 2))
		{
			return false;
		}
		else if (0 == strncmp(&myArray[arraySnake[0][0] + arraySnake[0][2]][arraySnake[0][1]], "◆", 2) )
		{
			return false;
		}
	}
	return true;

}

十二.食物生成

head.h中定义#define x_pos 20 int g_Nx ,g_Ny ; typedef int bool;//定义bool类型的变量 bool g_proFood = true;

void set_snakeFood()
{
	//如果有食物就返回,没有点添加食物
	if (false == g_proFood)
	{
		return ;
	}
	//设置坐标
	srand((unsigned int)time(NULL));//获得随机数
	g_Nx = rand() % 16 +2;
	g_Ny = rand() % 16 + 2;
	bool a_pos = true;
	while (1)
	{
		for (int i = 0; arraySnake[i][0] != 0; i++)
		{
			if (g_Nx * 2 == arraySnake[i][1] &&g_Ny == arraySnake[i][0])
			{
				a_pos = false;
			}
		}
		if (true == a_pos)
		{
			break;
		}
	}
	strncpy(&myArray[g_Ny][g_Nx*2], "●", 2);//不要忘记乘二,卡在这里好久了
	//添加食物后变成false
	g_proFood = false;
}

十三.蛇长大

head.h中定义蛇长大的成员变量int g_x = 2;

void set_snakeUp()
{
	
	//如果蛇头和食物坐标相同1。蛇增长
	if (g_Nx*2 == arraySnake[0][1] && g_Ny == arraySnake[0][0])
	{
		//蛇长大
		/*不明白的地方:为什么arraySnake[g_x][0];
							  arraySnake[g_x][0]-2;
							  arraySnake[g_x][0];这也能编译出来*/
		if (East==arraySnake[g_x][2])
		{
			arraySnake[g_x+1][0] = arraySnake[g_x][0];//行
			arraySnake[g_x+1][1] = arraySnake[g_x][1]-2;//列
			arraySnake[g_x+1][2] = arraySnake[g_x][2];//方向
		}
		else if (West == arraySnake[g_x][2])
		{
			arraySnake[g_x + 1][0] = arraySnake[g_x][0];//行
			arraySnake[g_x + 1][1] = arraySnake[g_x][1] + 2;//列
			arraySnake[g_x + 1][2] = arraySnake[g_x][2];//方向
		}
		else if (South == arraySnake[g_x][2])
		{
			arraySnake[g_x + 1][0] = arraySnake[g_x][0]+1;//行
			arraySnake[g_x + 1][1] = arraySnake[g_x][1];//列
			arraySnake[g_x + 1][2] = arraySnake[g_x][2];//方向
		}
		else if (North == arraySnake[g_x][2])
		{
			arraySnake[g_x + 1][0] = arraySnake[g_x][0]-1;//行
			arraySnake[g_x + 1][1] = arraySnake[g_x][1] ;//列
			arraySnake[g_x + 1][2] = arraySnake[g_x][2];//方向
		}
		g_x++;
		//如果蛇吃了食物就没有食物了,返回true给set_snakeFood()添加食物
		g_proFood = true;
		g_score++;
	}
}

十四.设置分数

head.h中定义分数变量int g_score = 0;

void set_score()
{
	COORD rd;
	rd.X = 45;
	rd.Y = 2;
	//设置位置
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),rd);
	//打印
	printf("score\n");
	rd.X = 47;
	rd.Y = 4;
	//设置位置
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);
	//打印
	printf("%d\n",g_score);
}

十五.main函数运行

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>//_getch头文件
#include <time.h>//获取时间数函数
#include"head.h"
#include<windows.h>//定义局部变量
#include<mmsystem.h>//音频头文件
#pragma comment(lib, "WINMM.LIB")//音频必加
#pragma warning (disable : 4996)//strncpy不安全,得加上
int main(void)
{
	one_interface();//初始界面
	myPlaySound();//音频
	_space();//点击空格键进入游戏界面
	system("cls");//清屏
	printf("\t\t\t\t\t\t欢迎进入游戏\n");
	Sleep(2000);
	stop_MyPlaySound();// 先消去再跑,顺序不能乱
	set_snakePos();//这个函数必须放在界面上面才能显示
	
	while (1)
	{
		system("cls");
		
		set_snakeFood();//产生食物
		set_snakeUp();//蛇变长
		if (false == set_snakeDead())//蛇死亡
		{
			printf("snake dead");
			break;
		}
		set_snakeRun();//蛇跑
		two_interface();//游戏界面
		set_score();//得分
		Sleep(500);
		
	}
	system("pause");
	return 0;
}

十六.运行结果

在这里插入图片描述

©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页