我相信大多數(shù)博友都會玩游戲。
玩游戲,牽涉到狀態(tài)包含 登陸,正常,死亡,復(fù)活,下線,
在上面狀態(tài)的基礎(chǔ)上。同時包含 站立,走動,跑動,不可移動施法狀態(tài),
戰(zhàn)斗狀態(tài),
通常這是三個不同的分組。也就說可以同時存在的狀態(tài)和不可同時存在的狀態(tài)。
通常情況下也許你會這么定義,
//分組1public bool 登陸 = false;public bool 死亡 = false;public bool 復(fù)活 = false;public bool 下線 = false;public bool 正常 = false;public bool 打坐 = false;//分組2public bool 站立 = false;public bool 走動 = false;public bool 跑動 = false;public bool 施法 = false;//分組3public bool 戰(zhàn)斗 = false;
這種情況下,判斷就變得很復(fù)雜,因?yàn)榇嬖冢瑫r成立和非同時成立的狀態(tài),
例如,戰(zhàn)斗的同時可以走動,也可以跑動,或者技能施法
但是在打坐,下線,死亡等狀態(tài)的時候既不能走動,也不能戰(zhàn)斗也不能施法。
這樣一來一去,判斷的if else 會多的,讓你頭痛欲裂的吧。
或許你會想到,是要枚舉,因?yàn)槊杜e提供位運(yùn)算,提供Enum.HasFlag()方法來判斷是否存在值
public enum Stauts{ //分組1 空值, 登陸, 死亡, 復(fù)活, 下線, 正常, 打坐, //分組2 站立, 走動, 跑動, 施法, //分組3 戰(zhàn)斗,}查看一下使用方式
Stauts sValue = Stauts.登陸;sValue = sValue | Stauts.站立;if (sValue.HasFlag(Stauts.站立)){ Console.WriteLine("存在站立狀態(tài)");}輸出:
但是,繼續(xù)測試一下

這樣看出來了,我并沒有設(shè)置復(fù)活狀態(tài),但是卻存在復(fù)活狀態(tài)~!
探究得明原因,是因?yàn)槲换颍ǎ?運(yùn)算, 按位或(|)表示相對應(yīng)的每位至少有一個為1,則結(jié)果為1,只有兩個都為0,結(jié)果才為0.
所以,我們應(yīng)該設(shè)置枚舉值的不同值;
為了更直觀的查看運(yùn)算方式,我們輸出枚舉值的二進(jìn)制值,
public static void Show(Stauts value){ string log = ("結(jié)果:" + ((long)value).ToString().PadLeft(10, ' ') + " -> " + Convert.ToString(((long)value), 2).PadLeft(64, '0')); Console.WriteLine(log);}查看一下
我們看到
Stauts.登陸 | Stauts.死亡 位或計算方式,結(jié)果值。
這些明白了,那就是枚舉的值,定義不合法,
public enum Stauts{ //分組1 空值 = 0, 登陸 = 1, 死亡 = 2, 復(fù)活 = 4, 下線 = 8, 正常 = 10, 打坐 = 20, //分組2 站立 = 40, 走動 = 80, 跑動 = 100, 施法 = 200, //分組3 戰(zhàn)斗 = 400,}輸出結(jié)果

這下,沒有了復(fù)活狀態(tài)。這樣判斷,會減少一半,
可還是出現(xiàn)一個問題。那就是分組問題,也就說,死亡狀態(tài)和復(fù)活狀態(tài)不能同時存在,
死亡狀態(tài)和跑動狀態(tài)也不可能同時存在
那么我們在想,枚舉值的能不能分組呢?

可惜C#下面枚舉值,只能使用整型的基礎(chǔ)類型。
沒辦法只能另辟蹊徑:
public class EnumStatus { public long Value { get; PRivate set; } public long GroupValue { private set; get; } public EnumStatus(long value, long group) { this.Value = value; } }接下來我們設(shè)置一組常量
// 0x000000一旦竟然這組狀態(tài)忽略一切狀態(tài) public static EnumStatus Status0_空值 = new EnumStatus(0, 0x000000); public static EnumStatus Status0_登陸 = new EnumStatus(1 << 0, 0x000000); public static EnumStatus Status0_死亡 = new EnumStatus(1 << 1, 0x000000); public static EnumStatus Status0_復(fù)活 = new EnumStatus(1 << 2, 0x000000); public static EnumStatus Status0_下線 = new EnumStatus(1 << 3, 0x000000); public static EnumStatus Status0_正常 = new EnumStatus(1 << 4, 0x000000); public static EnumStatus Status1_打坐 = new EnumStatus(1 << 5, 0x000000); //移動組狀態(tài) 4個狀態(tài)值 public static EnumStatus Status1_站立 = new EnumStatus(1 << 6, 0x00000f);//4位一組 public static EnumStatus Status1_走動 = new EnumStatus(1 << 7, 0x00000f);// public static EnumStatus Status1_跑動 = new EnumStatus(1 << 8, 0x00000f);// public static EnumStatus Status1_施法 = new EnumStatus(1 << 9, 0x00000f);// 無法移動的施法 //戰(zhàn)斗狀態(tài) 這組只有一個狀態(tài)值 public static EnumStatus Status2_戰(zhàn)斗 = new EnumStatus(1 << 10, 0x000010);//
后面的分組值,的由來是


0x00000f 二進(jìn)制 0000,1111,
0x000010 二進(jìn)制 0001,0000,這樣就成功分組了
上面分組代碼代碼有錯誤:
// 0x000000一旦竟然這組狀態(tài)忽略一切狀態(tài) public static EnumStatus Status0_空值 = new EnumStatus(0, 0x000000); public static EnumStatus Status0_登陸 = new EnumStatus(1 << 0, 0x000000); public static EnumStatus Status0_死亡 = new EnumStatus(1 << 1, 0x000000); public static EnumStatus Status0_復(fù)活 = new EnumStatus(1 << 2, 0x000000); public static EnumStatus Status0_下線 = new EnumStatus(1 << 3, 0x000000); public static EnumStatus Status0_正常 = new EnumStatus(1 << 4, 0x000000); public static EnumStatus Status1_打坐 = new EnumStatus(1 << 5, 0x000000); //移動組狀態(tài) 4個狀態(tài)值 public static EnumStatus Status1_站立 = new EnumStatus(1 << 6, 0x0003c0);//4位一組 public static EnumStatus Status1_走動 = new EnumStatus(1 << 7, 0x0003c0);// public static EnumStatus Status1_跑動 = new EnumStatus(1 << 8, 0x0003c0);// public static EnumStatus Status1_施法 = new EnumStatus(1 << 9, 0x0003c0);// 無法移動的施法 //戰(zhàn)斗狀態(tài) 這組只有一個狀態(tài)值 public static EnumStatus Status2_戰(zhàn)斗 = new EnumStatus(1 << 10, 0x000400);//
由于前面的分組0占用了6位,
所以分組應(yīng)該改為,


也許看到這里你需要一定的位運(yùn)算知識了;
接下來我在介紹一下
位運(yùn)算的操作符
//// 按位異或(^)比較特殊,它比較的是如果兩個不同則值為1(如:(1、0)(0、1)),相同則為0(如:(1、1)(0、0))。//// 按位與(&)表示相對應(yīng)的兩位必須都為1,結(jié)果才為1,否則為0//// 按位或(|)表示相對應(yīng)的每位至少有一個為1,則結(jié)果為1,只有兩個都為0,結(jié)果才為0.//// 按位取反~ 運(yùn)算符對操作數(shù)執(zhí)行按位求補(bǔ)運(yùn)算,其效果相當(dāng)于反轉(zhuǎn)每一位。
修改一下計算值
public class EnumStatus { public long Value { get; private set; } public long GroupValue { private set; get; } public EnumStatus(long value, long group) { this.Value = value; } public bool HasFlag(EnumStatus status) { return (this.Value & status.Value) != 0; } public void Show() { string log = ("結(jié)果:" + this.Value.ToString().PadLeft(10, ' ') + " -> " + Convert.ToString(this.Value, 2).PadLeft(64, '0')); Console.WriteLine(log); } public static EnumStatus Operator |(EnumStatus statusLeft, EnumStatus statusRight) { statusLeft.Value = statusLeft.Value & statusRight.GroupValue | statusRight.Value; return statusLeft; } public static EnumStatus operator &(EnumStatus statusLeft, EnumStatus statusRight) { statusLeft.Value = statusLeft.Value & (~statusRight.Value); return statusLeft; } }
上面重載的 位域算法也是有問題的。
public static EnumStatus operator |(EnumStatus statusLeft, EnumStatus statusRight) { if (statusRight.GroupValue==0)//當(dāng)分組為0的時候清除所有狀態(tài) { statusLeft.Value = statusLeft.Value & (statusRight.GroupValue) | statusRight.Value; } else {//當(dāng)分組不為零 statusLeft.Value = statusLeft.Value & (~statusRight.GroupValue) | statusRight.Value; } return statusLeft; }這下才是正確的結(jié)果

這下是不是很輕松的解決了這一系列的狀態(tài)問題呢?包括各種同時存在和不同時的存在的狀態(tài)~!
但是這也有一個弊端,那就是值只有64個,也就是64個狀態(tài),,雖然存在分組。但是每一個分組的值都必須不同才行。
不知道,各位看官還有么沒有更好的辦法????
==============================================================================================
java版本的
java的枚舉是可以自定義的這方面比較方便
但是java沒有運(yùn)算符重載,
enum EnumStatus { //0x000000一旦竟然這組狀態(tài)忽略一切狀態(tài) Status0_空值(0, 0x000000), Status0_登陸(1 << 0, 0x000000), Status0_下線(1 << 1, 0x000000), Status0_正常(1 << 2, 0x000000), //移動組狀態(tài) Status1_走動(1 << 3, 0x00000f), Status1_跑動(1 << 4, 0x00000f); Long value = 0L; Long group = 0L; private EnumStatus(long value, long group) { this.value = value; this.group = group; } public boolean hasFlag(EnumStatus status) { return (value & (~status.value)) != 0; } public void addStatus(EnumStatus status) { value = value & status.group | status.value;
新聞熱點(diǎn)
疑難解答