用C语言数组编写贪吃蛇
一.制作开始界面
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 x∗2是列。
答:将myArray
数组用坐标表示,y的数就相当于行数,由于方块占两字节,所以x的数等于 x ∗ 2 x\ast2 x∗2
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 x∗2 | 方向 |
---|---|---|
… | ||
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
- 点赞
- 收藏
- 关注作者
评论(0)