作者:米哈烏·波瓦瓦
來源儲存庫:二人英雄戰鬥模擬
二人英雄戰鬥模擬
此儲存庫包含以不同方式處理的給定任務(本文件下方)的解決方案。每種方法(已完成)都有自己的分支和標籤。應用程式可以透過 cli 運行。
這個儲存庫的目的(對我來說)是練習乾淨的程式碼和一些良好的程式碼設計,如下所示:
- OOP 的四大支柱(對我來說,如果你專注於 SOLID,它們就會自行出現)
- 堅實的原則
- 單一職責(我的每個班級都有自己獨特的任務)
- 開放/封閉(當我開始嘗試不同的方法時,我的大部分內部結構都沒有受到影響,只需要添加新功能)
- 里氏替換原則(我的程式碼在需要時使用抽象,並且不知道底層實作;例如查看 Unit 和 Colleague 類別)
- 介面隔離原則(多個小介面而不是一個大介面)
- 依賴倒置原則(實例化類別的唯一地方是 run.php 腳本和工廠,看看 Randomizer - 它可以被嘲笑!我不在任何類別中直接使用 rand() )
- 設計模式
- 裝飾器(src/修飾符)
- 工廠方法
- 觀察者模式(真分支)
- 中介者模式(適當的分支)
- DDD 戰術模式
- 值物件(src/屬性)
- 聚合(src/Unit - 這裡可以封裝的所有邏輯都在這裡)
- 網域服務(TurnService)
- 應用程式服務(GamePlayService)
- 工廠(工廠)
- 事件(src/Event)(是的,我可以使用活動總線代替)
- 鬆散耦合(源自 SOLID)
操作/事件記錄器、錯誤記錄器、印表機(讀取器)和核心邏輯彼此鬆散耦合 - 時分雙工
老實說,這不是純粹的TDD,首先實現失敗的測試,然後在測試通過後源代碼(我認為這不切實際),但是在我創建了一些抽象級別或類之後,我立即對其進行了測試並修復了所有小錯誤,如果我沒有考慮到的必要錯誤或邏輯錯誤。這就是為什麼當我實作 run.php 腳本(這是應用程式的入口點)並且我將其作為最後一步時,程式碼起作用了!我認為這已經足夠好了,不需要純粹的 TDD。
如何跑
- 運行 docer:
docker-compose up -d
- 運行應用程式:
docker-compose exec cli php run.php
- 運行單元測試
docker-compose exec cli vendor/bin/phpunit tests/
任務
創建Orderus和野獸之間的戰鬥模擬。每次戰鬥開始時,野獸和秩序都會產生不同的統計數據,遵循以下規則:
- 訂單:
- 生命值:70 - 100
- 強度:70 - 80
- 防禦:45 – 55
- 速度:40 – 50
- 運氣:10% - 30%(0%表示沒有運氣,100%一直是幸運)
- 額外技能:
- 快速出擊:輪到自己攻擊時連擊兩次;每次攻擊時有10%的幾率使用該技能
- 魔法護盾:敵人攻擊時僅承受普通傷害的一半;每次防守時他都會使用這個技能,有 20% 的變化
- 獸:
- 健康:60 - 90
- 強度:60 - 90
- 防禦:40 – 60
- 速度:40 – 60
- 運氣:25% - 40%
遊戲規則:
- 第一次攻擊由速度較高的玩家完成。如果兩個玩家的速度相同,則由運氣最高的玩家進行攻擊。
- 攻擊後,玩家交換角色:攻擊者現在防守,防禦者現在攻擊。
- 攻擊者造成的傷害計算公式如下:
Damage = Attacker strength – Defender defence
- 傷害將從防禦者的生命值中扣除。如果防禦者在該回合運氣好的話,攻擊者可能會錯過攻擊並且不會造成任何傷害。
- 奧德魯斯的技能是根據機會隨機出現的,因此每回合都要考慮到它們。
- 當其中一名玩家沒有生命值或回合數達到 20 時,遊戲結束。
- 應用程式必須每回合輸出結果:發生了什麼、使用了哪些技能(如果有)、造成的傷害、防禦者剩餘的生命值。
- 如果在達到最大輪數之前我們有獲勝者,則必須宣布獲勝者。
分支和標籤
- 分支:基地;標籤: 基礎運行應用程式:
包含尚未支援 printig 的基本解決方案(核心功能、單元測試) - 分支:觀察者模式;標籤:運行應用程式觀察者模式:
包含來自base
分支的所有程式碼,並使用觀察者模式透過列印和日誌記錄來擴展它 - 分支:中介模式;標籤:運行應用程式中介模式:
包含來自base
分支的所有程式碼,並使用調解器模式透過列印和日誌記錄來擴展它
待增加更多分支和方法...
目前分支:基地
解釋的話
最簡單和最“網頁應用程式”的解決方案是使用一些外部或自製的事件總線,但我只想使用設計模式(有一天我可能會添加該解決方案)。
待辦事項
- 忘記實施未命中能力...
- 修復 MagicShield 裝飾器中不存在的委託