1. 程式人生 > >基於EasyX庫的貪吃蛇遊戲——C語言實現

基於EasyX庫的貪吃蛇遊戲——C語言實現

接觸程式設計有段時間了,一直想學習怎麼去寫個遊戲來練練手。在看了B站上的教學終於可以自己試試怎麼實現貪吃蛇這個遊戲了。好了,廢話不多說,我們來看看如何用EasyX庫來實現貪吃蛇。

一、準備

  • 工具vc++6.0
  • 安裝庫檔案
    • EasyX庫安裝連結
    • 可以安裝任意版本,本人安裝的是2018春分版
    • 這是一個簡單易學的一個圖形庫,相信對於大家學習來說應該不成問題
  • 準備工作做好後接下來就得弄清楚遊戲工作機制了

二、基本介紹

  • 在這裡我們需要明白EasyX庫的基本知識,其次我們還有了解遊戲的工作原理,不能盲目的直接寫程式碼,需要一步步的思考,比如蛇是如何繪製、移動的;食物是怎麼產生的;蛇吃了食物會怎樣;死亡機制等等

    EasyX庫介紹

  1. 首先我們來講講EasyX庫的座標概念
    • 物理座標
      • 簡單來說,物理座標就是以視窗的左上角為原點,以水平向右為x軸,豎直向下為y軸,以畫素為單位
    • 邏輯座標
      • 邏輯座標和物理座標是一一對應的,不過邏輯座標是以點為單位
  2. 顏色概念
  • 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;
}