C語言實現經典小遊戲貪吃蛇
阿新 • • 發佈:2018-11-04
純c語言寫的小遊戲,本人才疏學淺,程式碼有很多不足,僅供給初學者參考。
實現功能:
- ↑ ↓ ← →分別用來控制上下左右四個方向
- 空格暫停
- esc退出遊戲
- f1加速, f2 減速
- 蛇的長度越長,速度越快(速度有上限)
- 食物顏色隨機
- 撞牆死/咬到自己死
不足之處:
- 實現了蛇撞牆和撞到自己兩種死亡判斷,但是沒有實現遊戲勝利。
- 蛇移動的時間和食物出現的時間固定,沒有實現遊戲難度的選擇。
執行結果展示:
程式碼如下:
標頭檔案(snack.h)
#ifndef __SNACK_H__ #define __SNACK_H__ #define _CRT_SECURE_NO_WARNINGS 1 #include <Windows.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #define WALL "▓" #define SNACK "●" #define FOOD "★" #define INIT_X 10 #define INIT_Y 20 #define INIT_LONG 4 enum Direction { UP = 1, //上 DOWN, //下 LEFT, //左 RIGHT //右 }; typedef enum GameStatus //遊戲狀態 { OK, //正常 NORMAL_END, //正常結束 KILL_BY_WALL, //撞牆 KILL_BY_SELF //咬到自己 }; typedef struct SnackNode //表示蛇身節點 { int x; int y; struct SnackNode* _pNext; }SnackNode, *pSnackNode; typedef struct Snack { pSnackNode _psnack;//位置 pSnackNode _pfood;//食物位置 int _TotalScore; //得分 int _AddScore; //增加分數 int _SleepTime; enum Direction _Dir; enum GameStatus _Status; }Snack, *pSnack; void setpos (int x, int y);//控制游標位置 int WelcomeToGame_1 ();//歡迎介面1 void WelcomeToGame_2 ();//歡迎介面2 void CreateMap ();//初始化地圖 void InitSnack (pSnack ps);//初始化蛇 void CreateFood (pSnack ps);//列印食物 void GameStart (pSnack ps);//遊戲開始 void SnackMove(pSnack ps);//蛇移動 void Killed_By_Wall(pSnack ps);//撞牆死 void Collide_Self(pSnack ps);咬到自己死 void AboutGame (pSnack ps);//遊戲說明 int color(int x); //改變字型顏色 int GetLength (pSnack ps);//獲取蛇的長度 void Exit_Game(pSnack snack);//退出遊戲 #endif
主要函式(main.c)
#include "snack.h" void setpos (int x, int y) { COORD pos = {0}; pos.X = x; pos.Y = y; SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), pos); } int WelcomeToGame_1 () { int i = 0; system ("mode con cols=100 lines=30"); //設定介面大小 system ("title 貪吃蛇"); setpos (38, 8); color (11); printf ("貪吃蛇xiao遊戲\n"); setpos (38, 13); printf ("1、開始遊戲"); setpos (38, 15); printf ("2、退出"); setpos (88, 28); printf ("2018/08/26"); setpos (38, 17); printf ("請選擇:"); scanf ("%d", &i); system ("cls"); return i; } void WelcomeToGame_2 () { color (11); setpos (32, 11); printf ("提示:"); setpos (35, 13); printf ("用↑↓←→控制蛇的移動方向,f1加速,f2減速"); setpos (35, 15); printf ("速度越快,得分越多"); setpos (35, 28); printf ("LOADING..."); Sleep (2500); system ("cls"); } void CreateMap () { int i = 0; color (15); //上邊界 for (i=0; i<=58; i+=2) { setpos (i, 0); printf (WALL); } //左邊界 for (i=0; i<30; i++) { setpos (0, i); printf (WALL); } //下邊界 for (i=2; i<=58; i+=2) { setpos (i, 29); printf (WALL); } //右邊界 for (i=1; i<29; i++) { setpos (58, i); printf (WALL); } } pSnackNode BuySnackNode () { pSnackNode cur = (pSnackNode)malloc (sizeof (SnackNode)); if (cur == NULL) { printf ("建立蛇身節點出錯,遊戲結束"); exit (1); } cur ->x = 0; cur ->y = 0; cur ->_pNext = NULL; return cur; } void print_snack(pSnack ps) { pSnackNode cur = ps->_psnack; while (cur) { setpos (cur->x, cur->y); color (14); printf (SNACK); cur = cur->_pNext; } color (12); } void InitSnack (pSnack ps) { int i = INIT_LONG; pSnackNode cur = NULL; pSnackNode first = (pSnackNode)malloc (sizeof (SnackNode)); if (first == NULL) { printf ("建立蛇頭節點出錯,遊戲結束"); exit (1); } first->x = INIT_X; first->y = INIT_Y; first->_pNext = NULL; while (--i) { cur = BuySnackNode (); cur ->x = first->x + 2; cur->y = first->y ; cur->_pNext = first; first = cur; } ps->_Dir = RIGHT; ps->_psnack = first; ps->_AddScore = 10; ps->_SleepTime = 200; ps->_TotalScore = 0; ps->_Status = OK; print_snack(ps); } void CreateFood (pSnack ps) { int x = 0; int y = 0; int col = 0; pSnackNode snack = ps ->_psnack ; pSnackNode food = BuySnackNode(); y = rand()% 28 + 1; do { x = rand ()% 55 + 2; }while ((x%2) != 0); food ->x = x; food ->y = y; while (snack) { if (food->x == snack->x && food->y == snack->y) { break; } else { snack = snack->_pNext; } } if (snack == NULL) { ps->_pfood = food; setpos (food->x, food->y); col = rand() % 15+1; color (col); printf (FOOD); } else { CreateFood (ps); } } void Killed_by_Self(pSnack ps) { pSnackNode cur = ps->_psnack->_pNext; while (cur != NULL) { if (cur->x == ps->_psnack ->x && cur->y == ps->_psnack ->y) { setpos (18, 21); printf ("很遺憾, 你把自己給咬死了!!!\n"); ps->_Status = KILL_BY_SELF; break; } cur = cur->_pNext; } } void Killed_By_Wall(pSnack ps) { if (ps->_psnack ->x == 0 || ps->_psnack ->x == 58 || ps->_psnack->y == 29 || ps->_psnack ->y == 0) { setpos (18, 21); printf ("很遺憾,你撞牆了!!!\n"); ps->_Status = KILL_BY_WALL; } } void GameStart (pSnack ps) { int i = 0; do { AboutGame (ps); //檢測是否從鍵盤上按下一個值 if(GetAsyncKeyState(VK_UP) && ps->_Dir != DOWN) //上 { ps->_Dir = UP; } if(GetAsyncKeyState(VK_DOWN) && ps->_Dir != UP) //下 { ps->_Dir = DOWN; } if(GetAsyncKeyState(VK_LEFT) && ps->_Dir != RIGHT) //左 { ps->_Dir = LEFT; } if(GetAsyncKeyState(VK_RIGHT) && ps->_Dir != LEFT) //右 { ps->_Dir = RIGHT; } if(GetAsyncKeyState(VK_ESCAPE))//退出 { ps->_Status = NORMAL_END; } if(GetAsyncKeyState(VK_F1))//加速 { if(ps->_SleepTime > 50) { ps->_SleepTime -= 30; } ps->_AddScore += 5; } if(GetAsyncKeyState(VK_F2))//減速 { if(ps->_SleepTime <= 500) { ps->_SleepTime += 50; if(ps->_AddScore != 6) ps->_AddScore -= 6; else ps->_AddScore = 6; } } if(GetAsyncKeyState(VK_SPACE))//暫停 { while(1) { Sleep(100); if(GetAsyncKeyState(VK_SPACE)) { break; } } } Sleep(ps->_SleepTime); SnackMove(ps); Killed_By_Wall(ps); Killed_by_Self(ps); }while (ps->_Status == OK); setpos (18, 23); printf ("請稍後..."); Sleep (2500); system ("cls"); setpos (45, 10); printf ("GAME OVER"); setpos (45, 15); printf ("總分:%d", ps->_TotalScore); setpos (80, 28); system ("pause"); } void Eat_Food(pSnack ps) { //分數增加 ps->_TotalScore += ps->_AddScore; //吃掉食物後吧食物銷燬 free (ps->_pfood ); ps->_pfood = NULL; //列印蛇 setpos (ps->_psnack ->x, ps->_psnack ->y); print_snack (ps); //在生成新的食物 CreateFood (ps); //每吃一個食物,速度增加 if (ps->_SleepTime >= 100) { ps->_SleepTime -= 10; ps->_AddScore += 5; } } void Not_Eat_food(pSnack ps) // 沒有吃東西,長度不變,只需要把最後一個節點處列印成空格,在銷燬掉最後一個節點 { pSnackNode cur = ps->_psnack; while (cur->_pNext ->_pNext != NULL) { cur = cur->_pNext; } setpos (cur->_pNext ->x, cur->_pNext->y); printf (" "); free (cur->_pNext); cur->_pNext = NULL; //列印蛇 setpos (ps->_psnack->x, ps->_psnack->y); print_snack (ps); } void SnackMove (pSnack ps) { pSnackNode cur = BuySnackNode (); switch (ps->_Dir) { case UP: { cur->x = ps->_psnack ->x; cur->y = ps->_psnack ->y-1; cur->_pNext = ps->_psnack ; ps->_psnack = cur; if (cur->x == ps ->_pfood ->x && cur->y == ps->_pfood->y) { Eat_Food(ps); } else { Not_Eat_food(ps); } } break; case DOWN: { cur->x = ps->_psnack ->x; cur->y = ps->_psnack ->y+1; cur->_pNext = ps->_psnack ; ps->_psnack = cur; if (cur->x == ps ->_pfood ->x && cur->y == ps->_pfood->y) { Eat_Food(ps); } else { Not_Eat_food(ps); } } break; case LEFT: { cur->x = ps->_psnack ->x-2; cur->y = ps->_psnack ->y; cur->_pNext = ps->_psnack ; ps->_psnack = cur; if (cur->x == ps ->_pfood ->x && cur->y == ps->_pfood->y) { Eat_Food(ps); } else { Not_Eat_food(ps); } } break; case RIGHT: { cur->x = ps->_psnack ->x+2; cur->y = ps->_psnack ->y; cur->_pNext = ps->_psnack ; ps->_psnack = cur; if (cur->x == ps ->_pfood ->x && cur->y == ps->_pfood->y) { Eat_Food(ps); } else { Not_Eat_food(ps); } } break; } } void AboutGame (pSnack ps) { color (2); setpos (65, 9); printf ("遊戲說明:"); setpos (68, 11); printf ("控制方向:↑↓←→"); setpos (68, 13); printf ("暫停:空格"); setpos (68, 15); printf ("退出遊戲:esc"); setpos (68, 17); printf ("f1加速,f2減速"); setpos (68, 19); printf ("分數:+%d", ps->_AddScore); color (11); } int color(int c) //改變字型顏色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改文字顏色 return 0; } void Exit_Game(pSnack ps) { pSnackNode cur = ps->_psnack; pSnackNode pre = NULL; while (cur != NULL) { pre = cur; cur = cur->_pNext; free (pre); pre = NULL; } }
功能測試test.c
#include "snack.h" void test () { int i = 0; int j = 0; Snack snack; srand ((unsigned)time(NULL)); do { //開始介面 i = WelcomeToGame_1 ()-2; switch (i) { case -1: { WelcomeToGame_2 (); //構造地圖(邊界) CreateMap (); //初始化蛇 InitSnack (&snack); //構造食物 CreateFood (&snack); //開始遊戲 GameStart (&snack); } break; case 0: setpos (38, 15); printf ("退出遊戲!!\n"); Exit_Game(&snack); break; default : setpos (38, 15); printf ("你的選擇有誤,2s後請重新選擇..."); Sleep (2000); break; } }while (i); setpos (66, 28); system ("pause"); } void test_food () { int i = 0; Snack snack; WelcomeToGame_2 (); //構造地圖(邊界) CreateMap (); //初始化蛇 InitSnack (&snack); //構造食物 for (; i<100; ++i) { CreateFood (&snack); Sleep (500); } } int main() { test (); return 0; }