C/C++編程筆記:C語言寫推箱子小遊戲,大一學習C語言練手項目

C語言,做爲大多數人的第一門編程語言,重要性不言而喻,不少編程習慣,邏輯方式在此時就已經造成了。這個是我在大一學習 C語言 後寫的推箱子小遊戲,本身的邏輯能力獲得了提高,在這裏同你們分享這個推箱子小遊戲項目。git

GitHub 倉庫地址:github.com/weizhiwen/C…github

先來看看最後的運行的效果。編程

這是一個在 Windows Dos 界面的小遊戲,界面上有推箱子的地圖,使用#來表明地圖的邊界,P來表明推箱子的小人,X來表明箱子,O來表明箱子要推到的目標位置。數組

W(w)、S(s)、A(a)、D(d)分別對應小人向上、下、左、右移動。微信

要寫這個小遊戲,咱們面臨的問題有如下幾個。框架

一、遊戲地圖怎麼保存?編程語言

二、遊戲怎麼運行?函數

三、遊戲地圖怎樣在位置固定的狀況下不斷變化?post

四、小人的移動邏輯怎麼寫?學習

五、遊戲怎麼結束?

一、遊戲地圖怎麼保存?

C語言中只有基本的數據類型,遊戲地圖是二維的平面結構,很容易想到使用二維數組來保存遊戲地圖,代碼詳情見 GitHub 倉庫中的關卡.h文件。

二、遊戲怎麼運行?

由於推箱子游戲在遊戲結束以前要不斷接受用戶的輸入,因此咱們能夠設置一個標誌來判斷遊戲是否結束,把這個標誌設置爲一個 while 循環的條件。在每次循環中,都要接收用戶的輸入,根據用戶輸入的值,來進行下一步的操做,在遊戲中就是小人的移動方向,上下左右,這裏咱們能夠用一個 switch 語句判斷。每一次循環,對應一次用戶輸入。

三、遊戲地圖怎樣在位置固定的狀況下不斷變化?

在每次循環中,首先要把當前的地圖顯示出來,便於用戶下一次的移動輸入。咱們將遊戲地圖設置爲一個全局變量,這樣在小人移動後,地圖上的字符改變就是永久的,而後打印局部改變的新地圖。這樣程序不斷循環,一遍遍的打印地圖,遊戲地圖上的字符是能夠不斷改變了,可是地圖的位置並不能固定下來。若是咱們能刷新界面上的值,不就能夠在位置固定的狀況下不斷變化了。刷新本質就是除舊迎新,即把原來的除去,迎來新的。在程序中,咱們能夠把原來的界面清除,再把新的界面顯示在原來的位置。C語言中能夠用system("cls")函數來清除控制檯的內容,而後咱們再把新的地圖內容顯示出來。

小人的移動邏輯屬於具體的程序實現,咱們放到下面再說,先來講說程序怎麼結束。

四、遊戲怎麼結束?

前面咱們說設置一個標誌來判斷遊戲是否結束,可是遊戲何時結束呢?推箱子的遊戲目標是將每一個箱子推到目標位置,這是一種遊戲結束的狀況,因爲每次循環都要判斷,能夠將其寫成一個函數。另外,若是用戶不想玩了想退出,這也是一種遊戲結束的狀況,這裏我只考慮了這兩種狀況,至於其餘狀況,讀者可自行考慮。

到目前位置咱們能夠寫出程序大體的框架了,外部一個大循環,每次循環都是先刷新界面,接收用戶輸入,處理用戶的輸入,判斷遊戲是否結束。

五、小人的移動邏輯怎麼寫?

在上面的程序截圖中,能夠看到我把小人的上下左右移動分別寫到了四個函數中,分別是 MoveToUp()、MoveToDown()、MoveToLeft()、MoveToRight()。以 MoveToUp() 函數爲例,咱們來分析小人移動的邏輯。

理論上,小人是能夠上下左右的移動的,可是,因爲有地圖的限制,小人不能穿牆的,只能在容許的道路上移動,好比下面這種狀況,小人想向上移動,確定是不容許的。

而下面這種的狀況,小人是能夠向上移動的,由於小人上面一格並無限制物。

