貪吃蛇---C語言實現
阿新 • • 發佈:2019-02-16
感想
大一剛放寒假,用了兩天時間終於將貪吃蛇寫好了。第一次寫專案,雖然小了點,但是在這過程中遇到的問題都讓我有所收穫。
實現
貪吃蛇各函式關係圖。如下圖:
有了各功能關係圖之後就可以開工寫程式碼了。
寫程式碼過程中遇到最多的問題,還是編譯器的問題。最開始使用dev c++編譯原始碼,程式碼不多時,編譯器工作還沒什麼問題。程式碼多了之後,編譯器直接將我寫好的原始碼打亂了。大概是原先在函式體中的程式碼都跑到函式體外邊。函式就剩下一個完整函式體。還有出現一些奇怪的括號,夾雜在程式碼中間。經過漫長的修改和重寫程式碼。《這次備份了一份》。第一次無法過編譯。第二次竟然過了。前後兩次無任何程式碼改動。於是將程式碼移到vs2015上執行,出現如下錯誤:
幾經尋求解決之法不得之後,毅然放棄vs2015,轉到eclipse平臺。幸好,eclipse c++可用。
----------------------------------------------------------------------------------------------------------------------------------
程式碼實現思路:
不得不提這個思路借鑑了別人的想法,二維陣列----遊戲介面。 二維陣列通過四個數字來分辨空、牆、食物、蛇,對應為0、1、2、3. 遊戲介面,就按照二維陣列中的數字輸出對應的字元即可。<這很簡陋--> 程式碼理想效果 主要是程式碼寫得太渣,導致蛇連續轉彎會斷了身子。大概這個意思 操作鍵需要大寫鍵盤鎖定----然後W A S D 接下來打算實現一個GUI版貪吃蛇,設定難度係數,優化那些渣程式碼,實現貪吃蛇自己找食物的功能。/* ============================================================================ 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; }