0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語言項目:貪吃蛇游戲(雙人模式)!詳細(xì)思路+源碼分享

C語言編程學(xué)習(xí)基地 ? 來源:C語言編程學(xué)習(xí)基地 ? 2023-01-14 15:14 ? 次閱讀

每天一個C語言小項目,提升你的編程能力!

貪吃蛇游戲大家都玩過,它的玩法也很簡單:用游戲按鍵上下左右控制蛇的方向,尋找吃的東西,每吃一口就能得到一定的積分,而且蛇的身子會越吃越長,身子越長玩的難度就越大,不能碰墻,不能咬到自己的身體,更不能咬自己的尾巴,等到了一定的分?jǐn)?shù),就能過關(guān),然后繼續(xù)玩下一關(guān)。

7d3e5e98-8cd6-11ed-bfe3-dac502259ad0.png

不過我們今天要做的貪吃蛇就不是單人本了,你可以理解為C語言貪吃蛇的雙人模式——貪吃蛇游戲的雙人對戰(zhàn)版。

游戲雙方分別控制藍(lán)色和紅色兩條小蛇的前進(jìn),碰壁或咬到蛇身體算輸。

這個對戰(zhàn)版的貪吃蛇游戲網(wǎng)上有不少源代碼,這個代碼的特點就是為兩個游戲者分別增加了命令隊列,以實現(xiàn)更舒服的控制。

本項目編譯環(huán)境:Visual Studio 2019/2022,EasyX插件

代碼展示:

1.定義變量和游戲元素

#include 
#include 
#include 
#include 
#include 


using namespace std;


#define  WIDTH    64      // 游戲區(qū)域網(wǎng)格寬度
#define  HEIGHT    48      // 游戲區(qū)域網(wǎng)格高度
#define  ITEMSIZE  10      // 游戲元素大小
#define  CMD_A_UP  0x1      // 控制命令:游戲者 A 向上
#define  CMD_A_DOWN  0x2      // 控制命令:游戲者 A 向下
#define  CMD_A_LEFT  0x4      // 控制命令:游戲者 A 向左
#define  CMD_A_RIGHT  0x8      // 控制命令:游戲者 A 向右
#define  CMD_B_UP  0x10    // 控制命令:游戲者 B 向上
#define  CMD_B_DOWN  0x20    // 控制命令:游戲者 B 向下
#define  CMD_B_LEFT  0x40    // 控制命令:游戲者 B 向左
#define  CMD_B_RIGHT  0x80    // 控制命令:游戲者 B 向右
#define  CMD_QUIT  0x100    // 控制命令:退出游戲


// 定義游戲元素
enum ITEM { EMPTY = 0, WALL, PLAYER_A, PLAYER_B, PLAYER_DEAD, PLAYER_A_NEXT, PLAYER_B_NEXT };


// 全局變量
ITEM  g_world[WIDTH][HEIGHT];  // 保存游戲區(qū)
POINT  g_player_a;        // 游戲者 A 的坐標(biāo)
POINT  g_player_b;        // 游戲者 B 的坐標(biāo)
POINT  g_offset_a;        // 游戲者 A 的移動偏移方向
POINT  g_offset_b;        // 游戲者 B 的移動偏移方向

2.繪制游戲元素

void DrawItem(int x, int y, ITEM item)
{
  switch(item)
  {
    case EMPTY:      setfillcolor(BLACK);    break;
    case WALL:      setfillcolor(LIGHTGRAY);  break;
    case PLAYER_A:    setfillcolor(BLUE);      break;
    case PLAYER_B:    setfillcolor(RED);      break;
    case PLAYER_DEAD:  setfillcolor(MAGENTA);    break;
  }
  bar(x * ITEMSIZE + 1, y * ITEMSIZE + 1, (x + 1) * ITEMSIZE - 2, (y + 1) * ITEMSIZE - 2);
  g_world[x][y] = item;
}

3.初始化游戲(將游戲地圖和蛇給繪制出來)

