1

Playerクラスがあるとしましょう。Move方向パラメータをChangePosition取り込むメソッド、2つのintを取り込むDisappearメソッド、voidメソッドなどがあります。

ユーザー(おそらくリストボックスを使用)がこれらのメソッドのいくつかをPlayerオブジェクトの動作に追加できるようにしたいと思います。たとえば、右に移動してから下に移動してから消えることを選択できます。次に、選択したメソッドがイベントに追加されるため、そのイベントが発生すると、選択したメソッドが実行されます。

誰かが以前にこのようなことをしたことがありますか?これを行うための最良の方法は何ですか?(私は13歳で、デザインパターンについてはあまり知りません)

4

3 に答える 3

2

もう1つのオプションは、Actionジェネリックを使用し、必要なメソッドを追加するだけで、特定のプレーヤーオブジェクトでそれらのアクションを呼び出すことができます。

これは、他の人が提案したインターフェースデザインのアイデアに代わるものですが、あなたのスタイルはこの方法を好むかもしれません。

Action<Player> playerActions = p => {}; //Do Nothing
playerActions += p => { p.Move(3); }; //Move
playerActions += p => { p.ChangePosition(1, 1); }; //Change position
playerActions += p => { p.Disappear(); }; //Disappear

//Invoke Actions
Player player = new Player();
playerActions(player);

//Invoke on another object as well
Player player2 = new Player();
playerActions(player2);
于 2012-10-07T15:41:43.177 に答える
2

まず、すべてのゲームロジックを、それだけを担当するEngineクラスを使用してEngineプロジェクトに配置する必要があります(すべてのゲームのロジックを処理し、UIとフレームワーク[および存在する場合は下位レイヤー]と通信します)。 )。

次に、列挙型EngineActionType(Move、ChangePos、Disappear、...)およびその他のプロパティを持つEngineActionクラスを作成できます。一般的な考え方は次のとおりです。

タイプを保持する列挙型があります:

public enum EngineActionType
{
    Move,
    ChangePos,
    Disappear,
    ...
}

すべてのエンジンアクションクラスを論理的にグループ化する抽象クラスを作成し、それらを共通のTypeプロパティで追加します。

public abstract class EngineAction
{
    public readonly EngineActionType Type;

    protected EngineAction(EngineActionType type)
    {
        this.Type = type;
    }
}

必要なすべてのパラメーターをプロパティとして保持する、エンジンアクションごとのクラスを作成します。EngineActionから派生し、適切なEngineActionTypeを基本コンストラクターに送信する必要があります。

public class EngineActionMove : EngineAction
{
    public int XDelta;
    public int YDelta;

    public EngineActionMove() : base(EngineActionType.Move)
    {
    }
}

public class EngineActionChangePos : EngineAction
{
    ...
}

...

その後、ユーザーが注文したときにこれらのオブジェクトをリストに入れ、そのオブジェクトを繰り返し処理して、タイプに応じて1つずつ実行します。

foreach (EngineAction action in actionsToDo)
{
    switch (action.Type)
    {
        case EngineActionType.Move:
            EngineActionMove mvAction = (EngineActionMove)action;

            // Example:
            player.Position = player.Position.Offset(mvAction.XDelta,
                                                     mvAction.YDelta);
            break;
        case EngineActionType.ChangePos:
            EngineActionChangePos cpAction = (EngineActionChangePos)action;

            // Example:
            player.Position = new Point(cpAction.X, cpAction.Y);
            break;
        case EngineActionType.Disappear:
            // Just make the player disappear,
            // because the operation needs no parameters
            player.Disappear();
            break;
        case ...:
        default:
            // maybe throw an error here, to find errors during development
            // it helps you find non-handled action types
    }
}

詳細なヒント:UIにあるロジックは少ないほど、優れています。いつも。

編集:Charlehによる素晴らしいアイデア:

public interface IEngineAction
{
    void Do(Player target);
}

public class EngineActionMove : IEngineAction
{
    public int XDelta;
    public int XDelta;

    public void Do(Player target)
    {
        // Example
        target.Position = ...
    }
}

public class EngineActionDisappear : IEngineAction
{
    public void Do(Player target)
    {
        // Example
        target.Visible = false;
    }
}

...

リストの例に追加:

var actionsToDo = new List<IEngineAction>();

actionsToDo.Add(new EngineActionDisappear());
actionsToDo.Add(new EngineActionMove { XDelta = 10, YDelta = 20 });

そして反復:

foreach (IEngineAction action in actionsToDo)
{
    action.Do(player);
}
于 2012-10-07T14:48:12.337 に答える
1

それを行うには多くの方法があります。1つの方法は、ファクトリパターンとストラテジーパターンを使用することです。

public static class PlayerBuilder
{
    public static Player BuildPlayer(BuildDefinition definition)
    {
        //logic in here to build a player -- pseudo-return value below as an example
        var strategy = new PlayerMovementStrategy();
        return new Player(strategy);
    }
}

クラスBuildDefinitionは、ユーザーの選択に基づいて構築できます。何かを追加するだけでなく、事前定義されたオプションのリストから選択できるようです。UIの選択に基づいて適切な戦略を作成します。

abstract class MovementStrategy
{
    public abstract void Move();
    public abstract void ChangePosition(Direction d);    
}
class PlayerMovementStrategy
{
    public override void Move()
    {
        //move
    }
    public override void ChangePosition(Direction d)
    {
        //change position
    }
}
abstract class VisibilityStrategy
{
    public abstract void Disappear();
}
class PlayerVisibilityStrategy
{
    public void Disappear()
    {
        //poof 
    }
}

class Player
{
     private readonly PlayerMovementStrategy movement;
     private readonly PlayerVisibilityStrategy visibility;

     public Player(PlayerMovementStrategy movement, PlayerVisibilityStrategy visibility)
     {
         this.movement = movement;
         this.visibility = visibility;
     }

     public void Disappear()
     {
         visibility.Disappear();
     }         
     public void Move(Direction d)
     {
         movement.Move(d);
     }
}
于 2012-10-07T14:55:56.500 に答える