简体   繁体   English

规则/验证设计模式

[英]Rule / validation design pattern

What design patterns can be used to create a rule / validation system for a game like chess (this is just a simple example, the actual game needs more difficult sets of rules) 可以使用哪些设计模式为象棋这样的游戏创建规则/验证系统(这只是一个简单的例子,实际游戏需要更复杂的规则集)

I've read several questions on this site and haven't found a conclusive answer nor an answer pointing me in the right direction. 我在这个网站上已经阅读了几个问题,但没有找到一个确凿的答案,也没有一个答案指出我正确的方向。

This system would require the following: 该系统需要以下内容:

  • Every object that has rules applied to it should implement a specific interface with a method that is the starting point for the validation 应用了规则的每个对象都应该使用一个方法来实现一个特定的接口,该方法是验证的起点
  • The rule should be applied in 2 steps: first, it needs to be validated (can pawn A move to square D4), if true then execute method A if false then execute method B 该规则应该分两步应用:首先,它需要被验证(可以pawn A移动到方格D4),如果为true则执行方法A如果为false则执行方法B
  • Every object can have multiple rules that need to be applied in a specific sequence. 每个对象都可以有多个需要按特定顺序应用的规则。 When rule 1 is finished, rule 2 should then start to validate etc 当规则1完成后,规则2应该开始验证等
  • Every separate rule (for example: can only move 1 square, can only move diagonally etc) must be in its own class and must be reusable and applicable on the objects that need rules. 每个单独的规则(例如:只能移动1个方格,只能对角移动等)必须在其自己的类中,并且必须可重用并适用于需要规则的对象。
  • Note this is going to be used in a multiplayer game on the backend 请注意,这将在后端的多人游戏中使用
  • Note that every rule need multiple objects to test its validity, for example, normally a pawn can move 1 square, now the next sqaure on the gameboard is filled by a pawn of your opponent. 请注意,每个规则都需要多个对象来测试其有效性,例如,通常一个pawn可以移动1个方块,现在游戏板上的下一个sqaure由对手的棋子填充。 Result: your pawn cannot move. 结果:你的棋子无法移动。 The pawn should include the other pawns positions, or the gameboard in its validation. 典当应包括其他典当位置,或其验证中的游戏板。

Another word for these rules would be behavioral limits. 这些规则的另一个词是行为限制。

I've also posted the question on gamedev.stackexchange but since this is not nescesarily a game related question and no-one seems to have an answer I'm posting it here too. 我也在gamedev.stackexchange上发布了这个问题,但由于这不是一个与游戏相关的问题而且没有人似乎有一个答案我也在这里发布。

The more I look at the problem, the more I'm reminded of a state/flow chart. 我越是看问题,我就越想起状态/流程图。

在此输入图像描述

  • Every object that has rules applied to it should implement a specific interface with a method that is the starting point for the validation 应用了规则的每个对象都应该使用一个方法来实现一个特定的接口,该方法是验证的起点

  • The rule should be applied in 2 steps: first, it needs to be validated (can pawn A move to square D4), if true then execute method A if false then execute method B 该规则应该分两步应用:首先,它需要被验证 (可以pawn A移动到方格D4),如果为true则执行方法A如果为false则执行方法B

The state object can contain multiple transitions. 状态对象可以包含多个转换。

A Transition consists of: 过渡包括:

  1. Condition(s) 条件)
  2. Action(s) 行动(S)
  • Every object can have multiple rules that need to be applied in a specific sequence . 每个对象都可以有多个需要按特定顺序应用的规则 When rule 1 is finished, rule 2 should then start to validate etc 当规则1完成后,规则2应该开始验证等

By using a state diagram, you get multiple rules and specific action sequences via states and state transitions 通过使用状态图,您可以通过状态和状态转换获得多个规则和特定的动作序列

  • Every separate rule (for example: can only move 1 square, can only move diagonally etc) must be in its own class and must be reusable and applicable on the objects that need rules. 每个单独的规则(例如:只能移动1个方格,只能对角移动等)必须在其自己的类中,并且必须可重用并适用于需要规则的对象。

This can be achieved by encapsulating the condition-checking behaviour as a class 这可以通过将条件检查行为封装为类来实现

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
                    }
}
  • Note this is going to be used in a multiplayer game on the backend 请注意,这将在后端的多人游戏中使用

  • Note that every rule need multiple objects to test its validity, for example, normally a pawn can move 1 square, now the next sqaure on the gameboard is filled by a pawn of your opponent. 请注意,每个规则都需要多个对象来测试其有效性,例如,通常一个pawn可以移动1个方块,现在游戏板上的下一个sqaure由对手的棋子填充。 Result: your pawn cannot move. 结果:你的棋子无法移动。 The pawn should include the other pawns positions, or the gameboard in its validation. 典当应包括其他典当位置,或其验证中的游戏板。

In the chess scenario, I propose passing around the move parameter: 在国际象棋场景中,我建议传递move参数:

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

At the same time, the states should have access to the entire GameBoard. 与此同时,各州应该可以访问整个GameBoard。 This allows the state to do things like 这允许国家做类似的事情

// Check for empty cell
GameBoard.GetPieceAt(move.ToPosition) == null;

// Check for opponent's piece
GameBoard.GetPieceAt(move.ToPosition).IsPlayer2;

To further extend this to your MMORPG scenario, I would pass any "sources" and/or "targets" via parameter 为了进一步将其扩展到您的MMORPG场景,我将通过参数传递任何“源”和/或“目标”

  • ie Collision source/target, or any objects that are directly affected 即碰撞源/目标,或任何直接受影响的对象

Conclusion 结论

Being so similar to a state problem, I think it's a good idea to look at state-based solutions. 与国家问题如此相似,我认为看一下基于状态的解决方案是个好主意。

Eg, State Pattern , Finite State Machines, State Transition Tables, automata, etc. 例如, 状态模式 ,有限状态机,状态转换表,自动机等。

Or you can try looking up decision tables and decision trees (haven't really used these myself, so I'm unable to say much about them) . 或者你可以尝试查找决策表和决策树(我自己没有真正使用过这些,所以我无法对它们说太多)

Unfortunately, I don't think I can recommend an exact solution. 不幸的是,我认为我不能推荐一个确切的解决方案。

But hopefully the few examples/keywords above will help you get started. 但希望上面的几个示例/关键字可以帮助您入门。

I'm thinking that a Strategy Pattern could be what you're looking for, it is lighter than the Specification Pattern suggested by HuorSwords, if you are looking for somthing easier to get started with. 我认为战略模式可能是你正在寻找的,它比HuorSwords建议的规范模式更轻,如果你正在寻找更容易开始的东西。

The rules you wish to use can be abstracted as strategies, then plugged into each piece as appropriate. 您希望使用的规则可以抽象为策略,然后根据需要插入每个部分。

Each rule can be kept in it's own class. 每条规则都可以保存在自己的类中。

Each strategy can be built up of a list of rules to be applied in order like you requested. 每个策略都可以按照您要求的顺序构建一系列规则。

我正在考虑针对您的问题的规范模式方法。

this is how I would design it. 这就是我设计它的方式。 (may or may not correspond to some design pattern). (可能或可能不对应于某些设计模式)。

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();
        }
    }

}

then, assuming you have some class/interface called pawn, that has a getX() method, you can do something like 那么,假设你有一些叫做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");

    }
}

EDIT: naturally Pawn can and should be changed to an interface like ThingsThatHaveAnXValue . 编辑:自然Pawn可以而且应该改成像ThingsThatHaveAnXValue这样的界面。 but for code clarity I left it as is 但为了代码清晰,我保持原样

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM