4

次の簡単なシナリオで、「教えて、聞かないで」の原則 (以下、「原則」) をどのように順守しますか? Tetris ゲームには、次の例に関連する Board、BlockGrid、および Piece クラスがあります。

public class Board
{
    private var fallingPiece:Piece;
    private var blockGrid:BlockGrid;
    ...
    public function moveFallingPiece(xDirection:int, yDirection:int):void
    {
        blockGrid.movePiece(fallingPiece, xDirection, yDirection);
    }
} 

FallingPiece が BlockGrid の一番下の行に配置されると、それは "fallingPiece" ではなくなります。私は次の原則に違反していないという点で正しいですか?

if(blockGrid.getPiecePosition(piece).y == 0)
{
    fallingPiece = null;
}

しかし、それは明らかに原則に違反していると私が考えるこれと本当に違うのでしょうか?

public function moveFallingPiece(xDirection:int, yDirection:int):void
{
    if(blockGrid.getPiecePosition(piece).y > 0)
    {
        blockGrid.movePiece(fallingPiece, xDirection, yDirection);
    }
    else
    {
        fallingPiece = null;
    }
}

私は、これらのクラスの関係を原則に沿った適切な方法で設計したとは考えていません。それが欠けている場合は、別のデザインについてアドバイスしてください。


編集、提案された解決策:

イベントを介して「コマンドフィードバック」を提案する回答を使用しました。Board は BlockGrid にピースを移動するように指示します。BlockGrid の movePiece メソッドは、結果に応じて MOVED_TO または MOVE_FAILED イベントを送出します。このイベントは、Board がリッスンしてピースの落下が停止したかどうかを判断するために使用できます。このソリューションに関するフィードバックをお寄せください。

public class Board
{
    ...
    public function Board()
    {
        ...
        blockGrid.addEventListener(PieceMoveEvent.MOVE_FAILED, onPieceMoveFailed);
        ...
    }

    public function moveFallingPiece(xDirection:int, yDirection:int):void
    {
            blockGrid.movePiece(fallingPiece, xDirection, yDirection);
    }

    public function onPieceMoveFailed(event:MovePieceEvent):void
    {
        if(event.instance == currentlyFallingPiece && event.fromPosition.y != event.toPosition.y)
        {
             currentlyFallingPiece = null;
        }
    }
4

4 に答える 4

1

あなたが探しているのは、イベント駆動型プログラミングです。.event() と呼ばれるメソッドを持つ Listener インターフェースと、イベントを表す Event インターフェースが必要です。オブジェクトは他のオブジェクト ( callbacks ) とともに Listener インターフェイスに登録されます。

Piece と Board を作成するときは、Listener インターフェイスを実装する必要があります。次に、registerListener(board); でボードを設定できます。次に、Piece 内で何かが起こると、登録されているすべてのリスナーをループし、それぞれで .event(event) を呼び出します。Board と同じように、新しいピースを作成するたびに board.registerListener(piece) を呼び出します。何かが起こっていると判断すると、すべての登録済みリスナーに何が起こったかを伝えることができます。次に、Board オブジェクトがこれを判断することで、ピースが落下していないことを伝えることができます。ウィキペディアの義務的なエントリは次のとおりです。

于 2010-02-07T02:17:08.887 に答える
1

Tell, Don't Askの原則によりよく従うには、fallingPieceが休憩点に達したときに、blockGridがBoardクラスに通知する必要があると思います。上記の両方のシナリオでは、fallingPiece を null にする必要があるかどうかを判断するために、ピースの position.y == 0 かどうかを blockGrid に問い合わせています。代わりに、blockGrid が Board クラスに、fallingPiece.y が 0 になったことを伝える必要があります。

于 2010-02-07T01:27:46.710 に答える
0

I would expect a class representing each shape (without position information), a controller containing a shape, position and orientation, and another class representing the current resulting grid of "landed" shapes. The landed-grid would have a

testLanded(shape, shapePosition, orientation)

method which would be called before/after each move operation to decide if the shape is to join the landed grid or should move and stay as the falling piece.

I'm going on the idea of not giving data to objects that shouldn't really own that data - but I've never implemented Tetris...

于 2010-02-07T01:59:25.840 に答える
0

設計を再考する必要があるかもしれません。Board は本当に落下するピースを追跡する必要がありますか、それとも BlockGrid に属するべきですか? 誰がどの行動を所有しているかを解決します。

Piece クラスの位置情報を保持し、場合によっては Piece クラスに BlockGrid のインスタンスを保持させます。

次に、 Board クラスでこのようなことを試すことができます...

public function moveFallingPiece(xDirection:int, yDirection:int):void
{
    blockGrid.moveFallingPiece(xDirection, yDirection);
}

次に、BlockGrid の moveFallingPiece メソッドで...

public function moveFallingPiece(xDirection:int, yDirection:int):void
{
    fallingPiece.move(xDirection, yDirection);
}

Piece の move メソッドで、ロジックを追加します...

public function move(xDirection:int, yDirection:int):void
{
    setPosition(xDirection, yDirection);

    if (getPosition().y <= 0)
    {
        blockGrid.setFallingPiece(null); 
        // this can bubble up to Board if need be
    }
}

AS3 のすべての能力は確かではありませんが、ここで抽象化を使用することは理にかなっています。(つまり、Piece クラスを BlockGrid ではなく ITrackFallingPieces に依存させ、BlockGrid に ITrackFallingPieces を実装させます)。

幸運を!

于 2010-02-07T04:13:14.230 に答える