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

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

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

C語(yǔ)言實(shí)現(xiàn)推箱子游戲!代碼思路+源碼分享

C語(yǔ)言編程學(xué)習(xí)基地 ? 來(lái)源:C語(yǔ)言編程學(xué)習(xí)基地 ? 作者:童晶 ? 2022-11-29 16:22 ? 次閱讀

經(jīng)典的推箱子是一個(gè)很古老的游戲了,相信大家都不陌生。其目的是在訓(xùn)練我們的邏輯思考能力。在一個(gè)狹小的倉(cāng)庫(kù)中,要求把木箱放到指定的位置,稍不小心就會(huì)出現(xiàn)箱子無(wú)法移動(dòng)或者通道被堵住的情況,所以需要巧妙的利用有限的空間和通道,合理安排移動(dòng)的次序和位置,才能順利的完成任務(wù)。

我們將編寫(xiě)推箱子游戲,玩家鍵盤(pán)控制游戲角色將所有黃色箱子推到白色方塊處,效果如圖所示:

da8b0848-6fbd-11ed-8abf-dac502259ad0.png

操作方法:方向鍵↑↓←→控制移動(dòng)推箱子,將箱子推到對(duì)應(yīng)位置。

首先學(xué)習(xí)字符串與字符數(shù)組的概念,并應(yīng)用字符數(shù)組初始化關(guān)卡數(shù)據(jù);然后利用鍵盤(pán)控制游戲角色移動(dòng),實(shí)現(xiàn)地圖元素更新和游戲勝利的判斷;接著利用三維字符數(shù)組,實(shí)現(xiàn)多關(guān)卡的游戲;最后學(xué)習(xí)基于文件的關(guān)卡數(shù)據(jù)讀取,利用枚舉類型改進(jìn)游戲代碼。

源碼:

#include   
#include 
#include 
#define B_SIZE 60 // 方塊大小
#define B_NUM 8 // 方塊個(gè)數(shù),一共8*8個(gè)方塊


struct Player // 結(jié)構(gòu)體,用于記錄玩家位置
{
  int i;
  int j;
};
Player player; // 玩家全局變量


enum Element // 定義枚舉類型,小方塊所有的可能的種類
{
  wall,target,box,empty,achieved,role
};


// 用于存儲(chǔ)地圖數(shù)據(jù),用枚舉類型實(shí)現(xiàn)
Element level[B_NUM][B_NUM] = 
{{wall,wall,wall,wall,wall,wall,wall,wall},
{wall,wall,wall,target,box,empty,empty,wall},
{wall,empty,empty,empty,empty,empty,empty,wall},
{wall,empty,empty,empty,empty,empty,empty,wall},
{wall,empty,empty,empty,empty,empty,empty,wall},
{wall,role,empty,box,target,wall,wall,wall},
{wall,empty,empty,empty,empty,wall,wall,wall},
{wall,wall,wall,wall,wall,wall,wall,wall}};


int targetNum,achievedNum; // 目標(biāo)位置個(gè)數(shù)、完成目標(biāo)個(gè)數(shù)