因此咱們要對小人理論上能夠移動到的那格(下一位置)進行判斷,若是不是限制物(箱子和箱子要移動到的位置下面在詳細說),小人就能夠移動,若是有限制物就不能移動。因此咱們須要記錄一個座標點的值,這裏「下一位置」的參照物能夠選取小人當前的位置,遊戲開始時,把小人的開始位置做爲當前位置。小人向上移動,「下一位置」的橫座標就是小人當前位置的橫座標減一,縱座標就是小人當前位置的縱座標。而後咱們就能夠根據「下一位置」的橫縱座標找到具體的字符值,若是是空的,就能夠移動,若是是箱子要移動的目標位置,小人也能夠移動,還有一種狀況是「下一位置」是箱子,咱們還要考慮箱子的「下一位置」,箱子的下一位置也很好獲得。由於小人和箱子是在一條線上移動的,因此在小人向上移動時,箱子的「下一位置」的橫座標就是小人「下一位置」的橫座標減一,二者的縱座標相同。一樣咱們也要對箱子「下一位置」的字符值進行判斷,若是字符值是空格和箱子能夠移動的位置,就是能夠移動的。小人向上移動的代碼以下:

小人向下、向左、向右移動的代碼也是相似的,無非就是把小人移動的下一座標改一改,向下移動,「下一位置」的橫座標就是小人的橫座標位置加一,二者縱座標相同,代碼詳情見 GitHub 倉庫中的控制.cpp文件。

到這裏整個程序就算是完成了,能夠運行整個程序效果以下,能發現哪裏有 Bug 嗎?

相信細心的你已經發現了,當小人移動到箱子要移動的目標位置,再移出,這個位置就會「消失」,爲何出現這種狀況呢?咱們在前面老是關注小人要移動的」下一位置「和箱子要移動的「下一位置」,卻沒有關注在移動以前,這個位置(上一位置)本來的值,咱們能夠記錄這個「上一位置」的值,可是這樣考慮的問題就比較多了,尤爲是箱子和小人都在箱子要移動的目標位置時,狀況很複雜,那麼有木有簡單的方法呢?其實到如今爲止,咱們的程序大致上是沒什麼問題的,只是箱子要移動的目標位置會出現「字符消失」。這只是個小 Bug,把用戶當測試的微軟是怎麼作的呢?系統發行後不停的發佈補丁,咱們也能夠像這樣給這個程序打個「補丁」。箱子要移動的位置是不變的,咱們能夠能不能用一個二維數組來存放這些特殊位置呢?這些特殊位置的值也是特殊的,要不就是目標位置,要不就是箱子,要不就是小人,而不能是空白字符,因此咱們能夠寫一個「補丁」——修復這個 Bug 的函數。當小人移動後,在每一個方向的移動函數結尾加上下面這個修復函數。這裏判斷特殊位置是否是空白字符,若是是空白字符,就將特殊位置的值改成目標位置的字符值,這裏是字符 「O」,這樣就「修復」了程序的 Bug,「字符消失」的問題也被解決了。

我將程序劃分紅了不一樣的文件,GitHub倉庫也有程序目錄的說明文件,讀者在閱讀代碼時,會注意到extern關鍵字的使用,這個關鍵字是爲了拆分的多個文件之間共用某個變量或者函數。將關卡中的遊戲地圖更換,就能夠實現推箱子的多個關卡,讀者有興趣可本身嘗試改進,本文也是起到一個拋磚引玉的做用。

最後想說的是,寫程序很注重邏輯,不管用什麼語言,程序的邏輯都是同樣的,無非就是哪一種語言更方便,更快捷。寫程序真正玩的是邏輯,只有邏輯清晰,代碼才能寫得好,不然頂多也是代碼的搬運工。

做者:Wizey

原文連接:https://juejin.im/post/5b874d4551882542ee71761b


自學C/C++編程難度很大,不妨和一些志同道合的小夥伴一塊兒學習成長!

C語言C++編程學習交流圈子,【點擊進入微信公衆號:C語言編程學習基地

有一些源碼和資料分享,歡迎轉行也學習編程的夥伴,和你們一塊兒交流成長會比本身琢磨更快哦!

相關文章
相關標籤/搜索