0

我正在使用开关作为我的 XNA 游戏的状态管理器。该开关是主要更新方法的一部分,因此它每帧都运行。有时我需要设置一个计时器值,并且每个方法调用只能设置一次。有多种方法可以根据情况设置计时器,因此它不能使用当前和先前的状态编号来检查是否可以覆盖先前的时间。

case "state 34": {
SetTime(theTime); // should run only once
// other things
if (TheTimeisRight(time)) // runs every call
    {
        SetTime(theTime); // should run only once
        if (TheTimeisRight(time)) 
        { /*  some methods  */ }
    }
break; }

我怎样才能做到这一点,或者有没有更好的方法来做到这一点而无需离开交换机?(更改 SetTime 方法是可以的,但我不想用额外的代码弄乱开关)

4

4 回答 4

1

另一种方法:在要调用的方法周围引入一个包装器:

    public sealed class RunOnceAction
    {
        private readonly Action F;
        private bool hasRun;

        public RunOnceAction(Action f)
        {
            F = f;
        }

        public void run()
        {
            if (hasRun) return;
            F();
            hasRun = true;
        }
    }

var setTimeOnce = new RunOnceAction(() => SetTime(theTime));然后在 switch 语句之前创建,并在那里调用 as setTimeOnce.run()。根据需要调整参数/返回值。

于 2012-10-19T05:26:56.047 回答
0

将呼叫置于循环之外。
您可能需要一个单独的条件语句来确定它是否应该运行,但这比尝试使用标志和/或各种其他臭代码方法来控制调用的重复要好得多。

编辑:

这就是我将它放在交换机外部的一个地方的意思:

if (someCondition && someOtherCondition && yetAnotherCondition)  
    setTime(theTime); // just one call, in one place, gets executed once

switch(someValue) 
{
    case "state 34": {
        //SetTime(theTime); // no longer necessary
        // other things
        if (TheTimeisRight(time)) // runs every call
        {
            //SetTime(theTime); // no longer necessary
            if (TheTimeisRight(time)) 
            { /*  some methods  */ }
        }
        break;

    ...etc...
}

一句忠告:对你的开关值使用枚举而不是字符串。

老实说,这几乎是任何人都可以在没有看到更完整的代码示例的情况下实际帮助您的程度(我认为您提供给我们的示例有些做作,并且与您所拥有的不太准确?)。解决此问题的最佳方法可能是解构 switch 语句并重新开始,因为维护状态机不是处理这种情况的最佳方法,或者您需要引入一些其他状态。

于 2012-10-19T05:21:16.607 回答
0

如果您不想弄乱布尔变量 ala hasSetTimeAlready,您总是可以引入另一个调用该方法的状态,然后进入原始状态。

于 2012-10-19T05:22:55.423 回答
0

我已经诉诸于使用HashSet<int>来检查当前SetTime(time, num)方法之前是否没有被调用过if (!hashSet.Contains(num))

void SetTime(int time, int num)
{
    if (!hashSet.Contains(num))
        {
            theTime = time;
            hashSet.Add(num);
        }
}

当然看起来不太酷,但可以工作并且不会过多地损坏方法调用(视觉上),因此保存了开关的可读性。

于 2012-10-19T15:49:42.907 回答