C語言項目實戰:10分鐘帶你開發風靡全球的2048遊戲

2019-09-28     C語言編程開發

2048遊戲也算是風靡一時的益智遊戲。其背後實現的邏輯比較簡單,代碼量不算多,而且趣味性強,適合作為有語言基礎的童鞋來加強編程訓練。

我們提供給大家的 2048 小遊戲,不要求大家精通 C 語言,也不會涉及到指針的使用,

只需要學會以下幾個知識點即可:

會使用變量(int、char)和二維數組;

能夠懂得函數的聲明和使用;

掌握 C 語言的分支結構(if-else 和 switch 語句)和循環結構(while 和 fo() 循環);

設計 2048 小遊戲的主要目的是讓大家夯實 C 語言基礎,訓練編程思維,培養解決問題的思路,領略多姿多彩的 C 語言。

前 言

遊戲截圖:

C語言

遊戲實現原理:

1.使用終端圖形庫文件curses繪製終端里的圖形。

2.使用一個二維數組保存4 x 4 空格中的變量。

鍵盤輸入控制移動,經過邏輯判斷,二維數組數據變化。

3.二維數組數據變化後交給圖形函數顯示出來。

庫文件curses介紹:

curses是一種終端圖形繪製庫,利用curses可以在終端中繪製多種圖形。


簡單demo

#include

#include

int main(){

initscr();

border(0,0,0,0,0,0,0,0);

move(5,15);

printw("%s","hello world");

refresh();

char ch=getch();

endwin();

return 0;

}

深入學習請查詢相關資料。

C語言

2048實現代碼分析

根據2048實現原理,代碼要實現的主要有三件事:

圖形繪製遊戲邏輯操作圖形加載邏輯結果

主程序代碼如下:

2048 C語言版代碼分析

//-------------頭文件--------------------//

#include

#include

#include

#include

#include

#include

//--------------------------------------//

//------------------全局變量-------------------------------

// 遊戲主介面是一個 4*4 的 16 宮格,使用二維數組進行表示,用 0 表示空格

int a[4][4] = {0};// 16

宮格中空格的個數

int empty;

// 涉及到新產生的數字的位置的兩個變量

int old_y, old_x;

//所有的C語言代碼就是在這三個函數中

int main(){

//初始化函數

init();

//遊戲運行時函數

play();

//結束函數,清屏

//endwin()來關閉

curses 模式.

endwin();

return 0;

}

main()函數代碼分析

頭文件+全局變量

頭文件中包含的庫文件如下:

標準輸入輸出

設計到內存操作函數

繪製圖形庫文件

時間函數

睡眠函數庫文件

信號相關操作庫文件

C語言

主函數代碼

主函數中共有三個子函數,其中複雜的為前兩個,第三個為curses關閉的函數,沒有任何邏輯。init()函數的作用是遊戲準備,繪圖函數等。play()函數是遊戲運行的主要邏輯函數。

C語言

下面分別分析init()函數和play()函數的實現。

init()函數

必要的curses庫開啟函數

設置遊戲開始時空格數為15

產生兩個隨機數x、y作為第一個數字的位置下標

調用draw()函數來繪製圖形

C語言

所有的圖形繪製都是依靠draw()函數來完成的。下面來分析該函數。

draw()函數

使用兩個雙層循環繪製4*4窗格。

調用draw_one()函數將全局變量數組a[][]中的數據顯示在空格中。

C語言

draw()_one()函數

將a[][]中的數字轉換成c[]中的字符

循環c[]輸出字符,並顯示在圖形中

C語言

play()函數代碼

play函數是整個遊戲的主題函數,負責移動,判斷等邏輯。遊戲的邏輯主要分兩個步驟來完成,以向左移動為例來說明:

C語言

1、循環16個窗口,從(0,0)開始,如果(0,1)和(0,0)相同,則兩個相加,並將(0,1)置為0。然後繼續判斷(0,2)和現在的(0,0)是否相同,相同則相加到(0,0)中。直到(0,0)右邊都判斷完成結束。

2、以上步驟只是完成一個窗口(0,0)的判斷,使用循環將16個都完成相加。

3、所有的完成相加之後可能的情況是下面這樣的,還須將所有的數字都移到左邊。以圖中(1,1)為例,循環到(1,1)時,判斷左邊的窗口是否為0,如果為0,則向左移動一個,繼續判斷左邊是否為0,直到移動到最左邊。

C語言

