c# - 规则/验证设计模式

标签 c# design-patterns

像国际象棋这样的游戏可以使用什么设计模式来创建规则/验证系统(这只是一个简单的例子,实际游戏需要更难的规则集)

我已经阅读了这个网站上的几个问题,但没有找到决定性的答案,也没有找到指向正确方向的答案。

此系统需要以下内容:

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

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

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

最佳答案

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

enter image description here

  • 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

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

过渡包括:

  1. 条件
  2. 行动
  • 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

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

  • 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.

这可以通过将条件检查行为封装为一个类来实现

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. Result: your pawn cannot move. The pawn should include the other pawns positions, or the gameboard in its validation.

在国际象棋场景中,我建议传递 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 、有限状态机、状态转换表、自动机等。

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

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

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

关于c# - 规则/验证设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14356851/

相关文章:

c# - 在 switch 语句中,有什么方法可以引用被切换的值吗?

language-agnostic - 新的设计模式/设计策略

java - 验证输入并相应执行操作

c# - 如果存在超过 37 个字符,如何将字符串拆分为多行

c# - 使用 SQL Server 数据库传输的 MassTransit

c# - 将通用实例转换为基类

java - 搜索策略以有效地从服务或服务器加载数据?

oop - 一棵树,其中每个节点可以有多个父节点

c# - 将音频流输入到 FFMPEG

c# - Linq 查询使所有调用都带外键的表数据