箱子小游戲簡易實現

      網友投稿 695 2022-05-29

      很早就想過做點小游戲了,但是一直沒有機會動手。今天閑來無事,動起手來。過程還是蠻順利的,代碼也不是非常難。今天給大家分享一下~

      1

      2

      3

      4

      也不說太多多余的話了,先看一下效果圖:

      游戲中的人物、箱子、墻壁、球都是字符構成的。通過wasd鍵移動,規則的話就是推箱子的規則,也就不多說了。

      關于代碼方面,我盡可能講的細致。希望大家可以理解~

      //主函數 void main(); //初始化一些數據 initData(); //在控制臺上打印地圖 drawMap(); //向上移動 moveUp(); //向左移動 moveLeft() //向下移動 moveDown() //向右移動 moveRight();

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      這幾個方法都顧名思義,而且用意也非常明確,就initData可能不知道具體用處,但是沒有什么大問題。唯一的問題就是,上左下右的順序可能會逼死幾個強迫癥患者,哈哈。

      為了方便,我把include和宏定義也放到參數列表當中

      //導入函數庫 #include #include #include //宏定義 #define WIDTH 8 #define HEIGHT 8 //定義地圖數組,二維數組有兩個維度,而地圖也是二維的矩形 int map[HEIGHT][WIDTH] = { {0, 0, 1, 1, 1, 0, 0, 0}, {0, 0, 1, 4, 1, 0, 0, 0}, {0, 0, 1, 0, 1, 1, 1, 1}, {1, 1, 1, 3, 0, 3, 4, 1}, {1, 4, 0, 3, 2, 1, 1, 1}, {1, 1, 1, 1, 3, 1, 0, 0}, {0, 0, 0, 1, 4, 1, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0} }; //人的位置,在二維地圖中,我們可以用坐標表示一個人的位置,就好比經緯度 int x, y; //箱子的個數,推箱子肯定要有箱子嘛。 int boxs;

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      這里參數不多,其中橫為x,縱為y,另外這里再規定一下map的一些東西:

      /** * 0 表示空 * 1 表示墻 * 2 表示人 * 3 表示箱子 * 4 表示目的地(球) * 5 表示已完成的箱子 */

      1

      2

      3

      4

      5

      6

      7

      8

      接下來我們一個一個函數來分析。

      main函數

      int main(int argc, char *argv[]) { char direction; //存儲鍵盤按的方向 initData(); //初始化一些數據 //開始游戲的循環,這里是個死循環,每按一次按鈕循環一次 while(1){ //每次循環的開始清除屏幕 system("cls"); //繪畫地圖 drawMap(); //判斷,當boxs的數量0時,!0為真,然后走break跳出循環(結束游戲) if(!boxs){ break; } //鍵盤輸入方向,這里使用getch,因為getch讀取字符不會顯示在屏幕上 direction = getch(); //用switch判斷用戶輸入的方向 switch(direction){ case 'w': //按w時,調用向上移動函數 moveUp(); break; case 'a': //按a時,調用向左移動函數 moveLeft(); break; case 's': moveDown(); break; case 'd': moveRight(); break; } } //當跳出循環時,運行該語句,游戲結束 printf("恭喜你完成游戲!※"); return 0; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      我大概說一下流程,循環外面沒有什么特別的。initData()只是一些簡單數據的初始化,不需要太在意。循環中大致流程如下:

      清除屏幕

      繪制地圖

      判斷游戲是否結束

      對用戶按下的按鈕進行反饋

      進入循環體,先清除屏幕,再繪制地圖,然后再判斷游戲是否結束。可能大家對這個順序不是很理解,這里我們先不考慮判斷游戲結束的問題。我們把清屏和繪制地圖合在一起,簡稱“重繪地圖”,而游戲結束的判斷先不考慮,那么流程就簡化為“重繪地圖 + 響應用戶的操作”。簡單來說就是,用戶按一下按鈕,我改變一下地圖。

      initData()

      void initData(){ int i, j; //加載數據時讓用戶等待,一般情況加載數據比較快 printf("游戲加載中,請稍后........."); //遍歷地圖中的數據 for(i = 0; i < HEIGHT; i++){ for(j = 0; j < WIDTH; j++){ //遍歷到2(人)時,記錄人的坐標。x, y是前面定義的全局變量 if(map[i][j] == 2){ x = j; y = i; } //遍歷到3時,箱子的數目增加。boxs是前面定義的全局變量 if(map[i][j] == 3){ boxs++; } } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      這個方法很簡單,就是遍歷地圖,然后初始化人的位置和箱子的個數。這里有一點要注意一下,就是到底內層循環是

      WIDTH還是外層循環是WIDTH。

      如圖,在遍歷過程中。外層循環控制行數,即HEIGHT。那么內層循環應該是WIDTH。

      drawMap()

      void drawMap(){ int i, j; for(i = 0; i < WIDTH; i++){ for(j = 0; j < HEIGHT; j++){ switch(map[i][j]){ case 0: printf(" "); break; case 1: printf("■"); break; case 2: printf("♀"); break; case 3: printf("◆"); break; case 4: printf("●"); break; case 5: printf("★"); break; } } printf("\n"); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      這里也非常簡單,變量map中的元素,然后通過switch判斷應該輸出的內容。然后內層循環每走完一次就換行。

      moveUp()

      這個函數內容有點多,想講一下大概思路:

      向上移有兩種情況 1、前面為空白 這種情況有兩個步驟 (1)將人當前的位置設置為空白(0), (2)再講人前面的位置設置為人(2) 2、前面為箱子 當前面為箱子時有三種情況 1、箱子前面為空白 移動人和箱子,這個操作有三個步驟 (1)將人當前位置設置為空(0) (2)將箱子位置設置為人(2) (3)將箱子前面設置為箱子(3) 2、箱子前面為墻 這種情況不需要做任何操作 3、箱子前面為終點 這種情況有四個個步驟 (1)將人的位置設置為空(0) (2)將箱子的位置設置為人(2) (3)將終點位置設置為★(5) (4)箱子boxs的數量減一 3、前面為墻 這種情況最簡單,不需要做任何操作 4、前面為終點 我這里沒有考慮太多,這種情況不做操作。(如果更換地圖的話可能需要修改代碼)

      推箱子小游戲的簡易實現

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      具體代碼如下,解析我全寫在注釋里面:

      void moveUp(){ //定義變量存放人物上方的坐標 int ux, uy; //當上方沒有元素時,直接return (其實人不可能在邊緣) if(y == 0){ return; } //記錄上方坐標,x為橫,y為縱,所有ux = x, uy = y - 1; ux = x; uy = y - 1; //上方為已完成的箱子 if(map[uy][ux] == 5){ return; } //假設上方為墻,直接return,這個和上面的判斷可以合在一起,這里為了看清楚分開寫 if(map[uy][ux] == 1){ return; } //假設上方為箱子 if(map[uy][ux] == 3){ //判斷箱子上方是否為墻 if(map[uy - 1][ux] == 1){ return; } //判斷箱子上方是否為終點 if(map[uy - 1][ux] == 4){ //將箱子上面內容賦值為5★ map[uy - 1][ux] = 5; map[uy][ux] = 0; //箱子的數目減1 boxs--; }else{ //移動箱子 map[uy - 1][ux] = 3; } } //當上面幾種return的情況都沒遇到,人肯定會移動,移動操作如下 map[y][x] = 0; map[uy][ux] = 2; //更新人的坐標 y = uy; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      這是一個方向的,其它方向要考慮的問題也和前面一樣,我也就不贅述了。

      moveLeft()

      這里大致都和上面一樣,就是在記錄左邊坐標時,應該應該是lx = x - 1。

      void moveLeft(){ //定義變量存放人物左邊的坐標 int lx, ly; //當左邊沒有元素時,直接return if(x == 0){ return; } //記錄左邊坐標 lx = x - 1; ly = y; //左邊為已完成方塊 if(map[ly][lx] == 5){ return; } //假設左邊為墻,直接return if(map[ly][lx] == 1){ return; } //假設左邊為箱子 if(map[ly][lx] == 3){ //判斷箱子左邊是否為墻 if(map[ly][lx - 1] == 1){ return; } //判斷箱子左邊是否為球 if(map[ly][lx - 1] == 4){ //將箱子左邊內容賦值為5★ map[ly][lx - 1] = 5; map[ly][lx] = 0; //箱子的數目減1 boxs--; }else{ //移動箱子 map[ly][lx - 1] = 3; } } map[y][x] = 0; map[ly][lx] = 2; x = lx; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      moveDown()

      這里在判斷邊界時,判斷的是 y == HEIGHT - 1。

      void moveDown(){ //定義變量存放人物下方的坐標 int dx, dy; //當下方沒有元素時,直接return if(y == HEIGHT - 1){ return; } //記錄下方坐標 dx = x; dy = y + 1; //下方為已完成方塊 if(map[dy][dx] == 5){ return; } //假設下方為墻,直接return if(map[dy][dx] == 1){ return; } //假設下方為箱子 if(map[dy][dx] == 3){ //判斷箱子下方是否為墻 if(map[dy + 1][dx] == 1){ return; } //判斷箱子下方是否為球 if(map[dy + 1][dx] == 4){ //將箱子下面內容賦值為5★ map[dy + 1][dx] = 5; map[dy][dx] = 0; //箱子的數目減1 boxs--; }else{ //移動箱子 map[dy + 1][dx] = 3; } } map[y][x] = 0; map[dy][dx] = 2; y = dy; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      moveRight()

      這里也沒什么特別說的:

      void moveRight(){ //定義變量存放人物右邊的坐標 int rx, ry; //當右邊沒有元素時,直接return if(x == WIDTH - 1){ return; } //記錄右邊坐標 rx = x + 1; ry = y; //右邊為已完成方塊 if(map[ry][rx] == 5){ return; } //假設右邊為墻,直接return if(map[ry][rx] == 1){ return; } //假設右邊為箱子 if(map[ry][rx] == 3){ //判斷箱子右邊是否為墻 if(map[ry][rx + 1] == 1){ return; } //判斷箱子左邊是否為球 if(map[ry][rx + 1] == 4){ //將箱子右邊內容賦值為5★ map[ry][rx + 1] = 5; map[ry][rx] = 0; //箱子的數目減1 boxs--; }else{ //移動箱子 map[ry][rx + 1] = 3; } } map[y][x] = 0; map[ry][rx] = 2; x = rx; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      現在再回顧開始的運行步驟

      清除屏幕

      繪制地圖

      判斷游戲是否結束

      對用戶按下的按鈕進行反饋

      這里把判斷游戲是否結束放到了重繪圖像后面,因為在對用戶進行反饋的時候只是改變了map中的數據,實際上最后一個箱子推到終點的圖像還沒有顯示出來,所以要在重繪之后再判斷是否結束游戲。

      代碼有很多冗余的地方,一方面是想大家更好的理解,還有一方面出于懶。哈哈,代碼運行起來沒有問題,源碼和源程序我會上傳,有興趣的可以下下來,或者直接復制代碼運行也是沒問題的。

      本文轉載自https://blog.csdn.net/zacksock/article/details/101645494

      5G游戲

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:12月新書《Go Web編程》領航
      下一篇:JAVA內存問題及定位方法總結
      相關文章
      亚洲免费在线视频观看| 亚洲最大av无码网址| 亚洲国产小视频精品久久久三级 | 亚洲国产婷婷综合在线精品| 亚洲AV香蕉一区区二区三区| 亚洲成熟丰满熟妇高潮XXXXX| 亚洲国产精品无码第一区二区三区| 亚洲熟妇无码一区二区三区 | 亚洲欧洲另类春色校园网站| 亚洲中文无码av永久| 亚洲欧洲精品在线| 亚洲国产午夜精品理论片| 亚洲毛片在线免费观看| 亚洲91精品麻豆国产系列在线| 亚洲伊人久久大香线蕉| 亚洲一级高清在线中文字幕| 亚洲国产成人99精品激情在线| 精品亚洲成在人线AV无码| 亚洲国产av美女网站| 亚洲日本国产精华液| 亚洲伊人久久大香线蕉在观| 亚洲国产美女在线观看 | 亚洲综合精品成人| 亚洲人成电影网站| 亚洲成人网在线观看| 亚洲国产亚洲综合在线尤物| 亚洲中文字幕无码一去台湾 | 亚洲av日韩综合一区二区三区| 国产亚洲中文日本不卡二区| 亚洲综合激情五月色一区| 亚洲免费网站观看视频| 老司机亚洲精品影院在线观看| 亚洲精品第一国产综合亚AV| 国产成人va亚洲电影| 亚洲五月午夜免费在线视频| 亚洲国产a∨无码中文777| 亚洲黄色在线电影| 2020天堂在线亚洲精品专区| 亚洲精品无码永久在线观看男男| 亚洲精品无码久久久久APP | 亚洲欧洲日产专区|