void init()
{
  int x, y;


  // 繪制墻壁
  for(x = 0; x < WIDTH; x++)
  {
    DrawItem(x, 0, WALL);
    DrawItem(x, HEIGHT - 1, WALL);
  }
  for(y = 1; y < HEIGHT - 1; y++)
  {
    DrawItem(0, y, WALL);
    DrawItem(WIDTH - 1, y, WALL);
  }


  // 繪制游戲區(qū)域
  for (x = 1; x < WIDTH - 1; x++)
    for (y = 1; y < HEIGHT - 1; y++)
      DrawItem(x, y, EMPTY);


  // 隨機產(chǎn)生兩個游戲者的位置(至少間隔 5 格)
  do
  {
    g_player_a.x = rand() % (WIDTH - 6) + 3;  g_player_a.y = rand() % (HEIGHT - 6) + 3;
    g_player_b.x = rand() % (WIDTH - 6) + 3;  g_player_b.y = rand() % (HEIGHT - 6) + 3;
  }while (  (g_player_b.x - g_player_a.x) * (g_player_b.x - g_player_a.x)
      + (g_player_b.y - g_player_a.y) * (g_player_b.y - g_player_b.x) <= 25);
  // 畫出兩個游戲者的位置
  DrawItem(g_player_a.x, g_player_a.y, PLAYER_A);
  DrawItem(g_player_b.x, g_player_b.y, PLAYER_B);


  // 隨機產(chǎn)生兩個游戲者的移動方向
  // 該方法的原理詳見:http://www.easyx.cn/skills/View.aspx?id=115
  int n;
  n = (rand() % 4) * 2 + 1;  g_offset_a.x = n / 3 - 1;  g_offset_a.y = n % 3 - 1;
  n = (rand() % 4) * 2 + 1;  g_offset_b.x = n / 3 - 1;  g_offset_b.y = n % 3 - 1;


  // 繪制 Player A 空心方塊提示移動方向
  int tx = g_player_a.x + g_offset_a.x;
  int ty = g_player_a.y + g_offset_a.y;
  setcolor(BLUE);
  rectangle(tx * ITEMSIZE + 1, ty * ITEMSIZE + 1, (tx + 1) * ITEMSIZE - 2, (ty + 1) * ITEMSIZE - 2);
  // 繪制 Player B 空心方塊提示移動方向
  tx = g_player_b.x + g_offset_b.x;
  ty = g_player_b.y + g_offset_b.y;
  setcolor(RED);
  rectangle(tx * ITEMSIZE + 1, ty * ITEMSIZE + 1, (tx + 1) * ITEMSIZE - 2, (ty + 1) * ITEMSIZE - 2);


  // 按確定開始游戲
  MessageBox(GetHWnd(), _T("對戰(zhàn)貪吃蛇 游戲說明:

")     _T("游戲目標(biāo):兩條蛇,先碰到墻壁或碰到任何蛇的身體就算輸。
")     _T("Player A 使用 A S D W 控制藍(lán)色小蛇移動方向。
")     _T("Player B 使用上下左右控制紅色小蛇移動方向。

")     _T("點“確定”按鈕開始游戲。"), _T("游戲說明"), MB_OK | MB_ICONINFORMATION);
}

4.獲取游戲雙方(用戶)的按鍵指令

int GetCmd()
{
  // 定義兩個用戶的命令隊列
  static queue PLAYER_A_CMD;
  static queue PLAYER_B_CMD;


  // 定義每次返回的命令
  int cmd = 0;


  // 處理按鍵
  while(_kbhit())
  {
    switch(_getch())
    {
      case 27:        cmd = CMD_QUIT;  break;
      case 'W':  case 'w':  if (PLAYER_A_CMD.size() < 16)  PLAYER_A_CMD.push(CMD_A_UP);  break;
      case 'S':  case 's':  if (PLAYER_A_CMD.size() < 16)  PLAYER_A_CMD.push(CMD_A_DOWN);  break;
      case 'A':  case 'a':  if (PLAYER_A_CMD.size() < 16)  PLAYER_A_CMD.push(CMD_A_LEFT);  break;
      case 'D':  case 'd':  if (PLAYER_A_CMD.size() < 16)  PLAYER_A_CMD.push(CMD_A_RIGHT);  break;
      case ?0 :  case 0xE0:
        switch(_getch())
        {
          case 72:    if (PLAYER_B_CMD.size() < 16)  PLAYER_B_CMD.push(CMD_B_UP);  break;
          case 80:    if (PLAYER_B_CMD.size() < 16)  PLAYER_B_CMD.push(CMD_B_DOWN);  break;
          case 75:    if (PLAYER_B_CMD.size() < 16)  PLAYER_B_CMD.push(CMD_B_LEFT);  break;
          case 77:    if (PLAYER_B_CMD.size() < 16)  PLAYER_B_CMD.push(CMD_B_RIGHT);  break;
        }
    }
  }


  // 讀取 Player A 的命令
  int c = 0;
  while(!PLAYER_A_CMD.empty())
  {
    c = PLAYER_A_CMD.front();
    PLAYER_A_CMD.pop();
    if ((c == CMD_A_UP   || c == CMD_A_DOWN) ?&& g_offset_a.x != 0)  break;
    if ((c == CMD_A_LEFT || c == CMD_A_RIGHT) && g_offset_a.y != 0)  break;
  }
  if (c != 0)
    cmd |= c;


  // 讀取 Player B 的命令
  c = 0;
  while(!PLAYER_B_CMD.empty())
  {
    c = PLAYER_B_CMD.front();
    PLAYER_B_CMD.pop();
    if ((c == CMD_B_UP   || c == CMD_B_DOWN) ?&& g_offset_b.x != 0)  break;
    if ((c == CMD_B_LEFT || c == CMD_B_RIGHT) && g_offset_b.y != 0)  break;
  }
  if (c != 0)  cmd |= c;


  // 返回命令
  return cmd;
}

5.處理用戶指令

bool DealCmd(int cmd)
{
  if ((cmd & CMD_A_UP)  && g_offset_a.x != 0)  { g_offset_a.x = 0;    g_offset_a.y = -1;  }
  if ((cmd & CMD_A_DOWN)  && g_offset_a.x != 0)  { g_offset_a.x = 0;    g_offset_a.y = 1;  }
  if ((cmd & CMD_A_LEFT)  && g_offset_a.y != 0)  { g_offset_a.x = -1;  g_offset_a.y = 0;  }
  if ((cmd & CMD_A_RIGHT) && g_offset_a.y != 0)  { g_offset_a.x = 1;    g_offset_a.y = 0;  }
  if ((cmd & CMD_B_UP)  && g_offset_b.x != 0)  { g_offset_b.x = 0;    g_offset_b.y = -1;  }
  if ((cmd & CMD_B_DOWN)  && g_offset_b.x != 0)  { g_offset_b.x = 0;    g_offset_b.y = 1;  }
  if ((cmd & CMD_B_LEFT)  && g_offset_b.y != 0)  { g_offset_b.x = -1;  g_offset_b.y = 0;  }
  if ((cmd & CMD_B_RIGHT)  && g_offset_b.y != 0)  { g_offset_b.x = 1;    g_offset_b.y = 0;  }
  if (cmd & CMD_QUIT)
    if (MessageBox(GetHWnd(), _T("您要退出游戲嗎?"), _T("游戲暫停"), MB_OKCANCEL) == IDOK)
      return false;


  return true;
}

6.判斷蛇的狀態(tài)&游戲結(jié)束后的彈窗選擇

bool DealGame()
{
  // Player A、B 前進(jìn)
  g_player_a.x += g_offset_a.x;
  g_player_a.y += g_offset_a.y;
  g_player_b.x += g_offset_b.x;
  g_player_b.y += g_offset_b.y;


  // 判斷 Player A、B 的生死狀態(tài)
  bool dead_a = false, dead_b = false, dead_ab = false;


  if (g_player_a.x == g_player_b.x && g_player_a.y == g_player_b.y)
  {
    DrawItem(g_player_a.x, g_player_a.y, PLAYER_DEAD);
    dead_ab = true;
  }
  else if (g_world[g_player_a.x][g_player_a.y] != EMPTY)
  {
    DrawItem(g_player_a.x, g_player_a.y, PLAYER_DEAD);
    dead_a = true;
  }
  else if (g_world[g_player_b.x][g_player_b.y] != EMPTY)
  {
    DrawItem(g_player_b.x, g_player_b.y, PLAYER_DEAD);
    dead_b = true;
  }
  else
  {
    DrawItem(g_player_a.x, g_player_a.y, PLAYER_A);
    DrawItem(g_player_b.x, g_player_b.y, PLAYER_B);
    return true;
  }


  // 判斷是否要重新開始
  bool restart = false;


  if (dead_ab || (dead_a && dead_b))
    restart = MessageBox(GetHWnd(), _T("Player A 和 Player B 都死了。
要再來一局嗎?"),
              _T("GAME OVER"), MB_YESNO | MB_ICONINFORMATION) == IDYES;
  else if (dead_a)
    restart = MessageBox(GetHWnd(), _T("Player A 死了。
要再來一局嗎?"),
              _T("GAME OVER"), MB_YESNO | MB_ICONINFORMATION) == IDYES;
  else if(dead_b)
    restart = MessageBox(GetHWnd(), _T("Player B 死了。
要再來一局嗎?"),
              _T("GAME OVER"), MB_YESNO | MB_ICONINFORMATION) == IDYES;


  if (restart)
  {
    init();
    return true;
  }
  else
    return false;
}

7.補上入口函數(shù)

void main()
{
  initgraph(640, 480);
  srand((unsigned)time(NULL));


  // 初始化
  init();


  // 游戲主循環(huán)
  while(true)
  {
    int cmd = GetCmd();          // 獲取用戶命令
    if (!DealCmd(cmd))  break;      // 處理命令
    if (!DealGame())  break;      // 處理游戲
    Sleep(200);              // 延時
  }


  // 關(guān)閉繪圖窗口
  closegraph();
}

大家趕緊去動手試試吧!

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 游戲
    +關(guān)注

    關(guān)注

    2

    文章

    743

    瀏覽量

    26317
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7604

    瀏覽量

    136860
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3616

    瀏覽量

    93739
  • Visual
    +關(guān)注

    關(guān)注

    0

    文章

    252

    瀏覽量

    34264
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4788

    瀏覽量

    68625

原文標(biāo)題:C語言項目:貪吃蛇游戲(雙人模式)!詳細(xì)思路+源碼分享

文章出處:【微信號:cyuyanxuexi,微信公眾號:C語言編程學(xué)習(xí)基地】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    貪吃蛇游戲

    編的簡單的貪吃蛇游戲
    發(fā)表于 05-05 16:40

    貪吃蛇游戲

    貪吃蛇游戲的下載
    發(fā)表于 03-04 18:24

    基于51單片機c語言貪吃蛇游戲

    基于51單片機的C語言貪吃蛇游戲仿真
    發(fā)表于 11-25 21:05

    貪吃蛇游戲的電路實現(xiàn)

    最近論壇好冷清,在此發(fā)一貼暖暖身,回到正題,大家都玩過“貪吃蛇游戲,用代碼實現(xiàn)該游戲想必難不倒大神,在網(wǎng)上也有一大堆針對該游戲的代碼實現(xiàn),如果擺脫代碼,用硬件來實現(xiàn)“
    發(fā)表于 11-19 17:52

    貪吃蛇游戲

    Labview制作貪吃蛇游戲,值得學(xué)習(xí)研究
    發(fā)表于 09-07 21:39

    C語言寫個貪吃蛇游戲

    C語言寫個貪吃蛇游戲 貪吃蛇是個非常經(jīng)典的游戲,用C
    發(fā)表于 04-10 10:44

    【FPGA DEMO】Lab 9:貪吃蛇游戲

    ` 本帖最后由 zhangyue510 于 2021-7-30 16:32 編輯 項目名稱:貪吃蛇游戲具體要求:在Perf-V實現(xiàn)貪吃蛇游戲
    發(fā)表于 07-30 15:53

    基于stm32的貪吃蛇游戲的設(shè)計資料分享

    目錄前言一、主要功能二、主要模塊1.貪吃蛇鏈表2.ADC3.定時器中斷三、實際顯示效果前言自學(xué)完電阻觸摸屏之后做的小項目。我采用了C語言鏈表的方式來形成
    發(fā)表于 02-21 07:27

    貪吃蛇游戲設(shè)計貪吃蛇收尾基本完成

    電子發(fā)燒友網(wǎng)站提供《貪吃蛇游戲設(shè)計貪吃蛇收尾基本完成.rar》資料免費下載
    發(fā)表于 03-24 23:06 ?4次下載

    C語言教程之貪吃蛇游戲的問題

    C語言教程之貪吃蛇游戲的問題,很好的C語言資料,快來學(xué)習(xí)吧。
    發(fā)表于 04-25 17:07 ?0次下載

    貪吃蛇游戲java源代碼

    貪吃蛇游戲java源代碼
    發(fā)表于 12-27 17:56 ?9次下載

    使用C語言設(shè)計貪吃蛇詳細(xì)資料合集(程序,應(yīng)用軟件,設(shè)計思路)免費下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用C語言設(shè)計貪吃蛇詳細(xì)資料合集(程序,應(yīng)用軟件,設(shè)計思路)免費下
    發(fā)表于 09-14 17:50 ?22次下載
    使用<b class='flag-5'>C</b><b class='flag-5'>語言</b>設(shè)計<b class='flag-5'>貪吃蛇</b>的<b class='flag-5'>詳細(xì)</b>資料合集(程序,應(yīng)用軟件,設(shè)計<b class='flag-5'>思路</b>)免費下載

    基于LabVIEW的貪吃蛇游戲源代碼

    基于LabVIEW的貪吃蛇游戲源代碼
    發(fā)表于 04-22 09:27 ?74次下載

    如何用C語言實現(xiàn)貪吃蛇游戲項目

    ? 這篇文章主要為大家詳細(xì)介紹了 C語言實現(xiàn)——《貪吃蛇項目》 ,文中示例代碼介紹的非常詳細(xì),具
    的頭像 發(fā)表于 11-09 16:38 ?2455次閱讀

    基于stm32的貪吃蛇游戲

    目錄前言一、主要功能二、主要模塊1.貪吃蛇鏈表2.ADC3.定時器中斷三、實際顯示效果前言 自學(xué)完電阻觸摸屏之后做的小項目。我采用了C語言鏈表的方式來形成
    發(fā)表于 12-24 19:32 ?21次下載
    基于stm32的<b class='flag-5'>貪吃蛇</b>小<b class='flag-5'>游戲</b>