推箱子游戲攻略圖文解析還有推箱子游戲攻略104

hello,各位小伙伴們大家好!

許久沒寫C語言的小游戲了,今天閑來無事,動起手來。過程還是蠻順利的,代碼也比較簡單。今天給大家分享一下~

一、介紹

開發語言:C語言

開發工具:VS2022/2019,VScode,Dev-C++都可以(沒有VS的話也可以來文末領取哦)

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

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

二、代碼實現

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

有比較不想動的好兄弟也可以直接來拿源碼(但不建議),領取源碼可以到文末領取!

(1)方法列表

//主函數

void main();

//初始化一些數據

initData();

//在控制臺上打印地圖

drawMap();

//向上移動

moveUp();

//向左移動

moveLeft()

//向下移動

moveDown()

//向右移動

moveRight();

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

(2)參數列表

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

//導入函數庫

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

//宏定義

#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;

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

/**

* 0 表示空

* 1 表示墻

* 2 表示人

* 3 表示箱子

* 4 表示目的地(球)

* 5 表示已完成的箱子

*/

(3)函數具體分析

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

1、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;

}

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

清除屏幕

繪制地圖

判斷游戲是否結束

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

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

2、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++;

}

}

}

}

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

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

3、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");

}

}

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

4、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、前面為終點

我這里沒有考慮太多,這種情況不做操作。(如果更換地圖的話可能需要修改代碼)

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

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;

}

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

6、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;

}

7、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;

}

8、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;

}

三、總結

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

清除屏幕

繪制地圖

判斷游戲是否結束

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

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

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

需要完整源碼對照的同學可以在文章末領取!

推箱子游戲教程就到此結束啦,大家趕緊試試吧!

源碼素材獲取通道:

可以關注小編在后臺私信我:【編程交流】哦!

在十幾年前,智能手機還未興起時,我相信大多數人手機中只有一兩個游戲,《推箱子》便是其中之一,可謂風靡一時,接下來我簡單介紹下這款即將被遺忘的游戲。

游戲并沒有精彩的畫面,如俄羅斯方塊般簡單卻又耐人尋味,很考驗測略,讓人愛不釋手。游戲的規則很簡單,在游戲中你將扮演一個推箱子的人物,你需要運用測略把各種箱子推到指定位置,通往羅馬的路不止一條,游戲的通關方式也有很多種,需要大家用智慧探索,游戲通關后一關比一關難,看看你能通道第幾關吧!