最浪漫的編程代碼:貪吃蛇c++代碼詳解

1 貪吃蛇效果展示

前言:C語言初學者都是在控制台上開發一些小遊戲什麼,由於沒有界面(比如圖片、音樂,不能做出擁有自己風格的程序)學起來比較乏味,很難堅持下去。所以我在這裡就教大家使用簡單的圖形化工具——easyx圖形界面庫,做一些好玩的,超絲滑的貪吃蛇

這麼絲滑的蛇蛇你做過嗎?四步即可完成C語言超絲滑貪吃蛇

2 背景知識

開發貪吃蛇小遊戲,讓初學者也能感受界面的魅力。做的不是很完善,希望大家可以自己動手完善它表白程序設計原理:

第一步,我們需要一張地圖,圖形庫初始化的窗口是自帶坐標的(左上角為0,0)。

第二步,我們需要一條蛇,這條蛇由蛇頭和蛇身組成(這裡我們初始化三節蛇)。

第三步,我們需要食物,並且在蛇吃掉食物之後將蛇的身體變長,而且重新生成一個食物。

第四步,蛇需要移動,這應該是最難實現的(實現蛇身坐標的傳值,除蛇頭以外,每一節蛇的坐標都是上節蛇的上一次運動之前的坐標,有點繞~)。

第五步,我們需要能用鍵盤控制蛇的運動方向,這個會和蛇的移動有一些聯繫。

第六步,蛇撞到牆或者撞到自己的身體就會死亡(判斷坐標是否重合就可以)。

3 錯誤及決絕方案

此程序使用Vs209+easyx開發。剛開始學習C語言或者沒接觸過easyx的夥伴,拿到代碼之後肯定有很多的錯誤,這就是所謂的給了源碼也不能運行,所以配置環境和查看報錯也是作為編程學習者,必須要掌握的技能。相關知識的基礎講解可觀看專欄教程:

4. 話不多說上代碼

4.1 頭文件snake.h

我們把一些函數的聲明,和結構體的定義放在頭文件中:

#ifndef _SNAKE_H_
#define _SNAKE_H_
#include<graphics.h>
#include<conio.h>
#include<stdio.h>
#include<time.h>
#define WIN_WIDTH 640 //窗口寬高
#define WIN_HEIGHT 480
#define MAX_SNAKE 10000 //蛇的最大節數
enum DIR //蛇的方向
{
 UP,
 DOWN,
 LEFT,
 RIGHT,
};
//每一節蛇的位置信息
typedef struct _Pos
{
 int x;
 int y;
 DWORD color;
}Pos;
typedef struct Snake_tlg //蛇的結構體
{
 int num;
 int dir;//蛇的方向
 int score;//分數
 int size;//蛇的寬度和高度
 int speed;//移動速度
 Pos coor[MAX_SNAKE];
}Snake;
typedef struct Food_tlg
{
 int x;
 int y;
 int r;
 int flag;
 DWORD color;
}Food;
//畫眼睛函數
void DrawEye(int x, int y);
//初始化數據
void GameInit();
//遊戲的繪製
void GameDraw();
//蛇的移動
void SnakeMove();
//控制方向
void KeyControl();
//吃食物
void EatFood();
//暫停遊戲 按空格暫停和繼續
void stop();
//定時器
bool Timer(clock_t ms);
#endif

4.2 實現文件snake.cpp

OK,頭文件部分完畢,接下來進入snake.cpp代碼編寫環節。

