UI要素を持つOOPの概念を使用してチェスゲームを設計しようとしています。私のアイデアは、選択されたときにピースが移動できる正方形/セルの数を示すことです。基本的に私はそれが移動/攻撃できるパス/方向を別の色で表示したいと思います。
次のようなもの
したがって、私は抽象Piece
クラスを設計しました。このクラスには、特に、方向に移動できるすべてのセルを追跡するMap
オブジェクトがあり、次のようになっていますMap<Direction, LinkedList<Cell>>
さて、クイーンオブクイーン自身のチームがFORWARD
方向に攻撃し、chessBoard[6][4]
にあるセルに自分自身を置くとします。
イベントのその特定のセルを監視しているQueen
または他のピースに通知して、各ピースが独自の更新メソッドを呼び出して攻撃の経路を再描画できるようにするための最良の方法は何ですか?
私はすべてのセルがサブジェクトになり、それらを観察している部分だけがオブザーバーになるというオブザーバーパターンで行くことを考えていました。したがって、いずれの場合でも、特定のピースのセットによって監視されているセルのいずれかで何かが発生すると、それらのピースのみが通知されます。
しかし、すべてのセルに最大32のリスナーが必要なため、これが良いアプローチかどうかはわかりません。それがまったくスケーラブルになるかどうかはわかりません。
それを行うためのより良い方法はありますか?
読んでいただきありがとうございます。
「移動可能なすべてのセルを追跡するMapオブジェクト」があると、時期尚早な最適化の例のように見えます。
「ピースが遅くなる可能性がある場合に備えて」、ピースごとにこれらのセルをすべて覚える代わりに、関連するList<Cell>
(またはMap<Direction, LinkedList<Cell>>
)メソッドが呼び出されたときに計算によって?この方法では、通知やオブザーバーパターン、または「32リスナー」は必要ありません。それが本当に駒の方法なのか、盤の方法なのかは議論の余地があるかもしれません。ただし、このメソッドをピースの代わりにボードに入れると、ピースはボードについて何も知る必要がないため、ボードとピースの間の循環依存を回避できます。
このメソッドが変更されていない同じボードで頻繁に呼び出されてパフォーマンスのボトルネックになると後でわかった場合(これは疑問です)、 memoization を使用して結果をキャッシュできます。これは、Map<Direction, LinkedList<Cell>>
1個あたりが必要ですが、他のボードの変更を積極的に監視する必要はありません。
私の提案は、物事をできるだけ簡単にすることです。オブジェクトに与える情報が多いほど、オブジェクトは複雑になり、追跡が難しくなります。
プログラムをレイヤーに分解してみましょう。そこにあるもの?
The Pieces。ピースは...単なるピースです。色とタイプ(ルーク、キング、クイーンなど)がありますが、それだけです。それは答えることができます:
The Board。ボードは、セルが断片を持つか持たないかの2D配列です。それは答えることができます:
さらに、ボードの現在の状態に基づいて、次の計算を依頼できます。
例:移動
B3 to A4
。
- B3に駒がない場合、それは違法です。
- ピースが斜めに移動できない場合、それは違法です。
- A4が同じ色の部分で占められている場合、それは違法です。
- キングがチェック状態にあり、その動きがキングを保護しない場合、それは違法です。等々。
ゲームの状態。ゲームの状態は、ボードの現在の状態とともに、ゲームでこれまでに起こったことを追跡します。これも:
I。 Tbe UIは、ゲームの状態とボードの描画を担当します。私たちはそれを尋ねることができます:
UIは、イベントを処理する唯一のものでなければなりません。ピースはイベントを処理しません。ゲームの状態はイベントを処理しません。また、理事会はイベントを処理しません。イベントが発生すると、UIは次のことを行います。
可能な移動を強調表示するなど、どうすればよいですか?ユーザーがボード上にマウスを置くと、UI
この最後の質問は、入力として位置を取り、合法的に攻撃される可能性のある位置のリスト(または配列)を返すボードのメンバー関数の形で実装できます。
このアプローチを使用する理由すべてのフィールド、すべてのプロパティ、クラスに追加するすべてのメンバーは、stateを追加します。すべての状態は、管理し、追跡し、必要に応じて更新する必要があります。コードはめちゃくちゃになり、1つの小さな変更で突然12の異なるクラスを変更する必要があるため、変更は困難です。
ピースの2D配列に基づいて合法的な動きのリストを計算することは、ピースごとにMap<Direction, LinkedList<Cell>>
を継続的に更新するよりもはるかに安価です。コードも少なくなります。
プログラムをレイヤーに分割し、各レイヤーに単一の責任(その下のレイヤーを制御する)を与えることにより、クリーンで効率的でモジュール式のプログラムを作成できます。
他の回答はすでに、あなたが求めていることをどのように行うことができるかを答えました。ここで指摘したいのは、OOPもデザインパターンも(そうではありませんが、まったく異なるものです)は、それらを使用するためだけに使用するべきではないことです。
これらはツールであるため、到達したい目的に応じて選択する必要があり、その逆ではありません。
チェスプログラムを作成する必要があり、OOPを使用することを選択した場合、またはOOPを学習してから、学習用の導管としてチェスを選択する場合それ。
それが後者である場合、私が疑っているように、私の提案は低いバーから始めることですが。
OOP他の多くと同じようにボードゲームを学ぶのは素晴らしい方法であり、私がこれまで使用してきたほとんどのプログラムよりも優れています。しかし、よりシンプルなゲームでスターを付けることをお勧めします。tic- tac-toe、そしてチェスやさらに複雑なゲームに到達するまで、複雑さのはしご(チェッカー、マインスイーパ、バックギャモンなど)を上に移動します。
あなたの目標がOOPを学ぶことである場合、私が提案しているアプローチは、OOPを介してチェスを行う方法よりも多くの概念と実践を学ぶように導くでしょう。