著者: ミハウ・ポワワ
ソースリポジトリ: two-heroes-fight-simulation
二人の英雄の戦いシミュレーション
このリポジトリには、さまざまな方法でアプローチされた特定のタスク (このファイルの下にある) に対するソリューションが含まれています。各アプローチ (完了したもの) には、独自のブランチと独自のタグがあります。アプリケーションは cli から実行可能です。
このリポジトリの目的は、(私にとって) クリーンなコードと、次のような優れたコード設計を練習することです。
- OOP の 4 つの柱 (私にとって、SOLID に焦点を当てれば、それらは自ら思いついたものです)
- 堅実な原則
- 単一の責任 (私のクラスにはそれぞれ独自のタスクがあります)
- オープン/クローズド (さまざまなアプローチを試し始めたとき、内部のほとんどは手つかずで、新しい機能を追加する必要があるだけでした)
- Liskov 置換原則 (私のコードは必要に応じて抽象化を使用し、基礎となる実装を認識していません。たとえば、Unit クラスと Colleague クラスを見てください)
- インターフェース分離の原則 (1 つの大きなインターフェースではなく、多数の小さなインターフェース)
- 依存関係逆転の原則 (クラスがインスタンス化される唯一の場所は run.php スクリプトとファクトリーです。ランダマイザーを見てください - モックすることができます! どのクラスでも rand() を直接使用しません)
- デザインパターン
- デコレータ (ソース/モディファイア)
- ファクトリーメソッド
- オブザーバーパターン (適切な分岐)
- メディエーター パターン (適切なブランチ)
- DDDの戦術パターン
- 値オブジェクト (ソース/プロパティ)
- 集約 (src/Unit - ここにカプセル化できるロジックのすべての部分がここにあります)
- ドメインサービス (TurnService)
- アプリケーションサービス (GamePlayService)
- 工場(工場)
- イベント (src/Event) (はい、代わりにイベント バスを使用できます)
- 疎結合(SOLIDから生じる)
アクション/イベント ロガー、エラー ロガー、プリンター (リーダー)、およびコア ロジックはすべて相互に疎結合されています。 - TDD
正直に言うと、最初に失敗するテストを実装し、次にテストが成功した後にソースコードを実装するという純粋な TDD ではありません (実際的ではないと思います)。ただし、抽象化レベルまたはクラスを作成した後、すぐにテストして、問題があればすべての小さなバグを修正しました。必要なエラーや、考えていなかった論理的なエラー。そのため、run.php スクリプト (アプリケーションへのエントリ ポイント) を実装し、最後のステップとして実行したところ、コードは機能しました。これで十分であり、純粋な TDD は必要ないと思います。
走り方
- docer を実行します:
docker-compose up -d
- アプリケーションの実行:
docker-compose exec cli php run.php
- 単体テストを実行する
docker-compose exec cli vendor/bin/phpunit tests/
タスク
オーダースとビーストの間の戦闘シミュレーションを作成します。戦闘が開始されるたびに、ビーストとオーダースは次のルールに従って異なる統計情報で生成されます。
- 注文:
- 健康状態: 70 - 100
- 強さ: 70 - 80
- 守備: 45 – 55
- スピード: 40 – 50
- 幸運: 10% - 30% (0% は幸運がないことを意味し、常に 100% 幸運であることを意味します)
- 追加のスキル:
- ラピッドストライク: 自分が攻撃する番の間に2回攻撃します。彼が攻撃するたびにこのスキルを使用する確率は 10% です
- マジックシールド:敵の攻撃時に通常の半分のダメージしか受けません。防御するたびにこのスキルを使用する割合が 20% 変化します
- 獣:
- 健康状態: 60 - 90
- 強さ: 60 - 90
- 守備: 40 – 60
- スピード: 40 – 60
- 運: 25% - 40%
ゲームプレイのルール:
- 最初の攻撃はスピードの速いプレイヤーが行います。両方のプレイヤーのスピードが同じ場合、攻撃は最も幸運なプレイヤーによって実行されます。
- 攻撃の後、プレーヤーは役割を切り替えます。攻撃者は防御し、防御者は攻撃します。
- 攻撃者が与えるダメージは次の式で計算されます:
Damage = Attacker strength – Defender defence
- ダメージは防御者の体力から差し引かれます。そのターンに防御側が幸運に恵まれた場合、攻撃側は攻撃を外してダメージを与えられない可能性があります。
- オーダースのスキルはチャンスに基づいてランダムに発生するため、各ターンで考慮してください。
- プレイヤーの 1 人が体力を失うか、ターン数が 20 に達するとゲームは終了します。
- アプリケーションは毎ターン、何が起こったのか、どのスキルが使用されたか (使用されている場合)、与えられたダメージ、防御者の残りの体力などの結果を出力する必要があります。
- 最大ラウンド数に達する前に勝者がいる場合は、その勝者を宣言する必要があります。
ブランチとタグ
- ブランチ: ベース;タグ: ベース実行アプリ:
printig をまだサポートしていない基本ソリューション (コア機能、単体テスト済み) が含まれています - ブランチ: オブザーバー パターン;タグ: 実行中のアプリのオブザーバーのパターン:
base
ブランチのすべてのコードが含まれており、オブザーバー パターンを使用して印刷とロギングを行うことでコードを拡張します。 - ブランチ: メディエーター パターン;タグ: 実行中のアプリ-メディエーター-パターン:
base
ブランチのすべてのコードが含まれており、Mediator パターンを使用して印刷とロギングを行うことでコードを拡張します。
さらにブランチとアプローチが追加される予定です...
現在のブランチ:ベース
説明の言葉
最も簡単で最も「Web アプリ」的な解決策は、外部または自作のイベント バスを使用することですが、私はデザイン パターンを試したいだけです (その解決策はいつか追加するかもしれません)。
TODO
- ミスアビリティ実装忘れてた…
- MagicShield デコレータの存在しない委任を修正