基於EasyX庫的貪吃蛇遊戲——C語言實現
阿新 • • 發佈:2018-12-19
接觸程式設計有段時間了,一直想學習怎麼去寫個遊戲來練練手。在看了B站上的教學終於可以自己試試怎麼實現貪吃蛇這個遊戲了。好了,廢話不多說,我們來看看如何用EasyX庫來實現貪吃蛇。
一、準備
- 工具vc++6.0
- 安裝庫檔案
- EasyX庫安裝連結
- 可以安裝任意版本,本人安裝的是2018春分版
- 這是一個簡單易學的一個圖形庫,相信對於大家學習來說應該不成問題
- 準備工作做好後接下來就得弄清楚遊戲工作機制了
二、基本介紹
在這裡我們需要明白EasyX庫的基本知識,其次我們還有了解遊戲的工作原理,不能盲目的直接寫程式碼,需要一步步的思考,比如蛇是如何繪製、移動的;食物是怎麼產生的;蛇吃了食物會怎樣;死亡機制等等
EasyX庫介紹
- 首先我們來講講EasyX庫的座標概念
- 物理座標
- 簡單來說,物理座標就是以視窗的左上角為原點,以水平向右為x軸,豎直向下為y軸,以畫素為單位
- 邏輯座標
- 邏輯座標和物理座標是一一對應的,不過邏輯座標是以點為單位
- 物理座標
- 顏色概念
- EasyX庫的預定義顏色常量如下:
常量 | 值 | 顏色 |
---|---|---|
BLACK | 0 | 黑 |
BULE | 0xAA0000 | 藍 |
GREEN | 0x00AA00 | 綠 |
CYAN | 0xAAAA00 | 青 |
RED | 0x0000AA | 紅 |
MAGENTA | 0xAA00AA | 紫 |
BROWN | 0x0055AA | 棕色 |
LIGHTGRAY | 0xAAAAAA | 淺灰 |
DARKGRAY | 0x555555 | 深灰 |
LIGHTBULE | 0xFF5555 | 亮藍 |
LIGHTGREEN | 0x55FF55 | 亮綠 |
LIGHTCYAN | 0xFFFF55 | 亮青 |
LIGHTRED | 0x5555FF | 亮紅 |
LIGHTMAGENTA | 0xFF55FF | 亮紫 |
YELLOW | 0x55FFFF | 黃 |
WHITE | 0xFFFFFF | 白 |
3.基本函式介紹
- initgraph(int width,int height,int flag=NULL):初始化繪圖環境
- width:繪圖環境的寬度
- height:繪圖環境的高度
- flag:繪圖環境的樣式,預設為NULL
- cleardevice():用於清除螢幕內容
- setbkcolor(COLORREF color):設定背景顏色
- setfillcolor(COLORREF color):設定填充顏色
- setlinecolor(COLORREF color):設定當前畫線顏色
- outtextxy(int x,int y,TCHAR c):用於在指定位置輸出字串
- x,y表示輸出字串的座標值
- c表示待輸出的字元
- fillroundrect(int left,int top,int right,int bottom,int ellipsewidth,int ellipseheight):繪製圓角矩形
- left:圓角矩形左部 x 座標
- top:圓角矩形上部 y 座標
- right:圓角矩形右部 x 座標
- bottom:圓角矩形下部 y 座標
- ellipsewidth:構成圓角矩形的圓角的橢圓的寬度
- ellipseheight:構成圓角矩形的圓角的橢圓的高度
工作原理
- 必須先包含標頭檔案,才能執行
#include<graphics.h>
#include<time.h>
#include<stdlib.h>
#include<conio.h>
- 我們要有窗口才能繪製蛇和食物,因此可以用initgraph()函式來實現
- 其次我們要弄清楚如何來描述視窗位置,這裡我們可以設定一個結構體Coor
struct Coor{
int x;
int y;
};
- 方向
enum Ch{ //列舉型別表示上下左右鍵的鍵值
up=72,
down=80,
left=75,
right=77
};
- 蛇也是有自己屬性的結構體
struct Snake{
//蛇的屬性
int n; //蛇當前節數,一節為一個正方形,n個正方形
struct Coor szb[500]; //snake的座標,存放蛇的座標,這裡設定500,表示蛇能達到的最大長度為500
Ch ch; //蛇的方向
}snake; //變數
- 食物的結構體
struct Food{
struct Coor fzb; //食物座標
int flag; //是否被吃
}food;
有了以上的結構體的定義,我們就可以設定函式來完成貪吃蛇的繪製、移動、食物的繪製以及死亡機制等等
- 函式內容如下
- InitSnake():包含視窗的初始化,初始化隨機種子,初始化蛇的起始座標
- DrawSnake():繪製蛇的每個節點
- MoveSnake():蛇的移動
- ChangeSnakeCh():通過鍵盤改變蛇的方向
- CoorFood():隨機生成食物的座標
- DrawFood():繪製食物樣式
- EatFood():蛇吃掉食物後的變化
- KnockWall():撞牆死亡
- EatSelf():吃到自己死亡
void InitSnake(){
//初始化視窗
srand((unsigned int)time(NULL)); //產生隨機種子
initgraph(200,200); //初始化200*200畫素的繪圖視窗
setbkcolor(GREEN); //設定背景顏色
//初始化蛇
//開始時蛇的節數為1,方向向右
snake.n=1;
snake.ch=right;
snake.szb[0].x=0;
snake.szb[0].y=0;
}
//繪製蛇,n節蛇
void DrawSnake(){
setlinecolor(GREEN); //設定蛇邊緣的線條顏色
setfillcolor(RED); //設定蛇身的顏色
//遍歷陣列
for(int i=0;i<snake.n;i++){
fillrectangle(snake.szb[i].x,snake.szb[i].y,snake.szb[i].x+10,snake.szb[i].y+10); //根據蛇的當前長度,建立蛇身,這裡設定一節蛇的大小為10*10個畫素
}
}
- 關於蛇的移動其實很簡單,只要將前面的節點座標傳遞給後面的節點座標,就能起到移動的效果
//蛇的移動
void MoveSnake(){
for(int i=snake.n-1;i>0;i--){
snake.szb[i].x=snake.szb[i-1].x;
snake.szb[i].y=snake.szb[i-1].y;
}
switch(snake.ch){
case up:
snake.szb[0].y-=10;
break;
case down:
snake.szb[0].y+=10;
break;
case left:
snake.szb[0].x-=10;
break;
case right:
snake.szb[0].x+=10;
break;
}
}
- 這裡需要注意的是:蛇移動時的方向改變規則是在蛇向左/右移動時,蛇只能向上/下移動,同理對於蛇在向上/下移動的情況
//通過鍵盤控制
void ChangeSnakeCh(){
int move;
move=getch(); //獲取鍵盤傳遞的字元
switch(move){
case right:
if(snake.ch!=left)
snake.ch=right;
break;
case left:
if(snake.ch!=right)
snake.ch=left;
break;
case up:
if(snake.ch!=down)
snake.ch=up;
break;
case down:
if(snake.ch!=up)
snake.ch=down;
break;
}
}
- 食物的產生與繪製
void CoorFood(){
food.fzb.x=rand()%20*10; //根據視窗畫素來產生食物座標
food.fzb.y=rand()%20*10;
food.flag=1; 1表示食物沒被吃的狀態,0表示已吃的狀態
}
//繪製食物
void DrawFood(){
//繪製圓角矩形
setfillcolor(YELLOW);
fillroundrect(food.fzb.x,food.fzb.y,food.fzb.x+10,food.fzb.y+10,10,10);
}
//蛇吃食物
void EatFood(){
//判斷蛇頭和食物是否重合
if(snake.szb[0].x==food.fzb.x&&snake.szb[0].y==food.fzb.y){
snake.n++; //蛇身長度加1
food.flag=0; 食物標記為0表示已吃
}
}
- 死亡機制
//撞牆
int KnockWall(){
for(int i=0;i<snake.n;i++){
if(snake.szb[i].x>200||snake.szb[i].x<0||snake.szb[i].y>200||snake.szb[i].y<0){
//如果蛇頭的座標值超出視窗的座標值,就返回錯誤
return 0;
}
}
}
//咬到自己
int EatSelf(){
for(int i=1;i<snake.n;i++){
if(snake.szb[0].x==snake.szb[i].x&&snake.szb[0].y==snake.szb[i].y){
//迴圈判斷蛇頭座標是否與蛇身某部分重合,若重合則放回錯誤
return 0;
}
}
}
- 主函式
int main(){
InitSnake(); //初始化
while(1){
while(!kbhit()){ //未改變蛇的方向之前
if(food.flag==0){
CoorFood();
}
cleardevice(); //先清屏,才能保證之前繪製的蛇身不會顯示出來
MoveSnake(); //先移動蛇的各個座標
DrawFood(); //繪製食物
DrawSnake(); //再繪製蛇身
if(!KnockWall()||!EatSelf()) //死亡機制
break;
EatFood(); //吃掉食物後,蛇和食物的變化
Sleep(150); //設定蛇的移動速度
}
while(!KnockWall()||!EatSelf()){
outtextxy(100,100,"YOU DIED!"); //如果蛇吃到自己或撞牆則在視窗顯示YOU DIED!
}
ChangeSnakeCh(); //通過鍵盤上下左右鍵來移動蛇
}
return 0;
}