前言
在Visual Studio 2019開發環境上以C/C++為編程語言,運用easyx庫實作貪吃蛇游戲邏輯的撰寫與可視化,
實驗要求與目標
實作貪吃蛇游戲基本功能,螢屏上隨機出現一個“食物”,稱為豆子,上下左右控制“蛇”的移動,吃到“豆子”以后“蛇”的身體加長一點,得分增加,“蛇”碰到邊界或,蛇頭與蛇身相撞,蛇死亡,游戲結束,為游戲設計初始歡迎界面,游戲界面,游戲結束界面;
進行互動界面的設計,要有開始鍵、暫停鍵和停止退出的選項,對蛇吃到豆子進行分值計算,可以設定游戲速度,游戲音樂等拓展元素,
實驗思路
很簡單的思路:
- 上下左右鍵控制蛇的移動;
- 吃到豆子分數增加,前移動的速度也線性增加,
- 空格鍵暫停游戲,
- 撞到墻或者咬到自己,游戲結束

實驗程序與部分代碼
實驗主要分為以下步驟:
1、蛇,豆子以及相關屬性的定義,
2、程式與鍵盤按鍵互動邏輯的實作,
3、移動蛇函式邏輯實作,
4、撞到墻或者咬到自己game over以及輔助功能的實作,
5、可視化的實作,
相關核心代碼
首先是蛇,豆子以及相關屬性的定義以及初始化:
這里運用了結構體來存放相關變數,初始點設為負值是因為不知到為什么每次豆子重繪時(1,1)總會有豆子一閃而逝(應該是重繪的問題)
typedef struct Point
{
int x = -10;
int y = -10;
}MYPOINT;
//蛇屬性
struct mySnake
{
int num; //蛇節
MYPOINT xy[MAX]; //記錄蛇每一節坐標
char position; //方向
}snake;
//食物
struct myFood
{
MYPOINT foodCoord; //食物坐標
int flag; //食物是否存在的標記
int eatGrade; //獲取分數
}food;
//列舉
enum movPosition
{
right_g,
left_g,
down_g,
up_g
};
//程序
void initSnake(); //初始化
void drawSnake(); //畫蛇
void moveSnake(); //移動蛇
void keyDown(); //控制蛇移動
void initFood(); //初始化食物
void drawFood(); //畫食物
void eatFood(); //吃食物
void showGrade(); //顯示分數
int snakeDead(); //蛇死亡
int snakeSpeed(); //蛇速度
void initFood() {
food.foodCoord.x = rand() % 80 * 10;
food.foodCoord.y = rand() % 60 * 10;
//cout << food.foodCoord.x << " " << food.foodCoord.y << endl;
food.flag = 1;
//不出現在蛇
for (int i = 0; i < snake.num; i++) {
if (food.foodCoord.x == snake.xy[i].x && food.foodCoord.y == snake.xy[i].y) {
food.foodCoord.x = rand() % 80 * 10;
food.foodCoord.y = rand() % 60 * 10;
}
}
}
void initSnake() //初始化
{
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; //初始化蛇的節數
snake.position = right_g; //初始化蛇的方向
}
程式與鍵盤按鍵互動邏輯的實作:
enum movPosition
{
right_g,
left_g,
down_g,
up_g
};
void keyDown() //控制蛇移動
{
char key = _getch();
if (key == 32) {
while (_getch() != 32);
}
switch (key)
{
case 'w':
case 'W':
case 72:
if (snake.position != down_g) {
snake.position = up_g;
}
break;
case 's':
case 'S':
case 80:
if (snake.position != up_g) {
snake.position = down_g;
}
break;
case 'a':
case 'A':
case 75:
if (snake.position != right_g) {
snake.position = left_g;
}
break;
break;
case 'd':
case 'D':
case 77:
if (snake.position != left_g) {
snake.position = right_g;
}
break;
break;
}
}
移動蛇,吃到豆子函式邏輯實作:
void moveSnake() //移動蛇;
{
//移動
for (int i = snake.num - 1; i > 0; i--) {
snake.xy[i].x = snake.xy[i - 1].x;
snake.xy[i].y = snake.xy[i - 1].y;
}
//蛇頭移動
switch (snake.position)
{
case up_g:
snake.xy[0].y -= 10;
break;
case down_g:
snake.xy[0].y += 10;
break;
case left_g:
snake.xy[0].x -= 10;
break;
case right_g:
snake.xy[0].x += 10;
break;
default:
break;
}
}
void eatFood() {
if (snake.xy[0].x == food.foodCoord.x && snake.xy[0].y == food.foodCoord.y) {
food.flag = 0;
snake.num++;
food.eatGrade += 10;
}
}
撞到墻或者咬到自己game over以及輔助功能的實作
int snakeDead() {
if (snake.xy[0].x < 0 || snake.xy[0].x>800 || snake.xy[0].y < 0 || snake.xy[0].y>600) {
MessageBox(hwnd, "game over", "撞墻", 0);
return 1;
}
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) {
MessageBox(hwnd, "game over", "自殺", 0);
return 1;
}
}
return 0;
}
int snakeSpeed() {
return 100 - (snake.num - 3) * 5;
}
easyx庫可視化
EasyX Library for C++ 是針對 VC 的一套繪圖庫,介面簡單易用,用起來很像 TC 的 graphics.h 繪圖,
畫蛇,畫豆子,以及出現相關提示的實作:
void drawSnake() { //畫蛇
for (int i = 0; i < snake.num; i++) {
setlinecolor(WHITE);
setfillcolor(BLACK);
fillrectangle(snake.xy[i].x, snake.xy[i].y, snake.xy[i].x + 10, snake.xy[i].y + 10);
}
}
void drawFood() {
setfillcolor(BLACK);
setlinecolor(WHITE);
cout << food.foodCoord.x << " " << food.foodCoord.y << endl;
fillrectangle(food.foodCoord.x, food.foodCoord.y, food.foodCoord.x + 10, food.foodCoord.y + 10);
}
void showGrade() {
char grade[MAX] = "";
sprintf(grade, "分數: %d", food.eatGrade);
setbkmode(TRANSPARENT);
settextcolor(BLACK);
outtextxy(650, 30, grade);
char tip[MAX] = "";
sprintf(tip,"暫停:按g空格鍵");
setbkmode(TRANSPARENT);
settextcolor(BLACK);
outtextxy(630, 100, tip);
char tip1[MAX] = "";
sprintf(tip1, "操控:w,a,s,d或上下左右鍵");
setbkmode(TRANSPARENT);
settextcolor(BLACK);
outtextxy(580, 170, tip1);
}
主函式方法
int main() {
srand(((unsigned int)time(NULL)));
hwnd = initgraph(800, 600); 初始化界面
setbkcolor(WHITE); //設定背景顏色
cleardevice(); //重繪
initSnake();
LOGFONT f;//字體樣式指標
gettextstyle(&f); //獲取字體樣式
_tcscpy(f.lfFaceName, _T("宋體")); //設定字體為宋體
f.lfQuality = ANTIALIASED_QUALITY; // 設定輸出效果為抗鋸齒
settextstyle(&f); // 設定字體樣式
settextcolor(BLACK);
while (1) {
cleardevice();
if (food.flag == 0) {
initFood(); //初始化食物
}
drawFood(); //畫食物
drawSnake(); //畫蛇
moveSnake(); //移動蛇
eatFood(); //吃食物
showGrade(); //顯示分數
if (snakeDead()) {
break;
}
if (_kbhit()) {
keyDown();
}
Sleep(snakeSpeed()); //蛇的速度
}
_getch();
closegraph();
system("pause");
return 0;
}
實驗結果
總體界面:

動態演示:

實際運動不會有痕跡,應該是gif格式的問題,
謝謝觀看~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/240471.html
標籤:其他
