繁体   English   中英

如何处理大量的if-else语句?

[英]How to handle large number of if-else statements?

我正在为一个项目创建一个游戏模拟器。 游戏由两支军队相互战斗组成。 每支军队由多名士兵组成。 士兵正在执行指令(从文本中读取)。

每条指令都是一个像移动,转动等命令。我来到了需要创建一个方法的部分,该方法将检查下一条指令是什么并执行它。 指令不太相似,这意味着它们没有相同的方法。

运行此方法的类存储游戏字段(2d数组)和所有士兵的数组,循环遍历它并执行每个士兵的下一个指令。 所以在这一点上,我有一个很长的列表,其中if-else描述每条指令会发生什么。 我正试图找到一种更好的方法来写这个,但无法弄清楚如何。 我知道很少的设计模式,但是我无法通过接口或继承来实现这一点(不确定它是否可行)。

如何解决if-else语句和长代码过多的问题?

我知道这里可能没有足够的信息,但任何建议都表示赞赏。

说明不太相似,这意味着它们没有相同的方法[...]如何解决if-else语句和长代码太多的问题?

一般来说,如果你有“如果这种类型,那么这样做”,那么你就有了多态性(虚函数)的情况。 在这种情况下,每个实体的共同点是,您正在尝试更新游戏模拟,并且游戏的每个部分(每个士兵)对更新模拟的含义有不同的概念。

我来到了需要创建一个方法的部分,该方法将检查下一条指令是什么并执行它。

我建议将其拆分为多个抽象级别:

  • 表示模拟本身
  • 从用户那里获取输入(读取文件)
  • 将输入转换为模拟中的操作

您希望获得此类独立性的原因是,如果您决定更改接受模拟输入的方式,则无需重新构建整个游戏。

游戏模拟

每个游戏都必须建立某种初始状态,因此他们知道世界应该是什么样子,以及每个动作应该如何改变世界。

在该状态设置之后,模拟将遍历全局循环,通常称为“游戏循环”,并将继续循环直到模拟完成(您退出,游戏结束,或者没有更多输入)。

大多数游戏如何处理他们的输入

在每个游戏循环开始时,它们会查找自上次循环以来的用户输入。 他们可能会寻找按键,鼠标输入,控制台上的输入,网络数据包等。他们接受此输入并将其转换为动作以进行模拟处理。

大多数游戏如何处理模拟:

大多数游戏为每个游戏实体制作一个抽象基类,并保留所有实体的全局集合。 实体基类将提供虚拟Update方法。 此方法将采用执行更新所需的任何状态。

一个例子,使用C#语法(对不起,我不懂Java)

public abstract class GameEntity
{
    public abstract void Update(TimeSpan timeElapsedSinceLastUpdate, World theWorld);
}

通过游戏循环的每次迭代,游戏将通过所有实体进行子循环,在每个实体上调用Update 每个游戏实体都有自己的Update实现。

特定实体可能会对输入做出反应,或更新某些内部状态。 它可能会根据其速度更新其位置。 它可能会检查自上次更新以来用户引发的操作,以查看是否应更改其加速度/位置。 它可以检查是否已经过了足够的时间来在游戏状态之间转换(例如,从counting-down状态到exploding状态)。 它可能与世界上的其他实体进行交叉/碰撞测试。

关键在于时间向前推进,每个游戏实体都可以拥有自己独立的概念,即时间变化。

如果您的游戏是基于回合的(因此不需要时钟时间的概念),或者每个实体已经具有对世界的引用,您可以从基础Update方法的签名中删除它们。 如果这变得有用,您可以考虑添加int updateNumberint currentTurn参数。

如何处理模拟:

你可能有士兵作为你唯一的实体类型。 动作将独立于更新命令传递给士兵。 然后在调用更新时执行操作。

如何处理模拟的初始状态:

你必须弄清楚你必须从多少士兵开始,以及他们的属性(类型,等级,健康等)。 您可能还需要有关世界的信息,例如网格大小或可能的地形数据。

如何处理输入:

  • 您可以在创建士兵时提供动作,跟踪动作以及应该执行哪个动作
  • 您可以在每次转弯/更新之前将要执行的操作提供给每个实体

无论哪种方式取决于您,但在每次更新之前进行操作将使您的游戏在未来更灵活地进行更改。 在大多数互动游戏中,用户倾向于一次输入一个回合。

这也不会限制您在每个回合创建要执行的命令队列,因为实体本身不必处理队列,因此它不必知道存在这样的队列。

您可能想要查看状态模式

如果你考虑一下,你真正想做的是创造一种专门用于游戏的新语言。 它被称为DSL(域特定语言)。

这在计算机科学中非常普遍。

如果你认为你的语言会非常简单,那就是这样的:

command1 arg1 ... argn
..
commandN argN1 ... argNn

然后,您可以使用pattern命令并按名称查找正确的命令。 这就是其他回应的内容。

但这真的是BASIC。 你如何管理错误? 太多,没有足够的论据? 最终条件表达式或循环? 如何向您的命令发送复杂的结构或参数? 如何定义'宏'或命令列表?

如果你想要更多的东西取决于你真正想做的事情,你可以去几条路线:

  • 使用带有XSD而不是自由文本的XML格式将允许对订单列表及其参数进行验证时间检查。 它还允许使用或通过数据结构,宏观或简单表达。 更好,但不是那么容易阅读。
  • 使用可以在java中很好地嵌入的现有脚本语言(如Groovy,Jython,clojure ...),以便您的命令实际上是源代码。 所以他们可以做语言允许的所有事情(所以你有循环,函数,脚本语言可以做的任何事情),并且你公开了允许控制你的士兵的API。
  • 你真的想要特定的东西。 一种特殊的语言,可能比我的示例中的语言更具出色性,但不希望包含常规脚本语言。 你有一套范围的工具,比如Eclipse Modeling framework中的XText,它就是为此而设计的。 帮助制作DSL。 或者你可以定义一个语法并使用像ANTR这样的解析器来帮助你。

这是一个非常广泛的主题,如果您的需求是基本的,一个大的开关案例,或命令模式就足够了。 如果你想要更专业但仍然有效的东西,我会尝试我指出的其他解决方案之一并花时间看看每个人能提供什么,可能与否,以及它如何为你服务......或者不是。

当然有可能:)你会使用多态 这是一个很好的例子

暂无
暂无

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

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