void startup()  // 初始化函數(shù)
{
  initgraph(B_NUM*B_SIZE,B_NUM*B_SIZE); // 新開(kāi)一個(gè)畫(huà)面
  setbkcolor(RGB(150,150,150)); // 灰色背景
  BeginBatchDraw(); // 開(kāi)始批量繪圖
  int i,j;
  targetNum = 0; // 目標(biāo)個(gè)數(shù),初始為0
  // 對(duì)二維數(shù)組遍歷
  for (i=0;i
    for (j=0;j
    {
      if (level[i][j]==role) // 找到地圖中player位置
      {
        player.i = i; // 設(shè)定player位置
        player.j = j; // 
        level[i][j]=empty; // 把地圖元素變成空白empty
      }
      else if (level[i][j]==target || level[i][j]==achieved ) // 如果元素是target或achieved
        targetNum++; // 目標(biāo)個(gè)數(shù)+1
    }
}


void show() // 繪制函數(shù)
{
  int i,j;
  cleardevice(); // 以背景顏色清空屏幕
  // 遍歷關(guān)卡二維數(shù)組數(shù)據(jù)
  for (i=0;i
  {
    for (j=0;j
    {
      if (level[i][j]==empty) // empty 元素是空白區(qū)域
      {
        setfillcolor(RGB(150,150,150)); // 繪制灰色地面
        setlinecolor(RGB(150,150,150));
        fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
      }
      else if (level[i][j]==wall)  // wall 元素是墻
      {
        setfillcolor(RGB(155,0,0));
        setlinecolor(RGB(150,150,150)); // 繪制淡紅色、灰色線的方框
        fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
      }
      else if (level[i][j]==box) // box 元素是可移動(dòng)的箱子
      {
        setfillcolor(RGB(255,255,0)); // 繪制一個(gè)黃色的方塊
        setlinecolor(RGB(150,150,150));
        fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
      }
      else if (level[i][j]==target) // target 元素是目標(biāo)
      {
        setfillcolor(RGB(250,250,250)); // 繪制一個(gè)白色的小方塊
        fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
          (j+0.7)*B_SIZE,(i+0.7)*B_SIZE);
      }
      else if (level[i][j]==achieved) // achieved 元素是已完成目標(biāo)
      {
        setlinecolor(RGB(150,150,150));
        setfillcolor(RGB(255,255,0)); // 繪制一個(gè)黃色的方塊
        fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
        setfillcolor(RGB(250,250,250)); // 繪制一個(gè)白色的小方塊
        fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
          (j+0.7)*B_SIZE,(i+0.7)*B_SIZE);
      }    
    }
  }
  // 以下繪制玩家,繪制一個(gè)人臉圖案
  i = player.i; 
  j = player.j;
  setfillcolor(RGB(255,0,0));
  fillcircle((j+0.5)*B_SIZE,(i+0.5)*B_SIZE,0.4*B_SIZE);//一個(gè)紅色圓臉
  setfillcolor(RGB(80,80,80));
  setlinecolor(RGB(80,80,80));
  fillcircle((j+0.3)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE);//兩個(gè)黑色眼睛
  fillcircle((j+0.7)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE); 
  setlinestyle(PS_SOLID,3);
  line((j+0.35)*B_SIZE,(i+0.7)*B_SIZE,(j+0.65)*B_SIZE,(i+0.7)*B_SIZE);//深灰色嘴巴
  setlinestyle(PS_SOLID,1);


  if (achievedNum==targetNum) // 如完成目標(biāo)個(gè)數(shù)==目標(biāo)個(gè)數(shù)
  {
    setbkmode(TRANSPARENT); // 透明顯示文字
    settextcolor(RGB(0,255,255)); // 設(shè)置字體顏色
    settextstyle(80, 0, _T("宋體")); // 設(shè)置字體大小、樣式
    outtextxy(80,200,_T("游戲勝利")); // 顯示游戲勝利文字
  }
  FlushBatchDraw(); // 開(kāi)始批量繪制
}


void update()  // 每幀更新運(yùn)行
{
  if(kbhit() && (achievedNum// 如果按鍵,并且游戲沒(méi)有勝利
  {
    char input = getch(); // 獲取按鍵
    if (input=='a' || input=='s' || input=='d' || input=='w') // 如果是有效按鍵
    {
      int goal_i = player.i; // 移動(dòng)的目標(biāo)位置
      int goal_j = player.j;
      int goalNext_i = goal_i; // 目標(biāo)位置再向前的一個(gè)位置
      int goalNext_j = goal_j;
      // 根據(jù)用戶的不同按鍵輸入,獲得目標(biāo)位置、再向前的一個(gè)位置
      if (input=='a') // 向左
      {
        goal_j = player.j -1 ; // 目標(biāo)位置在玩家位置的左邊
        goalNext_j = goal_j-1; // 目標(biāo)的下一個(gè)位置,在其再左邊
      }
      else if (input=='d') // 向右
      {
        goal_j = player.j +1 ; // 目標(biāo)位置在玩家位置的右邊 
        goalNext_j = goal_j+1; // 目標(biāo)的下一個(gè)位置,在其再右邊
      }
      else if (input=='s') // 向下
      {
        goal_i = player.i+1; // 目標(biāo)位置在玩家位置的下邊 
        goalNext_i = goal_i+1; // 目標(biāo)的下一個(gè)位置,在其再下邊 
      }
      else if (input=='w') // 向上
      {
        goal_i = player.i-1; // 目標(biāo)位置在玩家位置的上邊 
        goalNext_i = goal_i-1; // 目標(biāo)的下一個(gè)位置,在其再上邊 
      }


      // 根據(jù)不同地圖元素的情況,判斷如何移動(dòng)角色和更新地圖元素  
      if (level[goal_i][goal_j]==empty || level[goal_i][goal_j]==target ) 
      {  // 如果目標(biāo)位置是empty,或者target
        player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
        player.j = goal_j;        
      }
      else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==empty ) 
      {  // 如果目標(biāo)位置是box,再前面一個(gè)是empty
        player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
        player.j = goal_j;    
        level[goal_i][goal_j]=empty;  // 目標(biāo)位置變成empty
        level[goalNext_i][goalNext_j]=box;   // 再前面變成box
      }
      else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==target) 
      {  // 如果目標(biāo)位置是box,再前面一個(gè)是target
        player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
        player.j = goal_j;  
        level[goal_i][goal_j] = empty;  // 目標(biāo)位置變成empty 
        level[goalNext_i][goalNext_j] = achieved;  // 再前面變成achieved
      }
      else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== empty) 
      {  // 如果目標(biāo)位置是achieved,再前面一個(gè)是empty
        player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
        player.j = goal_j;    
        level[goal_i][goal_j] = target;  // 目標(biāo)位置變成target 
        level[goalNext_i][goalNext_j] = box; // 再前面變成box   
      }
      else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== target) 
      {  // 如果目標(biāo)位置是achieved,再前面一個(gè)是target
        player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
        player.j = goal_j;
        level[goal_i][goal_j] = target;  // 目標(biāo)位置變成target  
        level[goalNext_i][goalNext_j] = achieved; // 再前面變成achieved    
      }
      else // 其他情況都推不動(dòng)
        return; // 不做任何處理,函數(shù)直接返回
    }
    achievedNum = 0; // 完成目標(biāo)個(gè)數(shù),初始為0
    int i,j;
    for (i=0;i// 對(duì)二維數(shù)組遍歷
      for (j=0;j// 
        if (level[i][j]==achieved) // 如果元素是achieved
          achievedNum++; // 完成目標(biāo)個(gè)數(shù)+1
  }
}


int main() // 主函數(shù)
{
  startup();  // 初始化  
  while (1)  // 游戲主循環(huán)
  {
    show();    // 繪制
    update();   // 更新
  }
  return 0;
}

主要講解了字符串與字符數(shù)組、文件讀寫(xiě)、枚舉類型等語(yǔ)法知識(shí),實(shí)現(xiàn)了推箱子游戲。讀者可以嘗試在本章代碼基礎(chǔ)上繼續(xù)改進(jìn):

1、實(shí)現(xiàn)多關(guān)卡的選擇界面;

2、實(shí)現(xiàn)某一步移動(dòng)的撤銷功能(類似于下棋游戲中的悔棋功能);

3、實(shí)現(xiàn)按'h'鍵后進(jìn)行提示,播放正確步驟動(dòng)畫(huà)的功能;

4、實(shí)現(xiàn)一個(gè)圖形編輯器,并將設(shè)計(jì)的關(guān)卡信息保存為txt文件。

審核編輯 :李倩


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

    關(guān)注

    180

    文章

    7581

    瀏覽量

    135549
  • 編輯器
    +關(guān)注

    關(guān)注

    1

    文章

    798

    瀏覽量

    31011

原文標(biāo)題:C語(yǔ)言實(shí)現(xiàn)推箱子游戲?。ǔ?jiǎn)單詳細(xì))代碼思路+源碼分享

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

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    hex文件如何查看原c語(yǔ)言代碼

    直接將 .hex 文件轉(zhuǎn)換回原始的 C 語(yǔ)言代碼是不可能的,因?yàn)?.hex 文件是二進(jìn)制文件,它包含了單片機(jī)程序編譯后的機(jī)器碼,這些機(jī)器碼與原始的 C
    的頭像 發(fā)表于 09-02 10:37 ?734次閱讀

    如何用C語(yǔ)言實(shí)現(xiàn)高效查找(二分法)

    今天給分享一下使用C語(yǔ)言實(shí)現(xiàn)二分算法,主要包含以下幾部分內(nèi)容:二分查找算法介紹二分查找算法使用場(chǎng)景二分查找算法代碼實(shí)現(xiàn)二分查找算法實(shí)現(xiàn)過(guò)程用
    的頭像 發(fā)表于 06-04 08:04 ?825次閱讀
    如何用<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言實(shí)現(xiàn)</b>高效查找(二分法)

    使用C語(yǔ)言實(shí)現(xiàn)的CRC計(jì)算單元的例子

    使用C語(yǔ)言實(shí)現(xiàn)的CRC計(jì)算單元的例子
    的頭像 發(fā)表于 05-16 16:16 ?744次閱讀

    C語(yǔ)言實(shí)現(xiàn)Web參數(shù)傳遞

    電子發(fā)燒友網(wǎng)站提供《C語(yǔ)言實(shí)現(xiàn)Web參數(shù)傳遞.docx》資料免費(fèi)下載
    發(fā)表于 03-24 09:14 ?2次下載

    ADUC7061如何使用C語(yǔ)言實(shí)現(xiàn)EEPROM功能?

    我使用ADUC7061做的信號(hào)采集,現(xiàn)在客戶需要實(shí)現(xiàn)EEPROM功能來(lái)保存3-5個(gè)數(shù)據(jù),請(qǐng)問(wèn)如何使用C語(yǔ)言實(shí)現(xiàn)?不使用外部EEPROM 專用IC。
    發(fā)表于 01-12 06:56

    怎么寫(xiě)出效率高、思路清晰的C語(yǔ)言程序?

    要用C語(yǔ)言的思維方式來(lái)進(jìn)行程序的構(gòu)架構(gòu)建 要有良好的C語(yǔ)言算法基礎(chǔ),以此來(lái)實(shí)現(xiàn)程序的邏輯構(gòu)架 靈活運(yùn)用
    的頭像 發(fā)表于 01-02 14:20 ?489次閱讀

    php的源碼是什么開(kāi)源語(yǔ)言

    PHP的源碼是用C語(yǔ)言編寫(xiě)的,是一種開(kāi)源的服務(wù)器端腳本語(yǔ)言。下面是關(guān)于PHP源碼的詳細(xì)介紹。 一、PHP簡(jiǎn)介 PHP(全稱:PHP: Hyp
    的頭像 發(fā)表于 12-04 16:11 ?1537次閱讀

    如何利用緩存讓CPU更有效率地執(zhí)行代碼?

    我們先來(lái)看一個(gè)很經(jīng)典的例子(例子是C語(yǔ)言寫(xiě)的,其他語(yǔ)言實(shí)現(xiàn)也都是差不多的)
    的頭像 發(fā)表于 12-04 15:01 ?792次閱讀
    如何利用緩存讓CPU更有效率地執(zhí)行<b class='flag-5'>代碼</b>?

    c語(yǔ)言怎么把代碼全部注釋掉

    要將C語(yǔ)言代碼全部注釋掉,即不讓代碼被編譯和執(zhí)行,可以使用注釋語(yǔ)句來(lái)實(shí)現(xiàn)C
    的頭像 發(fā)表于 11-22 10:21 ?6022次閱讀

    C語(yǔ)言課程設(shè)計(jì)案例精編-源碼

    電子發(fā)燒友網(wǎng)站提供《C語(yǔ)言課程設(shè)計(jì)案例精編-源碼.rar》資料免費(fèi)下載
    發(fā)表于 11-21 10:39 ?1次下載
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>課程設(shè)計(jì)案例精編-<b class='flag-5'>源碼</b>

    C語(yǔ)言游戲源碼大放送

    電子發(fā)燒友網(wǎng)站提供《C語(yǔ)言游戲源碼大放送.rar》資料免費(fèi)下載
    發(fā)表于 11-21 10:36 ?1次下載
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>小<b class='flag-5'>游戲</b><b class='flag-5'>源碼</b>大放送

    178個(gè)C語(yǔ)言算法源碼下載

    電子發(fā)燒友網(wǎng)站提供《178個(gè)C語(yǔ)言算法源碼下載.zip》資料免費(fèi)下載
    發(fā)表于 11-21 09:35 ?3次下載
    178個(gè)<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>算法<b class='flag-5'>源碼</b>下載

    C語(yǔ)言實(shí)用程序150例

    電子發(fā)燒友網(wǎng)站提供《C語(yǔ)言實(shí)用程序150例.rar》資料免費(fèi)下載
    發(fā)表于 11-20 11:37 ?1次下載
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言實(shí)</b>用程序150例

    C語(yǔ)言指紋識(shí)別源碼分享

    電子發(fā)燒友網(wǎng)站提供《C語(yǔ)言指紋識(shí)別源碼分享.rar》資料免費(fèi)下載
    發(fā)表于 11-18 14:50 ?1次下載
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>指紋識(shí)別<b class='flag-5'>源碼</b>分享

    基于VHDL語(yǔ)言實(shí)現(xiàn)遠(yuǎn)程防盜報(bào)警設(shè)計(jì)

    電子發(fā)燒友網(wǎng)站提供《基于VHDL語(yǔ)言實(shí)現(xiàn)遠(yuǎn)程防盜報(bào)警設(shè)計(jì).pdf》資料免費(fèi)下載
    發(fā)表于 11-08 14:33 ?0次下載
    基于VHDL<b class='flag-5'>語(yǔ)言實(shí)現(xiàn)</b>遠(yuǎn)程防盜報(bào)警設(shè)計(jì)