1. 程式人生 > >貪吃蛇---C語言實現

貪吃蛇---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("\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;
}

理想效果 主要是程式碼寫得太渣,導致蛇連續轉彎會斷了身子。大概這個意思 操作鍵需要大寫鍵盤鎖定----然後W A S D 接下來打算實現一個GUI版貪吃蛇,設定難度係數,優化那些渣程式碼,實現貪吃蛇自己找食物的功能。