C語言基于EasyX實現(xiàn)貪吃蛇
本文實例為大家分享了C語言基于EasyX實現(xiàn)貪吃蛇的具體代碼,供大家參考,具體內(nèi)容如下
成品展示:
實現(xiàn)思路:
貪吃蛇的實現(xiàn)思路并不復(fù)雜,由于我們需要將數(shù)據(jù)展示在圖形窗口上,因此就不需要之前那種用數(shù)組表示整個游戲地圖的方法。
貪吃蛇的蛇有X坐標(biāo)和Y坐標(biāo),而且不止一節(jié),因此需要一個坐標(biāo)結(jié)構(gòu)體數(shù)組來保存,蛇的移動思路是除了第一節(jié)以外,后面每一節(jié)都是前面一節(jié)的坐標(biāo),然后通過鍵盤的輸入輸出使蛇的X或Y坐標(biāo)加或者減來起到上下左右移動的作用。通過判斷蛇與食物的坐標(biāo)是否重合絕對是否吃到食物,吃到食物以后,蛇的長度加一,分數(shù)增加,食物重新生成。通過與自身坐標(biāo)比較和界面坐標(biāo)比較,判斷是否撞墻或者撞自己,此時游戲結(jié)束。一直循環(huán)移動并且在圖形界面展示,其中通過睡眠函數(shù)Sleep來控制打印速度,從而控制蛇的移動速度。
最后如果需要在游戲時開啟音樂,為了方便則需要在文件目錄下放入音樂文件。
代碼實現(xiàn)
game.h
#pragma once #include<stdio.h> #include<time.h> #include<stdlib.h> #include<graphics.h> #include<conio.h> #include<windows.h> #include<mmsystem.h> #pragma comment(lib,"Winmm.lib") #define length 100 ?//蛇長度 //1.數(shù)據(jù)分析:基本數(shù)據(jù)成員分析 //坐標(biāo)屬性,蛇屬性,食物屬性 //坐標(biāo)屬性 typedef struct pointXY { ?? ?int x; ?? ?int y; }MYPOINT; //蛇屬性 struct Snake { ?? ?int num;//蛇的節(jié)數(shù) ?? ?MYPOINT xy[length]; //蛇最多有100節(jié) ?? ?char postion;//蛇的方向 }; //食物的屬性 struct Food { ?? ?MYPOINT fdxy; ?? ?int eatgrade=0;//吃食物的分數(shù) ?? ?int flag=0;//食物是否存在,0表示存在,1表示不存在 }; //方向 enum movePostion{right=77,left=75,down=80,up=72}; //主窗口 static HWND hwnd = NULL; //2.過程分析:函數(shù)分析 //初始化蛇和食物 void initSnakeFood(struct Snake*snake, struct Food* food); //畫蛇 void drawSnake(struct Snake* snake); //移動蛇 void moveSnake(struct Snake* snake); //按鍵處理 void keyDown(struct Snake* snake); //初始化食物 void initFood(struct Food*food, struct Snake* snake); //畫食物 void drawFood(struct Food* food); //吃食物 void eatFood(struct Food* food, struct Snake* snake); //判斷是否游戲結(jié)束 int snakeDie(struct Snake* snake); //判斷游戲是否勝利 int winGame(struct Snake* snake); //展示分數(shù) void showGrade(struct Food* food); //按空格鍵暫停 void pauseMoment();
這個頭文件主要包含函數(shù)聲明和頭文件的引用。
game.cpp
#undef UNICODE #undef _UNICODE #include"game.h" void initSnakeFood(struct Snake* snake, struct Food* food) { ?? ?//把前三節(jié)的屬性寫出來,初始化數(shù)據(jù) ?? ?snake->xy[2].x = 0; ?? ?snake->xy[2].y = 0; ?? ?snake->xy[1].x = 10; ?? ?snake->xy[1].y = 0; ?? ?snake->xy[0].x = 20; ?? ?snake->xy[0].y = 0; ?? ?snake->num = 3;//開始有三節(jié) ?? ?snake->postion = right;//初始化方向為右 ?? ?food->eatgrade = 0; } void drawSnake(struct Snake* snake) { ?? ?for (int i = 0; i < snake->num; i++) ?? ?{ ?? ??? ?setlinecolor(BLACK);//矩形邊框線的顏色 ?? ??? ?setfillcolor(RGB(rand() % 255, rand() % 255, rand() % 255));//內(nèi)部填充顏色 ?? ??? ?fillrectangle(snake->xy[i].x, snake->xy[i].y, snake->xy[i].x + 10, snake->xy[i].y + 10); ?? ?} } void moveSnake(struct Snake* snake) { ?? ?//除了第一節(jié)之外,后面每一節(jié)都是前面一節(jié)的坐標(biāo) ?? ?for (int i = snake->num; i > 0; i--) ?? ?{ ?? ??? ?snake->xy[i].x = snake->xy[i - 1].x; ?? ??? ?snake->xy[i].y = snake->xy[i - 1].y; ?? ?} ?? ?//第一節(jié)的處理 ?? ?switch(snake->postion) ?? ?{ ?? ?case right: ?? ??? ?snake->xy[0].x += 10; ?? ??? ?break; ?? ?case left: ?? ??? ?snake->xy[0].x -= 10; ?? ??? ?break; ?? ?case down: ?? ??? ?snake->xy[0].y += 10; ?? ??? ?break; ?? ?case up: ?? ??? ?snake->xy[0].y -= 10; ?? ?default: ?? ??? ?break; ?? ?} } void keyDown(struct Snake* snake) { ?? ?char userkey = 0; ?? ?userkey = _getch(); ?? ?switch (userkey) ?? ?{ ?? ?case right: ?? ??? ?if (snake->postion != left) ?? ??? ??? ?snake->postion = right; ?? ??? ?break; ?? ?case left: ?? ??? ?if (snake->postion != right) ?? ??? ??? ?snake->postion = left; ?? ??? ?break; ?? ?case down: ?? ??? ?if (snake->postion != up) ?? ??? ??? ?snake->postion = down; ?? ??? ?break; ?? ?case up: ?? ??? ?if (snake->postion != down) ?? ??? ??? ?snake->postion = up; ?? ??? ?break; ?? ?} } void initFood(struct Food* food, struct Snake* snake) { ?? ?food->fdxy.x = rand() % 64 * 10; ?? ?food->fdxy.y = rand() % 48 * 10; ?? ?food->flag = 1; ?? ?//如果食物出現(xiàn)在蛇身上,重新產(chǎn)生坐標(biāo) ?? ?for (int i = 0; i>snake->num; i++) ?? ?{ ?? ??? ?if (food->fdxy.x == snake->xy[i].x && food->fdxy.y == snake->xy[i].y) ?? ??? ?{ ?? ??? ??? ?food->fdxy.x = rand() % 64 * 10; ?? ??? ??? ?food->fdxy.y = rand() % 48 * 10; ?? ??? ?} ?? ?} } void drawFood(struct Food* food) { ?? ?setlinecolor(BLACK);//矩形邊框線的顏色 ?? ?setfillcolor(RGB(rand() % 255, rand() % 255, rand() % 255)); ?? ?fillrectangle(food->fdxy.x, food->fdxy.y, food->fdxy.x + 10, food->fdxy.y + 10); } void eatFood(struct Food* food, struct Snake* snake) { ?? ?//蛇邊長 ?? ?//食物重新生成 ?? ?//分數(shù)增加 ?? ?if (snake->xy[0].x == food->fdxy.x && snake->xy[0].y == food->fdxy.y) ?? ?{ ?? ??? ?snake->num++; ?? ??? ?food->eatgrade += 10; ?? ??? ?food->flag = 0; ?? ?} } //蛇死亡,游戲結(jié)束 int snakeDie(struct Snake* snake) { ?? ?if (snake->xy[0].x > 640 || snake->xy[0].x < 0 || snake->xy[0].y>480 || snake->xy[0].y < 0|| (snake->xy[0].x + 10) > 640 || (snake->xy[0].x + 10) < 0 || (snake->xy[0].y + 10) > 480 || (snake->xy[0].y + 10) < 0) ?? ?{ ?? ??? ?outtextxy(200, 200, "撞墻"); ?? ??? ?//MessageBox(hwnd, "游戲結(jié)束,點擊確定重新開始", "撞墻", MB_OKCANCEL); ?? ??? ?return 1;//返回1,游戲結(jié)束 ?? ?} ?? ?for (int i = 1; i < snake->num; i++) ?? ?{ ?? ??? ?if (snake->xy[0].x == snake->xy[i].x && snake->xy[0].y == snake->xy[i].y) ?? ??? ?{ ?? ??? ??? ?outtextxy(200, 200, "自殺"); ?? ??? ??? ?//MessageBox(hwnd, "游戲結(jié)束,點擊確定重新開始", "自殺", MB_OKCANCEL); ?? ??? ??? ?return 1; ?? ??? ?} ?? ?} ?? ?return 0; } int winGame(struct Snake* snake) { ?? ?if (snake->num == length) ?? ?{ ?? ??? ?outtextxy(200, 200, "勝利,恭喜通關(guān)"); ?? ??? ?//MessageBox(hwnd, "游戲結(jié)束,點擊確定重新開始", "恭喜通關(guān)", MB_OKCANCEL); ?? ??? ?return 1;//返回1,游戲結(jié)束 ?? ?} ?? ?else ?? ?{ ?? ??? ?return 0; ?? ?} } void showGrade(struct Food* food) { ?? ?char grade[100] = ""; ?? ?sprintf(grade, "%d", food->eatgrade); ?? ?setbkmode(TRANSPARENT); ?? ?settextcolor(LIGHTBLUE); ?? ?outtextxy(560,20,"分數(shù)"); ?? ?outtextxy(610,20,grade); } void pauseMoment() { ?? ?if (_getch() == 32) ?? ?{ ?? ??? ?while (_getch() != 32); ?? ?} }
test.cpp
#include"game.h" int main() { ?? ?mciSendString(L"open 1.mp3 alias bkmusic", NULL, 0, NULL);//打開音樂文件 ?? ?mciSendString(L"play bkmusic repeat", NULL, 0, NULL); ? ? //循環(huán)播放音樂 ?? ?srand((unsigned int)time(NULL));//隨機數(shù)種子 ?? ?struct Snake snake;//創(chuàng)建蛇 ?? ?struct Food food;//創(chuàng)建食物 ?? ?hwnd = initgraph(640, 480);//初始化窗口 ?? ?setbkcolor(WHITE);//設(shè)置窗口為白色 ?? ?int key = 0;//接收最終的彈窗指令,判斷是否繼續(xù)游戲 ?? ?do ?? ?{ ?? ??? ?initSnakeFood(&snake,&food);//初始化蛇和食物的分數(shù) ?? ??? ?key = 0; ?? ??? ?while (1) ?? ??? ?{ ?? ??? ??? ?BeginBatchDraw();緩沖區(qū)打印,防止閃屏 ?? ??? ??? ?cleardevice();//刷新 ?? ??? ??? ?if (food.flag == 0) ?? ??? ??? ?{ ?? ??? ??? ??? ?initFood(&food, &snake); ?? ??? ??? ?} ?? ??? ??? ?drawFood(&food);//畫食物 ?? ??? ??? ?eatFood(&food, &snake);//是否吃食物 ?? ??? ??? ?showGrade(&food);//打印食物 ?? ??? ??? ?drawSnake(&snake);//畫蛇 ?? ??? ??? ?EndBatchDraw();//緩沖區(qū)打印 ?? ??? ??? ?if (snakeDie(&snake))//判斷是否四方 ?? ??? ??? ?{ ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ??? ?if (winGame(&snake))//判斷是否勝利 ?? ??? ??? ?{ ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ??? ?while (_kbhit())//如果有按鍵則進入,否則不進入循環(huán) ?? ??? ??? ?{ ?? ??? ??? ??? ?pauseMoment();//暫停 ?? ??? ??? ??? ?keyDown(&snake); ?? ??? ??? ?} ?? ??? ??? ?moveSnake(&snake);//移動蛇 ?? ??? ??? ?Sleep(100); ?? ??? ?} ?? ??? ?key=MessageBox(hwnd, L"點擊確定重新開始", L"游戲結(jié)束", MB_OKCANCEL); ?? ??? ? ?? ?} while (key==IDOK);//如果點擊確定,則重新開始游戲 ?? ?closegraph();//關(guān)閉圖形模式,釋放由圖形系統(tǒng)分配的所有內(nèi)存 ?? ?system("pause"); ?? ?return 0; }
這個文件主要是通過調(diào)用不同的函數(shù),實現(xiàn)對蛇的操作和展示功能。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言數(shù)據(jù)在內(nèi)存中的存儲流程深入分析
使用編程語言進行編程時,需要用到各種變量來存儲各種信息。變量保留的是它所存儲的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個變量時,就會在內(nèi)存中保留一些空間。您可能需要存儲各種數(shù)據(jù)類型的信息,操作系統(tǒng)會根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲什么2022-10-10詳解C++ STL模擬實現(xiàn)forward_list
forward_list是C++ 11新增的容器,它支持從容器中的任何位置快速插入和移除元素的容器,不支持快速隨機訪問。本文將模擬實現(xiàn)forward_list,感興趣的可以了解一下2023-01-01