C语言初学者项目 200行代码用一个二维数组实现贪吃蛇游戏
Posted XXP_s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言初学者项目 200行代码用一个二维数组实现贪吃蛇游戏相关的知识,希望对你有一定的参考价值。
s
本文章面向c语言初学者,所以我尽可能用最基本的语法实现整个游戏,并且只用到一个二维数组实现,下面将详细讲解实现过程。
一个二维数组可以直接打印成一个平面,就形成了整个游戏的背景,我们可以通过改变数组的内容来控制蛇的移动,食物的生成等。
先建立整个游戏框架
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#define ROW 10//行数
#define COL 25//列数
#define SPEED 100//这里其实是刷新率,所以越低蛇速度越快,后边会引用到
int a[ROW][COL];
int main(void)
char play;
do
game();
printf("1:continue\\n");
printf("2:exit\\n");
play = getch();
while (play=='1');
printf("exit\\n");
return 0;
s
将二维数组建立为全局变量,使数组所有的数都初始化为0。之后可以用数组中不同的数字代表不同的事物,比如我们将数组的边框初始化为-2,-2就代表了墙
for (int i = 0; i < ROW; i++)//生成墙壁
for (int j = 0; j < COL; j++)
if (i == 0 || j == 0 || i == ROW - 1 || j == COL - 1)
a[i][j] = -2;
蛇的数字处理很重要,这涉及到蛇的移动问题,蛇的移动实际上可以理解为将尾巴那一块转移到将要移动的前方去,如果蛇要向上移动,就是把尾巴那一块转移到头的上边,同理向右移动即把尾巴移动到头的右边,理解了这个移动方式,就可以对蛇在数组中的值进行创建了,令头的值为1,之后身体块就是2,3、、、直到尾巴那个值,我们初始化蛇有三节,所以尾巴数为3(当然你也可以初始化其他的值)。
a[ROW-2][1] = 3;//生成蛇
a[ROW-2][2] = 2;//生成蛇
a[ROW-2][3] = 1;//生成蛇头
int tailmax = 3;//蛇长,之后蛇的变长要靠这个值
食物生成比较简单,取随机数在数组的范围内,如果是不恰当的位置就重新设置,设置食物的值为-1
void toeat(int a[ROW][COL])//生成食物
while (1)
int x = rand() % ROW;
int y = rand() % COL;
if (x != 0 && y != 0/*不能在边界上*/ && a[x][y] == 0/*只能在空的区域生成*/)
a[x][y] = -1;
break;
s
现在数组的基本处理完成,数组内一共有4种值 ,一种是-2,表示墙,一种是-1,表示食物,一种是0,表示空白区域,剩下的正数全都代表蛇,蛇头是1,那么就可以编写打印函数
void print(int a[ROW][COL])//打印
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if ((i == 0 || i == ROW - 1) && j != 0 && j != COL - 1)//上下边界
printf("-");
else if ((j == 0 || j == COL - 1) && i != 0 && i != ROW - 1)//左右边界
printf("|");
else if ((i == 0 || i == ROW - 1) && (j == 0 || j == COL - 1))//四个角
printf("+");
else if (a[i][j] == 0)//空白区域
printf(" ");
else if (a[i][j] == 1)//蛇头,我用字母‘O’表示
printf("O");
else if (a[i][j] == -1)//食物
printf("$");
else
printf("*");//剩下的都是正数,是蛇身
printf("\\n");
前三个if选择式可能有点吓人,因为我想建立一个(稍微)好看的边界,如果你嫌麻烦,可以直接让边界都是一个字符,如下
void print(int a[ROW][COL])//打印
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if(a[i][j]==-2)
printf("*");
else if (a[i][j] == 0)
printf(" ");
else if (a[i][j] == 1)
printf("O");
else if (a[i][j] == -1)
printf("$");
else
printf("*");
printf("\\n");
这些都处理好后,就可以进行蛇的移动操作了,我们习惯用wsad表示上下左右(不是)。首先思考,如何表示一只蛇向上移动一次呢?
从前文我们知道只要找到头尾坐标,将尾巴放到头上方就可以,但是蛇是一串连续的数字,在数组中必须要经过数据处理才能进行,得到头尾坐标后,我们可以先让尾巴消失,即坐标设置为0,然后把包括蛇头在内的蛇本体数字全部加1,这样原来蛇头的数字变成了2,现在没有蛇头,我们就可以把原来蛇头上面的数(如果头是a[i][j],头上面就是a[i-1][j])设置为1,新的蛇头就生成了,而且蛇新的尾巴的值没有改变,这样我们简单实现了蛇向上移动一格这个操作,转换为代码如下
int handx, handy;//蛇头坐标
int tailx, taily;//蛇尾坐标
for(int i=0;i<ROW;i++)
for(int j=0;j<COL;j++)
if (a[i][j] == 1)
handx = i;
handy = j;
//找到头坐标
for(int i=0;i<ROW;i++)
for(int j=0;j<COL;j++)
if (a[i][j] == tailmax)
tailx = i;
taily = j;
//找到尾坐标,这里就用到了之前的tailmax
if (a[handx - 1][handy] == 0)//判断前方是空白可行走
a[tailx][taily] = 0;//蛇尾设为0
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2)//排除墙壁、食物、空白
a[i][j]++;//蛇的身体和头都加1
a[handx - 1][handy] = 1;//设置新蛇头
运用这个逻辑,我们可以很容易实现吃食物这个过程,如果前进方向的值是-1即食物,就将整个蛇连头带尾所有值加1,然后把食物的值设为1,形成新的蛇头
else if (a[handx - 1][handy] == -1)//判断食物
for (int i = 0;i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2&&a[i][j]!=-5)
a[i][j]++;
a[handx - 1][handy] = 1;
tailmax++;//蛇变长了,所以尾巴的值要加1
toeat(a);.//生成一个新的食物
蛇的前方除了是空白和食物外就是墙和蛇身,如果继续前进就会游戏结束
else
gameover = 1;//之后用到
我们已经可以实现一次移动,稍微修改二维数组的参数就可以实现四个方向的移动,但是蛇的移动是一个连续的过程,我们应该用循环实现连续移动,但单纯的循环是非常快的,所以蛇会飞快移动,为了避免这种情况,我们要用到windows.h里边的Sleep函数即Sleep(m),m的值为停顿的毫秒,我们将之前定义的SPEED调用上去,Sleep(SPEED)就能控制蛇移动的速度。
另外,因为蛇一直在移动,程序一直在运行,我们要控制蛇必须要输入wsad的指令,不可能蛇动一次就输入一次,太麻烦,所以我们要学习一个新函数_kbhit(),它判断你的键盘有没有输入,没有就返回0,有就返回一个非0值。把他放在每次循环移动的后边,再用getch不回显直接读取输入的值,就可以操作蛇。
一次完整的移动如下
while(1)
if(move=='w')//以向上移动为例
if (a[handx - 1][handy] == 0)//判断可行走
a[tailx][taily] = 0;
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2)
a[i][j]++;
a[handx - 1][handy] = 1;
else if (a[handx - 1][handy] == -1)//判断食物
for (int i = 0;i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2&&a[i][j]!=-5)
a[i][j]++;
a[handx - 1][handy] = 1;
tailmax++;
toeat(a);
else gameover = 1;//判断游戏失败
break;
system("cls");//清除之前的屏幕
print(a);//打印新的局面,这样刷新基本实现的蛇的动态过程
Sleep(SPEED);//停一下
if (_kbhit())//判断是否有输入,没有直接跳过
char cao = getch();//用另一个变量来接受,避免接受到wsad以外的垃圾值
if (cao == 'w' || cao == 's' || cao == 'a' || cao == 'd')
move = cao;
因为要判断四个移动方向,我们用在while循环内部用switch语句来判断move的值决定移动的方向,
同时设置一个值int gameover=1来判断游戏是否结束。具体代码如下
while (!gameover)
for(int i=0;i<ROW;i++)
for(int j=0;j<COL;j++)
if (a[i][j] == 1)
handx = i;
handy = j;
//找到头坐标
for(int i=0;i<ROW;i++)
for(int j=0;j<COL;j++)
if (a[i][j] == tailmax)
tailx = i;
taily = j;
//找到尾坐标
switch (move)
case'w':
if (a[handx - 1][handy] == 0)//判断可行走
a[tailx][taily] = 0;
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2)
a[i][j]++;
a[handx - 1][handy] = 1;
else if (a[handx - 1][handy] == -1)//判断食物
for (int i = 0;i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2&&a[i][j]!=-5)
a[i][j]++;
a[handx - 1][handy] = 1;
tailmax++;
toeat(a);
else gameover = 1;
break;
case's':
if (a[handx + 1][handy] == 0)
a[tailx][taily] = 0;
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2 && a[i][j] != -5)
a[i][j]++;
a[handx + 1][handy] = 1;
else if (a[handx + 1][handy] == -1)
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i][j] != 0 && a[i][j] != -1 && a[i][j] != -2 && a[i][j] != -5)
a[i][j]++;
a[handx + 1][handy] = 1;
tailmax++;
toeat(a);
else gameover = 1;
break;
case'a':
if (a[handx][handy-1] == 0)
a[tailx][taily] = 0;
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
if (a[i]c语言中怎样实现对二维数组元素进行赋值并输出。