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

来源:https://www.cnblogs.com/yxy6/archive/2020/07/11/13285926.html
-Advertisement-
Play Games

C語言,作為大多數人的第一門編程語言,重要性不言而喻,很多編程習慣,邏輯方式在此時就已經形成了。這個是我在大一學習 C語言 後寫的推箱子小游戲,自己的邏輯能力得到了提升,在這裡同大家分享這個推箱子小游戲項目。 GitHub 倉庫地址:github.com/weizhiwen/C… 先來看看最後的運行 ...


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

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

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

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

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

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

1、游戲地圖怎麼保存?

2、游戲怎麼運行?

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

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

5、游戲怎麼結束?

1、游戲地圖怎麼保存?

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

2、游戲怎麼運行?

因為推箱子游戲在游戲結束之前要不斷接受用戶的輸入,所以我們可以設置一個標誌來判斷游戲是否結束,把這個標誌設置為一個 while 迴圈的條件。在每次迴圈中,都要接收用戶的輸入,根據用戶輸入的值,來進行下一步的操作,在游戲中就是小人的移動方向,上下左右,這裡我們可以用一個 switch 語句判斷。每一次迴圈,對應一次用戶輸入。

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

在每次迴圈中,首先要把當前的地圖顯示出來,便於用戶下一次的移動輸入。我們將游戲地圖設置為一個全局變數,這樣在小人移動後,地圖上的字元改變就是永久的,然後列印局部改變的新地圖。這樣程式不斷迴圈,一遍遍的列印地圖,游戲地圖上的字元是可以不斷改變了,但是地圖的位置並不能固定下來。如果我們能刷新界面上的值,不就可以在位置固定的情況下不斷變化了。刷新本質就是除舊迎新,即把原來的除去,迎來新的。在程式中,我們可以把原來的界面清除,再把新的界面顯示在原來的位置。C語言中可以用system("cls")函數來清除控制台的內容,然後我們再把新的地圖內容顯示出來。

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

4、游戲怎麼結束?

前面我們說設置一個標誌來判斷游戲是否結束,但是游戲什麼時候結束呢?推箱子的游戲目標是將每個箱子推到目標位置,這是一種游戲結束的情況,由於每次迴圈都要判斷,可以將其寫成一個函數。另外,如果用戶不想玩了想退出,這也是一種游戲結束的情況,這裡我只考慮了這兩種情況,至於其他情況,讀者可自行考慮。

到目前位置我們可以寫出程式大致的框架了,外部一個大迴圈,每次迴圈都是先刷新界面,接收用戶輸入,處理用戶的輸入,判斷游戲是否結束。

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

在上面的程式截圖中,可以看到我把小人的上下左右移動分別寫到了四個函數中,分別是 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語言編程學習基地

有一些源碼和資料分享,歡迎轉行也學習編程的伙伴,和大家一起交流成長會比自己琢磨更快哦!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • content方面 減少HTTP請求:合併文件、CSS精靈、inline Image 減少DNS查詢:DNS緩存、將資源分佈到恰當數量的主機名 減少DOM元素數量 Server方面 使用CDN 配置ETag 對組件使用Gzip壓縮 Cookie方面 減小cookie大小 css方面 將樣式表放到頁面 ...
  • sort()方法、 reverse()方法、數學對象MATH(常用)、計時器 ...
  • Web前端並不算新興行業,在國內也已經發展好些年了,隨著互聯網電商項目的不斷發展,讓企業越來越重視用戶體驗,而Web前端開發工程師正是實現這樣一切的關鍵。 Web前端工程師已成為目前行業內最緊俏的職位。Web前端開發依然是值得大家選擇的職業。各個企業對於人才稀缺量比較大,和其他的行業相比它還沒有達到 ...
  • 如果你是一位前端開發工程師,對“跨平臺”一詞應該不會感到陌生。像常見的前端框架:比如React、Vue、Angular,它們可以做網頁端,也可以做移動端,但很少能做到跨PC、Mac端,也就是我們熟知的Windows、Linux以及macOS上的應用程式。即使有,受限於JS的性能瓶頸,當有大量的科學計 ...
  • type 指示type要使用的驗證器。可識別的類型值為: string:類型必須為string。type 預設是 string // 校驗 string: [ {type: 'string', message: `請輸入字元串`, trigger: 'blur'} ] <el-form-item l ...
  • var arr = [4,0,7,9,0,0,2,6,0,3,1]; var x; function zy(arr,x) { for(var i=0; i<arr.length;i++) { if(arr[i] == x) { arr.splice(i,1); i--; } } } zy(arr,0 ...
  • 先看再點贊,給自己一點思考的時間,思考過後請毫不猶豫微信搜索【沉默王二】,關註這個長髮飄飄卻靠才華苟且的程式員。本文 GitHub github.com/itwanger 已收錄,裡面還有技術大佬整理的面試題,以及二哥的系列文章。 關於 Java 基礎、Java 面向對象編程、Java 字元串、Ja ...
  • 一、使用數據類型的雷區 不要賦值給不相關的變數 例如:int a = 2.36這條語句,會直接給a賦值2,而不會進行四捨五入,原理是直接截斷小數點後面的數字。 例如:float b = 3.1415926536,C中保證了float類型的前6位精度,會損失精度,應該使用double來進行賦值。 許多 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...