如何用具体操作的二进制字符/项目进行操作?

我有下一个问题。

一个项目可以有很多状态:

NORMAL = 0000000 DRY = 0000001 HOT = 0000010 BURNING = 0000100 WET = 0001000 COLD = 0010000 FROZEN = 0100000 POISONED= 1000000 

一个项目可以同时有一些状态,但不是全部

  • 不可能同时干燥和潮湿。
  • 如果你冷藏一个湿的物品,它变成冷冻。
  • 如果你把一个湿的物品,它变成正常
  • 一个项目可以燃烧和毒药

等等。

我已经尝试将二进制标志设置为状态,并使用AND来组合不同的状态,检查之前是否可以执行,或者更改为其他状态。

是否存在一个具体的方法来有效地解决这个问题,而没有一个无休止的开关来检查每一个状态与每个新的状态?

检查两种不同的状态是相对容易的,但是如果存在第三种状态,则不是微不足道的。

当我需要使用标志时,我通常会沿着这些线做一些事情。

 enum obj_state { NORMAL = 0x00000; DRY = 0x00002; HOT = 0x00004; BURNING = 0x00008; WET = 0x00010; COLD = 0x00020; FROZEN = 0x00040; POISONED = 0x00080; }; int objFlags; void DryOn() { objFlags |= DRY; } void HotOn() { objFlags |= HOT; } // etc... void DryOff() { if (FlagOn(DRY)) objFlags ^= DRY; } void HotOff() { if (FlagOn(HOT)) objFlags ^= HOT; } // etc... bool isDryOn() { return FlagOn(DRY); } bool isHotOn() { return FlagOn(HOT); } // etc... // If the given Bit is on this will return true. bool FlagOn(obj_state s) { return (objFlags & s) == s; } // returns -1 if failed, 1 if successful int apply_cold(Object obj) { if (obj.isWetOn()) { obj.ColdOff(); obj.WetOff(); obj.FrozenOn(); } else return -1; return 1; } //--------------------------------- // alt way of doing DryOn and WetOn // since these conditions can not be // active at the same time. void DryOn() { if (isWetOn()) return; else objFlags |= DRY; } void WetOn() { if (isDryOn()) return; else; objFlags |= WET; } 

这使得像apply_cold()这样的东西非常容易使用,而且显然可以在干燥和潮湿的状态下构建。

两点意见:

  1. 你的条件系统似乎有两个正交轴:温度和毒素。 像这样代表他们。
  2. 在思考这个问题时,你应该把状态状态分开。 COLDHOT是你提及他们的方式的转变,而不是状态。

结合这些观察结果会导致如下的情况:

 // These is the representation of the two axes. int temperature; // can be between -2 and +2, 0 is normal, 1 is hot, 2 is burning, -1 is cold, -2 is frozen bool poisoned; // These methods represent state transitions. void applyHeat() { if ( temperature <= 2 ) { ++temperature; } } void applyCold() { if ( temperature >= -2 ) { --temperature; } } void applyPoison() { poisoned = true; } void removePoison() { poisoned = false; } 

将您的状态表示为您所写的位掩码,您可以将约束描述转换为代码:

 if ( (state & HOT) && (state & COLD) ) { state &= ~HOT; state &= ~COLD; // reset both HOT and COLD flags if both are set } if ( (state & COLD) && (state & WET) ) { state &= ~WET; // cold items can't be wet state |= FROZEN; // instead, they're frozen } if ( (state & HOT) && (state & WET) ) { state &= ~WET; // hot and wet items dry up... state &= ~HOT; // ...and cool down } // add other constraints here... 

你可以把它包装成一个makeStateConsistent() ,你可以在testing状态位之前调用它来确保状态是有意义的。

然而,这种方法的一个局限是它不能说明状态变化的顺序。 例如,如果您想对潮湿的物品产生不同的效果,比湿的物品变热,则不能这样做:所有的makeStateConsistent()方法都会看到一个潮湿的物体,没有有关它如何成为这样的信息。

相反,你可以做的是使项目状态私人(至less在概念上),并通过一系列的方法,如coolItem()heatItem()wetItem()dryItem()等操作它。 这样,状态改变方法本身可以处理任何额外的改变。 例如, heatItem()方法可能如下所示:

 if ( state & COLD ) { state &= ~COLD; // cold items become normal temp when heated if ( state & FROZEN ) { state &= ~FROZEN; // ...and melt if they were frozen state |= WET; } } else if ( state & WET ) { state &= ~WET; // wet items dry up when heated, stay normal temp } else { state |= HOT; // dry normal temp items become hot } 

当然,你可能还想要makeStateConsistent()方法作为备份,以防万一你的状态改变方法有错误。

此外,在某些情况下,您可以通过消除不必要的状态来简化代码。 例如,你是否真的需要一个单独的FROZEN状态,还是仅仅把冷冻和潮湿物品当作冷冻物品就足够了?