欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

贪吃蛇---C语言实现

程序员文章站 2024-03-19 08:50:58
...

感想

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

实现

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

贪吃蛇---C语言实现

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

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

贪吃蛇---C语言实现

几经寻求解决之法不得之后,毅然放弃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("\n");
	}
}

void reScore() {
	//time_t nowtime;
	//time(&nowtime);
	//time=nowtime-starttime;
	score=snakeLength*10;
	printf("当前分数为:%d\n",score);
	//printf("你当前存活时间为: %d秒\n",time);
	printf("贪吃蛇长度:%d\n",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("\n");
	}
	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;
}

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

贪吃蛇---C语言实现

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

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