4

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

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

该系统将需要以下内容:

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

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

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

4

4 回答 4

8

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

在此处输入图像描述

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

  • 该规则应该分两步应用:首先,它需要验证(可以将棋子A移动到方块D4),如果为真则执行方法A 如果为假则执行方法B

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

过渡包括:

  1. 条件)
  2. 行动
  • 每个对象都可以有多个需要按特定顺序应用的规则。规则 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
                    }
}
  • 请注意,这将用于后端的多人游戏

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

在国际象棋场景中,我建议传递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 场景,我将通过参数传递任何“源”和/或“目标”

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

结论

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

例如,状态模式、有限状态机、状态转换表、自动机等。

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

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

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

于 2013-01-16T17:30:17.190 回答
2

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

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

每个规则都可以保存在它自己的类中。

每个策略都可以建立一个规则列表,按照您的要求按顺序应用。

于 2013-01-16T12:31:59.353 回答
1

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

于 2013-01-16T11:18:26.920 回答
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. 但为了代码清晰,我保持原样

于 2013-01-16T12:01:11.550 回答