基於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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM