贪吃蛇---C语言实现

感想

大一刚放寒假,用了两天时间终于将贪吃蛇写好了。第一次写项目,虽然小了点,但是在这过程中遇到的问题都让我有所收获。

实现

贪吃蛇各函数关系图。如下图:

有了各功能关系图之后就可以开工写代码了。

写代码过程中遇到最多的问题,还是编译器的问题。最开始使用dev c++编译源代码,代码不多时,编译器工作还没什么问题。代码多了之后,编译器直接将我写好的源代码打乱了。大概是原先在函数体中的代码都跑到函数体外边。函数就剩下一个完整函数体。还有出现一些奇怪的括号,夹杂在代码中间。经过漫长的修改和重写代码。《这次备份了一份》。第一次无法过编译。第二次竟然过了。前后两次无任何代码改动。于是将代码移到vs2015上运行,出现如下错误:

几经寻求解决之法不得之后,毅然放弃vs2015,转到eclipse平台。幸好,eclipse c++可用。

----------------------------------------------------------------------------------------------------------------------------------

代码实现思路:

不得不提这个思路借鉴了别人的想法,二维数组----游戏界面。
二维数组通过四个数字来分辨、墙、食物、蛇,对应为0、1、2、3.
游戏界面,就按照二维数组中的数字输出对应的字符即可。<这很简陋-->
代码
/*
 ============================================================================
 Name        : 0.c
 Author      : 陈致和
 Version     :
 Copyright   : 学习之用
 Description : Snake in C, Ansi-style
 ============================================================================
 */


#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>

/*全局变量*/
int flag = 1;//在初始位置绘制贪吃蛇的状态标志
int MapAndSnake[25][25] = { 0 };/*存储地图边界、贪吃蛇、食物----清零
								0代表空
								1代表地图元素
								2代表食物
								3代表贪吃蛇
								例如:0000
								0000
								0000
								0000

								1111
								1201
								1331
								1111*/
int x = 0, y = 0;//食物坐标
char direction = 'D';//初始--向右
const	int nVirtKeyA = 65;/*A*/
const	int nVirtKeyD = 68;
const	int nVirtKeyS = 83;
const	int nVirtKeyW = 87;
int headX,
	headY;//当前蛇头所在位置
int tailX,
	tailY;//当前蛇尾所在位置
int steeringKeyX,
	steeringKeyY;//转向标记点
int score;//分数
//time_t time;//存活时间
int snakeLength = 2;//初始长度为2
//time_t starttime

/*函数预申明*/
void createFood();
void iniMap(int x, int y);
void gamestart();
void reVector(int x, int y);
void reScore();
void exitGame();
DWORD WINAPI checkDirection(void *lpParameter);
void checkCollide();

