用C语言数组编写贪吃蛇

举报
神的孩子在歌唱 发表于 2021/06/10 00:54:04 2021/06/10
【摘要】 以下是观看B站up主后整理的笔记,点击进入老师的视频 贪吃蛇游戏制作过程 源码https://github.com/Rodma1/test.git 一.制作开始界面二.制作音乐播放器三.制作空格进入游戏界面四.制作关闭音乐五.制作游戏界面六.制作蛇身位置七.制作蛇身八.制作蛇跑九.制作消去蛇尾十.制作按键移动方向十一.蛇死亡十二.食物生成十三.蛇长大十四.设置...

以下是观看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");
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

二.制作音乐播放器

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

#include<mmsystem.h>//音频头文件
#pragma comment(lib, "WINMM.LIB")//音频必加

  
 
  • 1
  • 2
void myPlaySound()
{
	PlaySound("1.wav", NULL, SND_FILENAME | SND_ASYNC);
}

  
 
  • 1
  • 2
  • 3
  • 4

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

#include<conio.h>//_getch头文件

  
 
  • 1
void _space()
{
	while (1)
	{
		char charSpace;
		charSpace = _getch();//输入自动读进charSpace
		if (' ' == charSpace)
		{ break;
		}
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

四.制作关闭音乐

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

  
 
  • 1
  • 2
  • 3
  • 4

五.制作游戏界面

(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" };

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

(2)在源文件输出

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

六.制作蛇身位置

(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]的数组

y x*2 enum 蛇头
y x*2+2 enum 蛇身
y x*2+4 enum 蛇尾

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();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

七.制作蛇身

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不安全,得加上

  
 
  • 1
//蛇身
void set_snake()
{
	for (int i = 0; arraySnake[i][0] != 0; i++)
	{
		strncpy(&myArray[arraySnake[i][0]][arraySnake[i][1]], "◆",2 );//拷贝
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

八.制作蛇跑

解释:因为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();
	
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

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

刚开始

蛇头
蛇身
蛇尾

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);//空两格,因为正方体是占两个节点
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

十.制作按键移动方向

知识点: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;
		}
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

十一.蛇死亡

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;

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

十二.食物生成

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;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

十三.蛇长大

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++;
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

十四.设置分数

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);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

十五.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;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

十六.运行结果

在这里插入图片描述

文章来源: chenyunzhi.blog.csdn.net,作者:神的孩子都在歌唱,版权归原作者所有,如需转载,请联系作者。

原文链接:chenyunzhi.blog.csdn.net/article/details/105131476

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。