最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

C/C++編程筆記:C語言寫推箱子小游戲,大一學(xué)習(xí)C語言練手項目

2020-07-11 22:42 作者:C語言編程__Plus  | 我要投稿

C語言,作為大多數(shù)人的第一門編程語言,重要性不言而喻,很多編程習(xí)慣,邏輯方式在此時就已經(jīng)形成了。這個是我在大一學(xué)習(xí) C語言 后寫的推箱子小游戲,自己的邏輯能力得到了提升,在這里同大家分享這個推箱子小游戲項目。

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

先來看看最后的運(yùn)行的效果。


這是一個在 Windows Dos 界面的小游戲,界面上有推箱子的地圖,使用#來代表地圖的邊界,P來代表推箱子的小人,X來代表箱子,O來代表箱子要推到的目標(biāo)位置。

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

要寫這個小游戲,我們面臨的問題有以下幾個。

1、游戲地圖怎么保存?

2、游戲怎么運(yùn)行?

3、游戲地圖怎樣在位置固定的情況下不斷變化?

4、小人的移動邏輯怎么寫?

5、游戲怎么結(jié)束?

1、游戲地圖怎么保存?

C語言中只有基本的數(shù)據(jù)類型,游戲地圖是二維的平面結(jié)構(gòu),很容易想到使用二維數(shù)組來保存游戲地圖,代碼詳情見 GitHub 倉庫中的關(guān)卡.h文件。


2、游戲怎么運(yùn)行?

因為推箱子游戲在游戲結(jié)束之前要不斷接受用戶的輸入,所以我們可以設(shè)置一個標(biāo)志來判斷游戲是否結(jié)束,把這個標(biāo)志設(shè)置為一個 while 循環(huán)的條件。在每次循環(huán)中,都要接收用戶的輸入,根據(jù)用戶輸入的值,來進(jìn)行下一步的操作,在游戲中就是小人的移動方向,上下左右,這里我們可以用一個 switch 語句判斷。每一次循環(huán),對應(yīng)一次用戶輸入。

3、游戲地圖怎樣在位置固定的情況下不斷變化?

在每次循環(huán)中,首先要把當(dāng)前的地圖顯示出來,便于用戶下一次的移動輸入。我們將游戲地圖設(shè)置為一個全局變量,這樣在小人移動后,地圖上的字符改變就是永久的,然后打印局部改變的新地圖。這樣程序不斷循環(huán),一遍遍的打印地圖,游戲地圖上的字符是可以不斷改變了,但是地圖的位置并不能固定下來。如果我們能刷新界面上的值,不就可以在位置固定的情況下不斷變化了。刷新本質(zhì)就是除舊迎新,即把原來的除去,迎來新的。在程序中,我們可以把原來的界面清除,再把新的界面顯示在原來的位置。C語言中可以用system("cls")函數(shù)來清除控制臺的內(nèi)容,然后我們再把新的地圖內(nèi)容顯示出來。

小人的移動邏輯屬于具體的程序?qū)崿F(xiàn),我們放到下面再說,先來說說程序怎么結(jié)束。

4、游戲怎么結(jié)束?

前面我們說設(shè)置一個標(biāo)志來判斷游戲是否結(jié)束,但是游戲什么時候結(jié)束呢?推箱子的游戲目標(biāo)是將每個箱子推到目標(biāo)位置,這是一種游戲結(jié)束的情況,由于每次循環(huán)都要判斷,可以將其寫成一個函數(shù)。另外,如果用戶不想玩了想退出,這也是一種游戲結(jié)束的情況,這里我只考慮了這兩種情況,至于其他情況,讀者可自行考慮。

到目前位置我們可以寫出程序大致的框架了,外部一個大循環(huán),每次循環(huán)都是先刷新界面,接收用戶輸入,處理用戶的輸入,判斷游戲是否結(jié)束。


5、小人的移動邏輯怎么寫?

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

理論上,小人是可以上下左右的移動的,但是,由于有地圖的限制,小人不能穿墻的,只能在允許的道路上移動,比如下面這種情況,小人想向上移動,肯定是不允許的。


而下面這種的情況,小人是可以向上移動的,因為小人上面一格并沒有限制物。


所以我們要對小人理論上可以移動到的那格(下一位置)進(jìn)行判斷,如果不是限制物(箱子和箱子要移動到的位置下面在詳細(xì)說),小人就可以移動,如果有限制物就不能移動。所以我們需要記錄一個坐標(biāo)點(diǎn)的值,這里“下一位置”的參照物可以選取小人當(dāng)前的位置,游戲開始時,把小人的開始位置作為當(dāng)前位置。小人向上移動,“下一位置”的橫坐標(biāo)就是小人當(dāng)前位置的橫坐標(biāo)減一,縱坐標(biāo)就是小人當(dāng)前位置的縱坐標(biāo)。然后我們就可以根據(jù)“下一位置”的橫縱坐標(biāo)找到具體的字符值,如果是空的,就可以移動,如果是箱子要移動的目標(biāo)位置,小人也可以移動,還有一種情況是“下一位置”是箱子,我們還要考慮箱子的“下一位置”,箱子的下一位置也很好得到。因為小人和箱子是在一條線上移動的,所以在小人向上移動時,箱子的“下一位置”的橫坐標(biāo)就是小人“下一位置”的橫坐標(biāo)減一,兩者的縱坐標(biāo)相同。同樣我們也要對箱子“下一位置”的字符值進(jìn)行判斷,如果字符值是空格和箱子可以移動的位置,就是可以移動的。小人向上移動的代碼如下:


小人向下、向左、向右移動的代碼也是類似的,無非就是把小人移動的下一坐標(biāo)改一改,向下移動,“下一位置”的橫坐標(biāo)就是小人的橫坐標(biāo)位置加一,兩者縱坐標(biāo)相同,代碼詳情見 GitHub 倉庫中的控制.cpp文件。

到這里整個程序就算是完成了,可以運(yùn)行整個程序效果如下,能發(fā)現(xiàn)哪里有 Bug 嗎?


相信細(xì)心的你已經(jīng)發(fā)現(xiàn)了,當(dāng)小人移動到箱子要移動的目標(biāo)位置,再移出,這個位置就會“消失”,為什么出現(xiàn)這種情況呢?我們在前面總是關(guān)注小人要移動的”下一位置“和箱子要移動的“下一位置”,卻沒有關(guān)注在移動之前,這個位置(上一位置)原本的值,我們可以記錄這個“上一位置”的值,但是這樣考慮的問題就比較多了,尤其是箱子和小人都在箱子要移動的目標(biāo)位置時,情況很復(fù)雜,那么有木有簡單的方法呢?其實到現(xiàn)在為止,我們的程序大體上是沒什么問題的,只是箱子要移動的目標(biāo)位置會出現(xiàn)“字符消失”。這只是個小 Bug,把用戶當(dāng)測試的微軟是怎么做的呢?系統(tǒng)發(fā)行后不停的發(fā)布補(bǔ)丁,我們也可以像這樣給這個程序打個“補(bǔ)丁”。箱子要移動的位置是不變的,我們可以能不能用一個二維數(shù)組來存放這些特殊位置呢?這些特殊位置的值也是特殊的,要不就是目標(biāo)位置,要不就是箱子,要不就是小人,而不能是空白字符,所以我們可以寫一個“補(bǔ)丁”——修復(fù)這個 Bug 的函數(shù)。當(dāng)小人移動后,在每個方向的移動函數(shù)結(jié)尾加上下面這個修復(fù)函數(shù)。這里判斷特殊位置是不是空白字符,如果是空白字符,就將特殊位置的值改為目標(biāo)位置的字符值,這里是字符 “O”,這樣就“修復(fù)”了程序的 Bug,“字符消失”的問題也被解決了。


我將程序劃分成了不同的文件,GitHub倉庫也有程序目錄的說明文件,讀者在閱讀代碼時,會注意到extern關(guān)鍵字的使用,這個關(guān)鍵字是為了拆分的多個文件之間共用某個變量或者函數(shù)。將關(guān)卡中的游戲地圖更換,就可以實現(xiàn)推箱子的多個關(guān)卡,讀者有興趣可自己嘗試改進(jìn),本文也是起到一個拋磚引玉的作用。

最后想說的是,寫程序很注重邏輯,無論用什么語言,程序的邏輯都是一樣的,無非就是哪種語言更方便,更快捷。寫程序真正玩的是邏輯,只有邏輯清晰,代碼才能寫得好,否則頂多也是代碼的搬運(yùn)工。

作者:Wizey

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

學(xué)習(xí)C/C++編程知識,提升C/C++編程能力,歡迎關(guān)注UP一起來成長!
另外,UP在主頁上傳了一些學(xué)習(xí)C/C++編程的視頻教程,有興趣或者正在學(xué)習(xí)的小伙伴一定要去看一看哦!會對你有幫助的~

C/C++編程筆記:C語言寫推箱子小游戲,大一學(xué)習(xí)C語言練手項目的評論 (共 條)

分享到微博請遵守國家法律
聂荣县| 图木舒克市| 西藏| 韶山市| 霍林郭勒市| 赤峰市| 满洲里市| 盐山县| 乌拉特后旗| 吉首市| 陆丰市| 奉新县| 泰顺县| 图木舒克市| 沙雅县| 志丹县| 德化县| 商南县| 长宁区| 安平县| 垣曲县| 丰城市| 砀山县| 彰化市| 灵台县| 裕民县| 自治县| 廉江市| 新郑市| 虎林市| 定兴县| 呼和浩特市| 齐齐哈尔市| 垫江县| 大理市| 衢州市| 玉龙| 县级市| 永城市| 施秉县| 大余县|