规则/验证设计模式

时间:2013-01-16 11:02:37

标签: c# design-patterns

可以使用哪些设计模式为象棋这样的游戏创建规则/验证系统(这只是一个简单的例子,实际游戏需要更多的规则)

我在本网站上已经阅读了几个问题,但没有找到确凿的答案,也没有找到答案,指出我正确的方向。

此系统需要以下内容:

  • 每个应用了规则的对象都应该实现特定的 接口与作为验证起点的方法
  • 该规则应分两步实施:首先,它必须是 验证(可以pawn A移动到方格D4),如果为true则执行方法 如果为假,则执行方法B
  • 每个对象都可以有多个需要在a中应用的规则 具体顺序。当规则1完成时,规则2应该开始 验证等
  • 每个单独的规则(例如:只能移动1个方格,只能 对角移动等)必须在自己的类中,并且必须是可重用的 适用于需要规则的对象。
  • 请注意,这将用于后端的多人游戏
  • 请注意,每个规则都需要多个对象来测试其有效性 例如,通常一个棋子可以移动1平方,现在是下一个平方 游戏板由你的对手的棋子填充。结果:你的棋子 不能动。典当应包括其他典当位置,或 验证游戏板。

这些规则的另一个词是行为限制。

我也在gamedev.stackexchange上发布了这个问题,但由于这不是一个与游戏相关的问题而且没有人似乎有答案我也在这里发布。

4 个答案:

答案 0 :(得分:8)

我越是看问题,我就越想起状态/流程图。

enter image description here

  
      
  • 应用了规则的每个对象都应该使用作为验证起点的方法实现特定的接口

  •   
  • 该规则应分两步应用:首先,需要验证(可以典当A移动到方格D4),如果是,则执行方法A如果为false则执行方法B

  •   

状态对象可以包含多个转换。

过渡包括:

  1. 条件(S)
  2. 动作(S)
  3.   
        
    • 每个对象都可以包含需要以特定序列应用的多个规则。当规则1完成后,规则2应该开始验证等
    •   

    通过使用状态图,您可以通过状态和状态转换获得多个规则和特定的动作序列

      
        
    • 每个单独的规则(例如:只能移动1个方格,只能对角移动等)必须在自己的类中,并且必须可重用并适用于需要规则的对象。
    •   

    这可以通过将条件检查行为封装为类

    来实现
    public class Condition 
    {
        public string Name {get; set;}
        public Func<Move,bool> IsMet {get;set;} 
    }
    
    // Captures the behaviour of moving diagonally by 1-step
    // This can now be referenced/composed by other classes to build
    // a more complex condition
    var moveDiagonalCondition = new Condition 
    { 
        Name="Move diagonal", 
        IsMet = move => 
                        {
                            var delta = (move.ToPosition - move.FromPosition);
                            // 1 step to the left or right
                            return Math.Abs(delta.X) == 1 
                            // 1 step upwards (if player),
                            // or 1 step downwards (if opponent)
                            && delta.Y == move.IsPlayer1Move ? -1 : 1
                        }
    }
    
      
        
    • 请注意,这将在后端的多人游戏中使用

    •   
    • 请注意,每个规则需要多个对象来测试其有效性,例如,通常一个pawn可以移动1个方块,现在游戏板上的下一个sqaure由你的棋子填充对手。结果:你的棋子无法移动。典当应包括其他典当位置,或其验证中的游戏板。

    •   

    在国际象棋场景中,我建议传递move参数:

    public class Move
    {
        public Point FromPosition {get;set;}
        public Point ToPosition {get;set;}
        public Piece Piece {get;set;}
    }
    

    与此同时,各州应该可以访问整个GameBoard。  这允许州执行诸如

    之类的事情
    // Check for empty cell
    GameBoard.GetPieceAt(move.ToPosition) == null;
    
    // Check for opponent's piece
    GameBoard.GetPieceAt(move.ToPosition).IsPlayer2;
    

    为了进一步扩展到您的MMORPG场景,我会通过参数传递任何“来源”和/或“目标”

    • 即。碰撞源/目标或任何直接受影响的对象

    结论

    与国家问题如此相似,我认为看一下基于状态的解决方案是个好主意。

    ,例如State Pattern,有限状态机,状态转换表,自动机等

    或者您可以尝试查找决策表和决策树(我自己并没有真正使用过这些,所以我无法对它们说太多)

    不幸的是,我认为我不能推荐一个确切的解决方案。

    但希望上面的几个示例/关键字可以帮助您入门。

答案 1 :(得分:2)

我认为Strategy Pattern可能是您正在寻找的东西,它比HuorSwords建议的规格模式更轻,如果您正在寻找更容易上手的东西。

您希望使用的规则可以抽象为策略,然后根据需要插入每个部分。

每条规则都可以保存在自己的班级中。

每个策略都可以按照您要求的顺序构建一系列规则。

答案 2 :(得分:1)

我在想Specification Pattern解决问题的方法。

答案 3 :(得分:1)

这就是我设计它的方式。 (可能或可能不对应于某些设计模式)。

abstract class Rule<T>
{
    protected abstract bool implementRule(T on, GameWorld gw);

    protected abstract void doIfTrue();

    protected abstract void doIfFalse();

    public void runRule(T on, GameWorld gw)
    {
        if (implementRule(on, gw))
        {
            doIfTrue();
        }
        else
        {
            doIfFalse();
        }
    }

}

然后,假设你有一个名为pawn的类/接口,它有一个getX()方法,你可以做类似的事情

class RuleImpl : Rule<Pawn> // note T is now Pawn
{

    protected override bool implementRule(Pawn on, GameWorld gw) {
        if(on.getX()<gw.getX()){
            return true;
        }

        return false;
    }


    protected override void doIfTrue()
    {
        Console.WriteLine("true");

    }


    protected override void doIfFalse() {
        Console.WriteLine("false");

    }
}

编辑:自然Pawn可以而且应该更改为ThingsThatHaveAnXValue这样的界面。但为了代码清晰,我把它保留原样