#include"snake.h"
Snake snake;
Food food;
//畫眼睛函數
void DrawEye(int x, int y)
{
 setfillcolor(WHITE);
 solidcircle(x, y, 3);
 setfillcolor(BLACK);
 solidcircle(x, y, 2);
}
void GameInit()
{
 srand(GetTickCount());
 //初始化蛇
 snake.num = 10;
 snake.dir = RIGHT;
 snake.score = 0;
 snake.size = 10;
 snake.speed = 1;
 snake.coor[0].x = 20;
 snake.coor[0].y = 10;
 for (int i = 0; i < snake.num; i++)
 {
  snake.coor[i].color = GREEN;
 }
 //初始化食物
 food.x = rand() % (WIN_WIDTH - 10);
 food.y = rand() % (WIN_HEIGHT - 10);
 food.flag = 1;
 food.r = rand() % 3 + 2;
 food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
}
void GameDraw()
{
 //設置背景顏色
 setbkcolor(RGB(191, 215, 215));
 cleardevice();
 //畫蛇 
 for (int i = 0; i < snake.num; i++)
 {
  setfillcolor(snake.coor[i].color);
  solidcircle(snake.coor[i].x, snake.coor[i].y, snake.size / 2);
 }
 //畫眼睛
 int eyewidth = 5;
 switch (snake.dir)
 {
 case UP:
 case DOWN:
  DrawEye(snake.coor[0].x - eyewidth, snake.coor[0].y);
  DrawEye(snake.coor[0].x + eyewidth, snake.coor[0].y);
  break;
 case LEFT:
 case RIGHT:
  DrawEye(snake.coor[0].x, snake.coor[0].y - eyewidth);
  DrawEye(snake.coor[0].x, snake.coor[0].y + eyewidth);
  break;
 }
 //畫食物
 if (food.flag == 1)
 {
  setfillcolor(food.color);
  solidcircle(food.x, food.y, food.r);
 }
 //顯示分數
 char temp[20] = "";
 sprintf(temp, "分數:%d", snake.score);
 setbkmode(TRANSPARENT);
 outtextxy(20, 20, temp);
}
void SnakeMove()
{
 for (int i = snake.num - 1; i > 0; i--)//從最後一節蛇開始,每一節蛇都等於前一節蛇的上一次坐標
 {
  snake.coor[i].x = snake.coor[i - 1].x;
  snake.coor[i].y = snake.coor[i - 1].y;
 }
 //根據方向移動
 switch (snake.dir)
 {
 case UP:
  snake.coor[0].y -= snake.speed;
  if (snake.coor[0].y + 10 <= 0)
  {
   snake.coor[0].y = WIN_HEIGHT;
  }
  break;
 case DOWN:
  snake.coor[0].y += snake.speed;
  if (snake.coor[0].y - 10 >= WIN_HEIGHT)
  {
   snake.coor[0].y = 0;
  }
  break;
 case LEFT:
  snake.coor[0].x -= snake.speed;
  if (snake.coor[0].x + 10 <= 0)
  {
   snake.coor[0].x = WIN_WIDTH;
  }
  break;
 case RIGHT:
  snake.coor[0].x += snake.speed;
  if (snake.coor[0].x - 10 >= WIN_WIDTH)
  {
   snake.coor[0].x = 0;
  }
  break;
 }

}
void KeyControl()
{
 //使用win32API獲取鍵盤消息
 if (GetAsyncKeyState(VK_UP) && snake.dir != DOWN)
 {
  snake.dir = UP;
 }
 if (GetAsyncKeyState(VK_DOWN) && snake.dir != UP)
 {
  snake.dir = DOWN;
 }
 if (GetAsyncKeyState(VK_LEFT) && snake.dir != RIGHT)
 {
  snake.dir = LEFT;
 }
 if (GetAsyncKeyState(VK_RIGHT) && snake.dir != LEFT)
 {
  snake.dir = RIGHT;
 }
 //按A鍵加速,不按回復初始狀態
 if (GetAsyncKeyState('A') && snake.speed == 1)
 {
  snake.speed = 5;
 }
 else if (snake.speed == 5)
 {
  snake.speed = 1;
 }
}
void EatFood()
{
 if (snake.coor[0].x >= food.x - food.r && snake.coor[0].x <= food.x + food.r &&
  snake.coor[0].y >= food.y - food.r && snake.coor[0].y <= food.y + food.r &&
  food.flag == 1)
 {
  snake.num += 5;
  snake.score += 10;
  food.flag = 0;
  //每一節的顏色都要初始化
  for (int i = snake.num - 5; i < snake.num; i++)
  {
   snake.coor[i].color = food.color;
  }
 }
 if (food.flag == 0)
 {
  food.x = rand() % (WIN_WIDTH - 10);
  food.y = rand() % (WIN_HEIGHT - 10);
  food.flag = 1;
  food.r = rand() % 10 + 3;
  food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
 }
}
void stop()
{
 if (_kbhit() && _getch() == 32)
 {
  while (getch() != 32);
 }
}
bool Timer(clock_t ms)
{
 static clock_t t = clock();
 if (clock() - t > ms)
 {
  t = clock();
  return true;
 }
 return false;
}

4.3 測試文件main.cpp

最後我們一起來測試一下吧

#include"snake.h"
int main()
{
 //創建一個圖形窗口
 initgraph(WIN_WIDTH, WIN_HEIGHT);
 GameInit();
 BeginBatchDraw();//①
 while (1)
 {
  if(Timer(10))
  {
   SnakeMove();
  } 
  GameDraw();
  FlushBatchDraw();//②
  EatFood();
  KeyControl();
  stop();
 }
 EndBatchDraw();//③    ①②③為雙緩衝繪圖防止閃屏代碼
 //關閉圖形窗口
 closegraph();
 return 0;
}

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/222047.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-09 13:26
下一篇 2024-12-09 13:26

相關推薦

發表回復

登錄後才能評論