/*函数区*/
void printfmun() {
	int i, j;
	for (i = 0; i<25; i++)
	{
		for (j = 0; j<25; j++)
			printf("%d ", MapAndSnake[i][j]);
		printf("
");
	}
}

void reScore() {
	//time_t nowtime;
	//time(&nowtime);
	//time=nowtime-starttime;
	score=snakeLength*10;
	printf("当前分数为:%d
",score);
	//printf("你当前存活时间为: %d秒
",time);
	printf("贪吃蛇长度:%d
",snakeLength);
}
void exitGame() {
	printf("Game Over !");
	exit(0);
}
DWORD WINAPI checkDirection(void *lpParameter) {//按键检测函数*

			int key;
			key=getch();
			while(1){
			key=getch();
			if(key==nVirtKeyA)
			direction=(char)key;
			else if(key==nVirtKeyD)
			direction=(char)key;
			else if(key==nVirtKeyS)
			direction=(char)key;
			else if(key==nVirtKeyW)
			direction=(char)key;
				}


	 }
 void checkCollide(){
	if(x==headX && y==headY)//蛇头与食物正常碰撞
	{
		snakeLength++;

		switch(direction){
			case 'A':{
				MapAndSnake[x][y-1]=3;
				headY--;
				break;
			}
			case 'D':{
				MapAndSnake[x][y+1]=3;
				headY++;
				break;
			}
			case 'S':{
				MapAndSnake[x+1][y]=3;
				headX++;
				break;
			}
			case 'W':{
				MapAndSnake[x-1][y]=3;
				headX--;
				break;
			}
		}
		createFood();
	}


}
void reVector(int x,int y){
				int time=200;//更新时间
							//更新二维数组值


					/*方向键*/
			  switch(direction){
						/*左右*/
						case 'A':{
							steeringKeyX=headX;steeringKeyY=headY;
							if(tailX>steeringKeyX){
								MapAndSnake[headX][headY-1]=3;
								headY--;
								MapAndSnake[tailX][tailY]=0;
								tailX--;
							}
							else if(tailX<steeringKeyX){
								MapAndSnake[headX][headY-1]=3;
								headY--;
								MapAndSnake[tailX][tailY]=0;
								tailX++;
							}
							else if(tailX==steeringKeyX){
								MapAndSnake[headX][headY-1]=3;
								headY--;
								MapAndSnake[tailX][tailY]=0;
								tailY--;
							}
							break;
						}
						case 'D':{
							steeringKeyX=headX;steeringKeyY=headY;
							if(tailX>steeringKeyX){
								MapAndSnake[headX][headY+1]=3;
								headY++;
								MapAndSnake[tailX][tailY]=0;
								tailX--;
							}
							else if(tailX<steeringKeyX){
								MapAndSnake[headX][headY+1]=3;
								headY++;
								MapAndSnake[tailX][tailY]=0;
								tailX++;
							}
							else if(tailX==steeringKeyX){
								MapAndSnake[headX][headY+1]=3;
								headY++;
								MapAndSnake[tailX][tailY]=0;
								tailY++;
							}
							break;
						}

						/*上下*/
						case 'S':{
							steeringKeyX=headX;steeringKeyY=headY;
							if(tailY>steeringKeyY){
								MapAndSnake[headX+1][headY]=3;
								headX++;
								MapAndSnake[tailX][tailY]=0;
								tailY--;
							}
							else if(tailY<steeringKeyY){
								MapAndSnake[headX+1][headY]=3;
								headX++;
								MapAndSnake[tailX][tailY]=0;
								tailY++;
							}
							else if(tailY==steeringKeyY){
								MapAndSnake[headX+1][headY]=3;
								headX++;
								MapAndSnake[tailX][tailY]=0;
								tailX++;
							}
							break;
						}
						case 'W':{
							steeringKeyX=headX;steeringKeyY=headY;
							if(tailY>steeringKeyY){
								MapAndSnake[headX-1][headY]=3;
								headX--;
								MapAndSnake[tailX][tailY]=0;
								tailY--;
							}
							else if(tailY<steeringKeyY){
								MapAndSnake[headX-1][headY]=3;
								headX--;
								MapAndSnake[tailX][tailY]=0;
								tailY++;
							}
							else if(tailY==steeringKeyY){
								MapAndSnake[headX-1][headY]=3;
								headX--;
								MapAndSnake[tailX][tailY]=0;
								tailX--;
							}
							break;
						}
					}

					checkCollide();
					if(x!=0 && y!=0)//食物坐标不为零时刷新食物
					{
						MapAndSnake[x][y]=2;
					}
					 if(headY==24||headX==24||headX==0||headY==0)
						exitGame();
					Sleep(time);

					system("cls");//
					//printfmun();
					gamestart();
 }

void createFood() {
													 /*随机产生食物坐标*/
int high = 23, low = 1;
srand(time(NULL));
x = rand() % (high - low + 1) + low;
y = rand() % (high - low + 1) + low;
	if(flag==1){
		iniMap(x, y);
		flag=0;
	}
	else
	reVector(x,y);

}
void iniMap(int x, int y) {


	//time(&starttime);
	/*初始化二维数组*/
	int i, j;
	for (i = 0; i<25; i++)
		for (j = 0; j<25; j++)
		{
			if (i == 0 || i == 24)
				MapAndSnake[i][j] = 1;
			else if (i>0 && i<25)
				if (j == 0 || j == 24)
					MapAndSnake[i][j] = 1;/*填充地图边界*/
				else if (x == i && y == j)
					MapAndSnake[x][y] = 2;/*填入食物*/
				else if (i == 23)
					if (j == 2 || j == 3)
						MapAndSnake[i][j] = 3;
		}
	headX = 23; headY = 3;//初始条件下蛇头位置
	tailX = 23; tailY = 2;//初始条件下蛇尾位置
}





void gamestart() {//绘制地图、食物、贪吃?

	int i, j;
	for (i = 0; i<25; i++)
	{
		for (j = 0; j<25; j++)
		{
			if (MapAndSnake[i][j] == 1 ||
				MapAndSnake[i][j] == 2 ||
				MapAndSnake[i][j] == 3)
				printf("■");
			else
				printf("  ");
		}
		printf("
");
	}
	reScore();
	//printfmun();
	reVector(x, y);
}

int main() {

	/**键盘按键检测线程*/
	DWORD ThreadId;
	HANDLE threadOne;
	INT parameter;
	threadOne = CreateThread(NULL,
					0,
					checkDirection,
					¶meter,
						0,
					&ThreadId);
	/**/
	createFood();
	gamestart();
	getchar();
	return 0;
}

理想效果
主要是代码写得太渣,导致蛇连续转弯会断了身子。大概这个意思


操作键需要大写键盘锁定----然后W A S D

接下来打算实现一个GUI版贪吃蛇,设置难度系数,优化那些渣代码,实现贪吃蛇自己找食物的功能。

原文地址:https://www.cnblogs.com/deciduousmap/p/12193731.html