
很多學 Python 的人都卡在同一個地方語法看懂了練習題也做了但合上教程自己寫不出任何有完整邏輯的程序。這通常不是笨而是反饋太長。等你學會列表、字典、函數、文件操作再動手可能已經過去兩周熱情早被耗光了。但如果第一周就做出一個“能玩”的東西情況會完全不同。今天要拆解的這個項目名字叫「人狗大作戰」。它是一個純文字、單文件、不依賴第三方庫的回合制小游戲。運行之后你能在終端里扮演一個遇到惡犬的人選擇“攻擊、投喂、躲避”等策略來影響劇情走向最后觸發不同結局。我的判斷是它特別適合作為 Python 入門后的第一個實戰項目因為它把input、if/elif/else、while、random、函數拆分這些基礎知識的練習全部裝進了一個 200 行左右的程序里。你不需要先學完“所有語法”才能做項目游戲本身就是驅動你把語法用起來的最好方式。這篇文章會從游戲設計思路講起然后逐步搭建骨架最后給出完整可運行源碼。讀完你可以直接復制、運行、改造也可以把它當作教學案例講給別人聽。1. 為什么一個文字游戲能點燃 Python 興趣很多初學者對 Python 的印象停留在“數據分析”“人工智能”這些宏大標簽上。結果一打開教程先背變量、再學列表練了半天九九乘法表內心真實想法是這東西到底能干什么問題不在于 Python 不夠有趣而在于學習路線缺少“正反饋閉環”。什么叫正反饋閉環就是你在電腦前敲下代碼運行之后立刻看到一個真實結果。這個結果越接近“你在做的事”你的學習動力就越強。文字游戲恰好站在了這個閉環的最前端。文字游戲有四個天然優勢第一它只需要終端不需要圖形界面。任何裝了 Python 的電腦都能運行跨平臺問題幾乎不存在。第二它天然是交互式的。程序會反復向你提問你輸入不同內容程序給出不同反應。這種“即時反饋”是刷題和背語法給不了的。第三它自帶劇情和懸念。玩家關心的是下一步會發生什么而不是“這個循環我到底學沒學會”。等你通關之后回頭一看才發現循環、判斷、隨機早就用熟了。第四它容易擴展。文字游戲做出來后你想加道具、加角色、加地圖都只是在原有邏輯上做增量。一個項目可以陪你從入門走到進階。「人狗大作戰」這個項目名2023 年前后經常出現在 Python 小游戲練習的相關內容里網上也有各種玩法版本。但我們不糾結某個固定玩法而是自己從零設計一版。因為寫游戲最大的樂趣不是照抄別人的代碼而是自己定義規則然后看著規則在代碼里活過來。2. 游戲設計沒有需求分析的開發都是寫著玩很多人一上來就寫代碼寫到一半發現邏輯混亂最后只能推倒重來。這其實是開發習慣的問題。寫任何程序哪怕是 200 行的小游戲也應該先想清楚三件事玩家能做什么對手能做什么游戲什么時候結束。2.1 核心玩法設計我給「人狗大作戰」定的核心規則是玩家遇到一只兇巴巴的小狗每回合雙方各選一個行動行動碰撞后產生不同結果。玩家每回合可以從四個行動里選一個攻擊強行制服狗狗但自己也可能受傷。投喂用食物試探增加狗狗好感度。躲避穩住局面觀察狗狗接下來的反應。查看狀態查看當前血量、狗狗血量和好感度。狗狗每回合會隨機做出三種反應之一咬主動攻擊玩家。吼虛張聲勢威懾玩家。跑試圖拉開距離。不同的行動組合會產生不同結果。例如玩家“攻擊”而狗狗“咬”雙方都會掉血玩家“投喂”而狗狗“吼”好感度會明顯增加玩家“躲避”而狗狗“跑”狗狗則會恢復一點精力。2.2 游戲怎么結束我設計了三個結局這讓玩家有重復挑戰的欲望第一個結局是“人狗同盟”。當好感度達到 100狗狗信任玩家游戲進入和平結局。第二個結局是“武力壓制”。狗狗血量降到 0玩家贏了但代價是內心的失落。第三個結局是“任務失敗”。玩家血量先歸零游戲結束提示玩家也許狗狗只是想要食物和耐心。三個結局對應三種玩法思路硬剛、懷柔、拖延。玩家如果想看懂全部劇情就必須把三套策略都試一遍。這種“可重玩性”恰恰是文字游戲最迷人的地方。2.3 用到的 Python 知識點知識點在游戲中的位置作用input()玩家行動選擇獲取用戶輸入if/elif/else行動結果結算根據組合觸發不同分支while True主循環讓游戲持續到勝負判定break結局觸發結束循環退出游戲random.choice()狗狗行動生成隨機行為函數定義行動選擇、結果結算拆分功能讓主邏輯清晰這個表格可以當作復習清單。寫完游戲之后你再用它對照一遍會發現自己已經不知不覺掌握了 Python 核心入門語法。3. 環境準備裝好 Python 就能開始在做游戲之前需要確認電腦上已經安裝了 Python。3.1 Python 安裝與驗證無論你用的是 Windows、macOS 還是 Linux都可以去 Python 官網下載對應系統的穩定版安裝包。版本號以官網最新穩定版為準本文重點演示的是通用思路不針對特定小版本。Windows 用戶安裝時有一個關鍵勾選項很多新手容易忽略在安裝向導第一頁勾選最下方的Add Python to PATH。這一步的作用是讓系統能在命令行直接識別python命令。如果漏掉后續運行會提示找不到命令。裝完之后打開終端或命令行工具輸入python --version如果輸出類似Python 3.x.x說明環境正常。有些系統上 Python 命令可能是python3 --version這是因為某些 Linux 發行版會同時存在 Python 2 和 Python 3用python3可以明確調用 Python 3。你自己機器上哪條能用就用哪條。3.2 創建項目文件建議新建一個專門的文件夾比如dog_battle然后在里面新建一個 Python 文件文件名可以是human_dog_battle.py。mkdir dog_battle cd dog_battle在文件夾里新建文件后用任意文本編輯器打開比如 VS Code、PyCharm、Notepad或者系統自帶的記事本。注意Windows 自帶的記事本也可以但保存時文件編碼要選擇 UTF-8否則中文輸出可能出現亂碼。Python 3 默認使用 UTF-8 編碼所以只要你保存時選對編碼終端里的中文一般不會出問題。如果運行后中文亂碼優先檢查終端編碼設置和文件保存編碼。4. 從零搭建游戲骨架直接給完整代碼看起來確實很爽但如果只是想“跑通”你其實錯失了最重要的學習過程。我建議按下面三步先把骨架搭出來再逐步填充細節。4.1 先寫主循環所有回合制游戲的核心都是同一個結構循環 結束條件。while True: print(新回合開始) # 玩家行動、狗狗行動、結果結算 break這里的while True表示無限循環游戲會一直運行下去。什么時候結束由勝負判定條件決定判定實現后把break放到對應分支里。很多新手不理解為什么要用while True總覺得它很危險。實際上它就是讓程序“邊運行邊等待輸入”的經典寫法配合break就能精確退出。4.2 玩家輸入與校驗玩家輸入是整個游戲交互的入口。為了讓程序更健壯我們一定要對輸入做校驗。while True: choice input(請輸入數字 1-4).strip() if choice in [1, 2, 3, 4]: print(f你選擇了 {choice}) break else: print(輸入無效請重新輸入。)這里有兩個細節值得注意strip()方法會去掉用戶輸入首尾的多余空格避免用戶在輸入數字時誤敲一個空格導致判斷失敗。這是實際開發中非常常見的坑。校驗邏輯使用if choice in [...]而不是寫一長串or條件代碼更簡潔也更容易擴展。如果以后要加第 5 個選項只需要在列表里加一個字符串。4.3 隨機行為狗狗的行為需要隨機產生。Python 的標準庫random提供了choice方法可以直接從一個序列中隨機挑一個元素。import random actions [咬, 吼, 跑] dog_move random.choice(actions)random是 Python 標準庫的一部分不需要額外安裝。這也是本項目能“零第三方依賴”運行的重要原因。5. 完整代碼人狗大作戰下面是完整源碼。建議不要直接復制粘貼先嘗試自己根據前面的骨架思路補全遇到困難再看答案。如果只是想體驗效果直接復制也能運行。# 文件名human_dog_battle.py import random import time def show_status(player_hp, dog_hp, affection): print(\n 當前狀態 ) print(f你的血量{player_hp} | 狗狗血量{dog_hp} | 好感度{affection}) print() def get_player_action(): print(\n請選擇行動) print(1. 攻擊強行制服) print(2. 投喂增加好感) print(3. 躲避觀察局勢) print(4. 查看狀態) while True: choice input(請輸入數字 1-4).strip() if choice 1: return 攻擊 elif choice 2: return 投喂 elif choice 3: return 躲避 elif choice 4: return 查看狀態 else: print(輸入無效請重新輸入。) def get_dog_action(): return random.choice([咬, 吼, 跑]) def resolve_round(player_move, dog_move, player_hp, dog_hp, affection): print(f\n你選擇了【{player_move}】狗狗選擇了【{dog_move}】) if player_move 攻擊: if dog_move 咬: player_hp - 15 dog_hp - 20 print(你沖上前去狗狗也毫不示弱。你被咬了一口但也打中了它。) elif dog_move 吼: player_hp - 5 dog_hp - 25 print(狗狗虛張聲勢地吼叫你抓住破綻給了它一下。) else: dog_hp - 20 print(狗狗想轉身逃跑被你的攻擊命中。) elif player_move 投喂: if dog_move 咬: player_hp - 10 affection 10 print(它警惕地咬了你一口但開始留意你手里的食物。) elif dog_move 吼: affection 15 print(它吼了兩聲卻沒有真的下口。你慢慢蹲下把食物放在面前。) else: affection 5 dog_hp 5 print(它跑開幾步遠遠看著你。你把食物放在地上等它慢慢靠近。) elif player_move 躲避: if dog_move 咬: print(你及時后退躲開了它的撲咬。) elif dog_move 吼: affection 5 print(它吼叫著試探你你保持冷靜沒有后退一步。) else: dog_hp 10 print(它跑遠了。你趁機喘了口氣狗狗也恢復了一點精力。) elif player_move 查看狀態: show_status(player_hp, dog_hp, affection) return player_hp, dog_hp, affection def main(): print(歡迎來到「人狗大作戰」) print(你遇到了一只兇巴巴的小狗。) print(可以攻擊它也可以嘗試用食物安撫它。) time.sleep(1) player_hp 100 dog_hp 80 affection 0 round_count 0 while True: round_count 1 print(f\n-------- 第 {round_count} 回合 --------) show_status(player_hp, dog_hp, affection) player_move get_player_action() if player_move 查看狀態: continue dog_move get_dog_action() player_hp, dog_hp, affection resolve_round( player_move, dog_move, player_hp, dog_hp, affection ) if affection 100: print(\n狗狗終于放下戒備搖著尾巴走到你身邊。) print(你成功馴服了它從此它成為你的伙伴。) print(【結局人狗同盟】) break if dog_hp 0: print(\n狗狗倒了下去。你贏了但心里似乎有些空落落的。) print(【結局武力壓制】) break if player_hp 0: print(\n你被狗狗打敗了……它可能只是想要一點食物和耐心。) print(【結局任務失敗】) break time.sleep(1) if __name__ __main__: main()代碼寫完后幾個核心邏輯值得再解釋一次。resolve_round函數接收玩家行動、狗狗行動以及三個狀態變量計算后返回更新后的狀態。它本身不修改外部變量而是把結果傳遞回來。這種“輸入參數、返回結果”的函數設計比直接在函數里修改全局變量更清晰也更不容易出 bug。get_player_action里的while True是輸入校驗的經典模式。只要用戶輸入不合法就繼續循環直到拿到合法輸入才return。這樣可以保證resolve_round永遠收到的都是合法行動值。main函數里的while True是游戲主循環。每次循環是一回合先展示狀態再獲取玩家操作再讓狗狗隨機行動最后結算勝負。好感度優先級最高先判斷它是否達到 100再判斷雙方血量。這樣設計的原因是想傳遞一個價值觀感化比武力更重要所以和平結局優先觸發。if __name__ __main__:這個寫法保證了當文件被直接運行時才執行main()。以后如果別人寫代碼import你的文件不會莫名其妙啟動游戲。6. 運行結果與效果驗證在終端進入項目文件夾運行python human_dog_battle.py如果你的系統需要用python3就把命令替換成python3 human_dog_battle.py運行后你會看到類似下面的界面。歡迎來到「人狗大作戰」 你遇到了一只兇巴巴的小狗。 可以攻擊它也可以嘗試用食物安撫它。 -------- 第 1 回合 -------- 當前狀態 你的血量100 | 狗狗血量80 | 好感度0 請選擇行動 1. 攻擊強行制服 2. 投喂增加好感 3. 躲避觀察局勢 4. 查看狀態 請輸入數字 1-4輸入1狗狗隨機行動輸出類似你選擇了【攻擊】狗狗選擇了【吼】 狗狗虛張聲勢地吼叫你抓住破綻給了它一下。之后再回到下一回合狀態顯示說明主循環正常。驗證游戲是否成功可以按三條路線各玩一次第一次全程選攻擊觀察“武力壓制”結局能否觸發。第二次全程選投喂觀察“人狗同盟”結局能否觸發。第三次故意連續選攻擊并期待玩家血量下降觀察“任務失敗”結局能否觸發。如果三種結局都能正常出現程序邏輯基本沒有問題。如果某一結局一直觸發不了優先檢查對應條件的比較符號以及行動結果結算里血量或好感度的增減值。運行失敗時第一步要看終端里的報錯信息。Python 的報錯會明確告訴你是哪一行出了問題是語法錯誤還是變量名拼寫錯誤。絕大多數小問題都能通過“看最后一行報錯”解決。7. 常見問題與排查思路問題現象可能原因排查方式解決方案提示python不是內部或外部命令Python 未加入 PATH運行python --version確認重新安裝并勾選Add Python to PATH中文輸出亂碼文件編碼不是 UTF-8查看編輯器右下角編碼把文件另存為 UTF-8 編碼輸入數字后沒有反應輸入了全角數字或空格檢查輸入內容用strip()去掉空格只輸入半角數字無限循環停不下來缺少break或條件永遠為真檢查所有結局分支確認每個結局都有break狗狗行為永遠一樣random未生效或種子固定檢查是否調用random.choice確認代碼import random且每次調用choice血量變成負數后仍未結束結算順序錯誤查看resolve_round后的判斷順序在結算后緊接著判斷血量而不是在其他邏輯之后這些問題是初學者最常遇到的。其中輸入問題最隱蔽因為控制臺里的空格和全角字符肉眼看不太出來。如果代碼怎么改都不對建議先把用戶輸入原樣打印出來確認它到底是什么內容。8. 工程化建議從能玩到好用完成了基礎版之后你已經有了一個“能跑”的程序。但“能跑”和“寫得好”之間還有距離。下面這些建議能讓代碼質量明顯提升也能幫你建立更好的開發習慣。8.1 用常量代替魔法數字代碼里的100、80、15、20這些數字散落在多個函數中。如果將來想調整難度需要逐個修改還容易漏掉。更合理的做法是統一使用常量PLAYER_MAX_HP 100 DOG_MAX_HP 80 AFFECTION_MAX 100Python 社區習慣用全大寫變量名表示“這個值不該被修改”。雖然 Python 沒有真正意義的常量但這是一種代碼約定能顯著提高可讀性。8.2 把判斷邏輯繼續拆分現在的resolve_round雖然有 9 種交互結果但都堆在一個函數里代碼規模已經比較大了。進一步優化時可以把每一類行動提取成獨立函數比如handle_attack、handle_feed、handle_dodge。def handle_attack(dog_move, player_hp, dog_hp): ... return player_hp, dog_hp這樣resolve_round只負責根據玩家行動分發到對應函數每個函數的職責更單一測試起來也更方便。8.3 增加可配置的難度你可以給游戲增加一個簡易的難度選擇簡單模式狗狗初始血量低困難模式狗狗初始血量高而且傷害更大。把初始參數做成用戶輸入能讓游戲的可玩性立刻上一個臺階。難度參數設計好后連帶著需要在玩家選擇難度時做輸入校驗。這會讓你再把輸入校驗邏輯鞏固一遍一舉兩得。8.4 給程序加日志游戲本身不需要日志但你在學習和調試過程中可以考慮加一個debug開關用來輸出戰斗結算的詳細數值。DEBUG True if DEBUG: print(f[調試] 玩家血量變化后{player_hp}, 狗狗血量{dog_hp})這個習慣對以后開發更復雜的程序非常有價值。日志是程序員定位問題的第一工具早點養成習慣后面會少走很多彎路。8.5 打包成可執行文件如果想把游戲分享給沒有安裝 Python 的朋友可以用PyInstaller打包成可執行文件。pip install pyinstaller pyinstaller -F human_dog_battle.py打包完成后在dist目錄下會生成一個可執行文件。把這個文件發給別人對方雙擊即可運行不需要安裝 Python 環境。這是很多 Python 新手想要掌握的技能也是把作品分享出去的常用方式。9. 從這個小游戲到更遠的 Python 之路「人狗大作戰」看起來只是一個文字游戲但它背后的知識點其實覆蓋了 Python 入門階段最關鍵的內容。你現在可以動手做三件事。第一先把代碼完整敲一遍不要復制粘貼。哪怕最終和示例代碼幾乎一樣你也會因為修改過幾個小問題而收獲巨大。因為“敲代碼時手很快出問題時腦子才開始真正工作”。第二嘗試修改參數。把狗狗初始血量改成 50把攻擊傷害改成 30看看游戲難度如何變化。這種小改動能讓你直觀感受到數值設計對游戲體驗的影響。第三給它增加一個新功能。比如增加一個“逃跑”選項或者增加一個“道具”系統讓玩家可以撿到骨頭提高投喂效果。每加一個新功能你都會被迫復習一遍已有的代碼結構這正是項目驅動學習的精髓。文字游戲的下一步很自然地會朝著圖形界面方向走。你可以用 Tkinter 做窗口版也可以用 pygame 做動畫版。但要記住工具可以換核心邏輯不變。先學會用標準庫把規則表達清楚再談圖形渲染和界面美化會讓后續學習輕松很多。如果你順手把這個項目保存到自己的代碼倉庫里以后回頭再看會發現那些曾經“看不懂的語法”已經變成了“理所當然的工具”。這就是興趣帶來的正反饋你不是在堅持學習而是在好奇心的驅動下主動探索。希望這只兇巴巴的小狗能成為你 Python 學習路上一個值得記住的坐標。動手運行一下比收藏十篇教程都有用。