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语言中怎样实现对二维数组元素进行赋值并输出。

C语言实现一个可变长的二维数组

c语言的杨辉三角程序

c语言,用二维数组解决迷宫问题。来段完整的代码吧。

C语言中二维数组行指针是啥

C语言基础项目:200 行代码实现贪吃蛇,思路+源码详解