3

リンク済み: MouseListener を使用してグリッド内のセル範囲を選択する

2 つのグリッドを持つ戦艦ゲームを作成しています。ユーザーは自分の船を 1 つのグリッドに配置してから、もう 1 つのグリッドを爆撃します。

10x10 のセルのグリッドを作成する Grid という抽象クラスがあります (これは JPanel クラスを拡張します)。次のように、各セルにリスナーを与えます。

public Grid() {
    setPreferredSize(new Dimension(300, 300));
    setLayout(new GridLayout(GRID_SIZE,GRID_SIZE));

    for (int x = 0; x < GRID_SIZE; x++)
        for (int y = 0; y < GRID_SIZE; y++) {
            final Cell cell = new Cell(x, y);
            cellArray[x][y] = cell;
            add(cell);
            cell.addMouseListener(new MouseListener() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    mouseClick(e, cellArray);
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    mouseEnter(e, cellArray);
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    mouseExit(e, cellArray);
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    mousePress(e, cellArray);
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    mouseRelease(e, cellArray);
                }
            });
        }
}

したがって、これらのリスナーは 2 つのサブクラスからアクセスできます。リスナーは、上記のコードに見られるように別のメソッドを呼び出します。これらのメソッドはコンストラクタの下に含まれており、すべて抽象的です。

public abstract void mouseClick(MouseEvent e, Cell[][] cellArray);
public abstract void mouseEnter(MouseEvent e, Cell[][] cellArray);
public abstract void mouseExit(MouseEvent e, Cell[][] cellArray);
public abstract void mousePress(MouseEvent e, Cell[][] cellArray);
public abstract void mouseRelease(MouseEvent e, Cell[][] cellArray);

次に、2 つの具体的なサブクラスを作成します。1 つは「プレイヤー グリッド」用で、もう 1 つは「コンピューター グリッド」用です。主な違いは、プレーヤー グリッドでは、リスナーを使用してすぐに船を配置することです。コンピューター グリッドでは、船は自動的に配置されます (クラスのオブジェクトが構築されるときに行われます)。

つまり、Computer グリッド クラスのリスナーは、ユーザーが正方形を爆撃しようとする試みに応答するためだけに存在するということです。プレイヤー グリッドは、船が配置されると、コンピューターによって自動的に爆撃されるはずです。

これは私が困難に遭遇したところです。PlayerGrid クラスに computerAttack() というメソッドを作成しましたが、クラスの外部からメソッドにアクセスする方法がわかりません。2 つのサブクラスを通信させるにはどうすればよいですか? さらに、これはそれを行う適切な方法ですか、それともこれら 2 つのクラスでやりすぎているのでしょうか? ここでは必要なだけ多くの情報を提供しようとしましたが、2 つのサブクラスの実際の内容が必要な場合は、それらを提供できます。

4

2 に答える 2

5

これは、 MVCのようなパターンが適用される典型的なアプリケーションです。のようなメソッドを含む、ゲーム ロジックを個別に、一般的な使用のために実装しますcomputerAttack()。したがって、ゲーム ロジックにはグリッド/プレーヤーの両方への参照が含まれ、グリッド/プレーヤーの両方のイベント インターフェイスも実装されます。このように、グリッドはお互いを知る必要はありません。

M - グリッド状態の内部表現 (船/水、爆撃済み/未爆撃など)

V - GUI コンポーネント (グリッド、ボタン、UI イベント リスナー インターフェイスなど)

C - ゲーム ロジック (別のクラスまたはパッケージで実装)

于 2013-04-27T16:39:40.117 に答える
1

PlayerGridおそらく、と をComputerGrid別々に考えないでください。どちらも単にGrids として扱います。はのゲーム状態Gridを維持します。プレーヤー用に 1 つ、コンピュータ用に 1 つ用意しますGridGrid

GridListener次に、 上の重要なイベントのコールバックを持つインターフェイスを作成できますGrid。と のようattackSuccess(int x, int y)attackFailed(int x, int y)

したがって、のようなメソッドがある場合Grid.attack(int x, int y)、おおよそ次のようになります。

boolean shipRemoved = removeShipAt(x, y);
if (shipRemoved) {
    // return true means that a ship was present and was removed.
    for (GridListener l: gridListeners) {
        l.attackSuccess(x, y);
    }
} else {
    // return false means that a ship was not present.
    for (GridListener l: gridListeners) {
        l.attackFailed(x, y);
    }
}

このように、 はGrid互いに直接通信しませんが、相手のイベントをリッスンできます。または、より高いレベルのゲーム コントローラーが両方のイベントをリッスンし、他の(複数可) に適切Gridに通知することができます。Grid

于 2013-04-27T16:42:13.807 に答える