具體的代碼分析:

使用一個死循環while(1)來循環接收輸入,判斷等。

ch=getch()接收輸入,switch case來判斷輸入的內容。

C語言

具體分析其中一個,以向左移動為例:

循環判斷每一個空格中的數字

如果為0,則繼續下一次循環;如果不為0,則判斷其右邊的格子中數字是否相同。

如果右邊格子中的數字和當前格子中相同,那麼相加,繼續判斷右邊的右邊直到數組到底。

所有相同的數字都相加結束之後,將所有的數字整體向左移動。

case 68: // 左移方向鍵

for(y = 0; y < 4; y++)

for(x = 0; x < 4; )

{ //如果a[y][x]中的值為0,則跳過該次循環

if(a[y][x] == 0)

{

x++; continue;

}

else //如果a[y][x]中的值不為0,則 { //循環的思想是,以傳入的坐標為基點,向右邊搜索,如果右邊的和基點相等,則將兩個點相加 //相加之後繼續向後搜索,還有相等的則繼續相加。直到超出範圍而退出。 //下一次循環繼續搜索。

for(i = x + 1; i < 4; i++)

{ //判斷a[y][x+1],即該空格的右邊的對應位置是否為0,如果為0則退出本次循環

if(a[y][i] == 0)

{ continue;

} else //如果不為0,則判斷是否相等,如果相等則相加,然後將後面一個置0,退出循環 { if(a[y][x] == a[y][i])

{

a[y][x] += a[y][i];

a[y][i] = 0; //當有相加產生之後,會多出一個空格。這裡體現空格的減少。

empty++; break;

} else

{ break;

}

}

} //當該次循環退出之前,只是完成了該基點的一次搜索,所以要向右邊移動一個,繼續下一次的業務。

x = i;

}

} //當所有的相加都完成之後,要將數據整體向左移動,體現在數據全都左移。

//將所有的數值向左移

for(y = 0; y < 4; y++) for(x = 0; x < 4; x++)

{ //如果該位為0,則不動,因為需要移動的是有數值的項

if(a[y][x] == 0)

{ continue;

}

else //如果該為不為0,則向左移動一位,前提是判斷該位的左邊是空位

{ //如果前面是左邊是空位,則移動到空位上,繼續判斷左邊的左邊是不是空位,如果是則繼續移動,直到所有的都移動完成。

for(i = x; (i > 0) && (a[y][i-1] == 0); i--)

{

a[y][i-1] = a[y][i];

a[y][i] = 0; //一旦移動過,就將move置1,方便後面空格中生成新的數據

move = 1;

}

}

} break;

C語言

當switch case結束之後,要完成當前狀態的檢驗:

判斷空格的剩餘數,如果剩餘小於等於0,則遊戲結束

如果不等於0,則判斷空格是否等於上次或者有移動,兩者有一個成立,就要生成新的數字

產生新數字的下標a[x][y]中的x、y,直到該x、y對應的數組a[][]上為空值時才成功

判斷該x、y是否為最佳出現地點

生成不等於0或者2的時候退出。(不明白的這裡的邏輯)

在第四步中使用了函數cnt_value()來判斷下一個數字出現的最佳地點,後面單獨分析。

C語言

cnt_value()

該函數主要選擇出下一個數字的最佳出現地點,原則就是周圍的空格數最多。

以上一步驟產生的x、y為起點,算出其左右的空格數。

循環所有的空格,統計其周圍8個空格的空格數。如果有空格數大於起點的,則生成新的數字。

cnt_one()為具體計算某一個空格周圍8個格子的空格數的函數。邏輯簡單,不做具體分析。

cnt_one()

C語言

整個邏輯都很正常,除了這最後的cnt_value()函數,這裡要找出四周空格最多的一個窗口,而直接將隨機產生的窗口作為周圍空格最多的就不合理了(max並非最多)。後面只要出現空格數大於該窗口的就選為下一個數字出現的窗格,實際獲取的並未最多空格的下標。應該是統計出4*4窗格中周圍空格數最多的,然後在最多的窗口處出現下一個數字。

C語言

加C/C++學習交.流群,免費獲取C語言、C++學習資料,學習路線指導和梳理,更有進階乾貨的直播免費學習權限 ,都是大牛帶飛 讓你少走很多的彎路的 群...號是 546912356

文章來源: https://twgreatdaily.com/zh-my/aBDRg20BMH2_cNUgzxhV.html