我不知道为什么这样做 [英] I don't know why it is doing this

查看:64
本文介绍了我不知道为什么这样做的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个项目只是为了训练一下C#(我是初学者),但我遇到了一个问题。 (我在控制台上做到了这一点,所以我不必再做一个完整的设计了)

我想拥有特定类型的行星,并使其中一些可以居住,其中一些无法居住。 (这可能是一个非常愚蠢的错误)



但是现在控制台显示某些类型不适合居住,而它们不在不适合居住的类型列表中。 (我跳过了现在不重要的代码)



I was making a project just to train a bit in C# (I'm a beginner), but I ran into a problem. (I did it on console so I didn't have to make a whole design again)
I wanted to have specific types of planets, and make some of them habitable and some of them uninhabitable. (It's probably a really stupid mistake)

But right now the console shows that some types aren't habitable while they are not in the list of uninhabitable types. (I skipped the code that isn't important for now)

class Planet
    {
        public biomes biome; 
        public bool isHabitable = true; 
        public Planet()
        { 
            biome = getBiome(); 
            biomes notHabitable = biomes.Radiated | biomes.Barred | biomes.Dead | biomes.In                                  ferno | biomes.Toxic | biomes.Frozen | biomes.Glacial;    
            //if ((notHabitable & biome) == biome) { isHabitable = false; }                            // I tried both of these if-statements, but they didn't work
            if (notHabitable.HasFlag(biome)) { isHabitable = false; }        
            else { isHabitable = true; } 
        }
 
        static readonly Random rd = new Random();
        static T RandomEnumValue<T>()
        {
            return Enum.GetValues(typeof(T)).Cast<T>().OrderBy(x => rd.Next()).FirstOrDefault();
        }  
        private biomes getBiome()
        {
            return RandomEnumValue<biomes>();
        } 
    } 
    [FlagsAttribute]
    public enum biomes : long
    {                                              
        Radiated = 0x0, 
        Barred = 0x1, 
        Dead = 0x2,    
        Inferno = 0x4, 
        Dune = 0x8, 
        Desert = 0x16, 
        Minimal = 0x32, 
        Toxic = 0x64,   
        Savannah = 0x128, 
        Steppe = 0x256, 
        Tundra = 0x512,                     
        Swamp = 0x1024, 
        Jungle = 0x2048, 
        Forest = 0x4096,
        Frozen = 0x8192,
        Ocean = 0x16384,
        Terran = 0x32768,
        Glacial = 0x65536
    }



     class Program
    {
        static bool WritePlanet()
        {
            Planet pl = new Planet();

            Console.WriteLine("Planet biome: " + pl.biome.ToString());
            Console.WriteLine("Habitable: " + pl.isHabitable);
            Console.WriteLine("Press [\\] + enter to generate a new planet");

            if (Console.ReadLine() == "\\")
            {
                Console.Clear();
                WritePlanet();
                return true;
            }
            
            else
            {
                return false;
            }
        }


        static void Main(string[] args)
        {
            try { WritePlanet(); }
            catch (Exception ex) { Console.WriteLine("Error" + ex); Console.ReadLine(); } 
        }
    } 

推荐答案

对于初学者来说,这不是一个愚蠢的问题,至少你制定了它是正确的,这是如此罕见的这些天,我特别感谢。



您的想法是使用位映射枚举类型来描述紧凑的行星状态良好的支持方式是好的。只有声明才能以这种方式改进:

For a beginner, this is not so silly question, at least you formulated it correctly, which is so rare these days, my special thanks for that.

Your idea to use bit-mapped enumeration type to describe the planet status in a compact and well-supportable way is good. Only the declaration could be improved in this way:
internal enum Biomes : ushort
{                                              
        Radiated = 1 << 0, 
        Barred = 1 << 1, 
        Dead = 1 << 2,   
        Inferno = 1 << 3, 
        Dune = 1 << 4,
        //...
}

我希望你明白了。另请注意,对于基础整数类型,使用无符号类型,在大多数情况下,您也可以跳过它。我也将这个名字大写,以满足(好)微软的命名建议(你是正确的,使它成为一个复数名词)。



现在,让我们谈谈你的错误。你错误地测试了这些位。这是如何做到的:

I hope you got the idea. Also note the use of the unsigned type for underlying integer type, which you can also just skip, in most cases. I also capitalize the name to meet (good) Microsoft naming recommendations (you were correct to make it a plural noun).

Now, let's talk about your bug. You test the bits incorrectly. This is how it can be done:

bool isRadiated = (biome & Biomes.Radiated) > 0;
boole isBarred = (biome & Biomes.Barred) > 0;
// are you getting the idea?
//...
biomes notHabitable = isRadiated | isBarred /* ... and so on; you could write it shorter... */;



嗯,这是一个非常明显的错误,特别是如果你注意到你甚至没有使用它 biome 值。嗯,这样的事情发生了,特别是起初。 :-)



我建议你学习位操作真的很好:http://msdn.microsoft.com/en-us/library/6a71f45d.aspx [ ^ ]。



另外,对于真正高级的枚举使用(与是否位图),请参阅我关于此主题的三篇文章: http://www.codeproject.com/Articles/SAKryukov #articles [ ^ ]。



最后,辐射并不意味着生命是不可能的。一些生命形式甚至可以承受地球上的恶劣辐射水平。这是生物学,而不是编程。对于家庭锻炼,尝试回答一个不同的问题:地球是否适合居住?。这个问题并不像看起来那么容易。例如,看看这个论坛上的许多帖子可能有助于得出地球可能适合居住的结论,但知识生活的存在可能是一个争议问题。 :-)



祝你好运。新年快乐!



-SA


Well, it was quite an obvious bug, especially if you pay attention that you did not even use biome value. Well, such things happen, especially at first. :-)

I would advise your to learn bit operations really well: http://msdn.microsoft.com/en-us/library/6a71f45d.aspx[^].

Also, for really advanced use of enumerations (with bit maps or not), please see my three articles on this topic: http://www.codeproject.com/Articles/SAKryukov#articles[^].

And finally, that "radiated" does not mean that life is impossible. Some life form can withstand harsh radiation levels even on Earth. This is biology, not programming. For a home exercise, try to answer a different question: "Is the Earth habitable?". This question is not so easy as it may seem. For example, the look at many posts at this forum may help to conclude that the Earth might be habitable, but the presence of intellectual life could be a matter of controversies. :-)

Good luck. Happy New Year!

—SA


我知道发生了什么...



您的枚举被定义为标志,但您错误地为标志分配值,它应该是:



I know what's happening...

Your enum is defined as flags, but you are incorrectly assigning values to the flags, it should be:

[Flags]
public enum biomes : long
    {                                              
        Radiated = 0x0, 
        Barred = 0x1, 
        Dead = 0x2,    
        Inferno = 0x4, 
        Dune = 0x8, 
        Desert = 0x10, 
        Minimal = 0x20, 
        Toxic = 0x40,   
        Savannah = 0x80, 
        Steppe = 0x100, 
        Tundra = 0x200,                     
        Swamp = 0x400, 
        Jungle = 0x800, 
        Forest = 0x1000,
        Frozen = 0x2000,
        Ocean = 0x4000,
        Terran = 0x8000,
        Glacial = 0x10000
    }





您提供的十六进制值实际上是其他值的组合。您不会乘以2(如果您要分配十进制值,则会这样),但在执行十六进制值时,8 * 2 = 0x10,而不是0x16。 0x16是你可能不想要的其他值的组合。



或者你可以从值中删除0x,同样,你不应该使用0x0作为标志值,因为它字面意思是无标志,0x0应始终为无,并在0x01处开始您的值。



编辑:这是我的意思更改它以便更容易添加可居住/可居住的行星:





The hex values you were giving were actually combinations of other values. You don't multiply by 2 (you would if you were assigning decimal values), but when doing hex values, 8 * 2 = 0x10, not 0x16 for example. 0x16 is a combination of other values you probably didn't want.

OR you could just remove the 0x from the value, also, you should not use 0x0 as a flag value, since it literally means "no flags", 0x0 should always be "None", and start your values at 0x01.

here is how I would change it to make it easier to add habitable/inhabitable planets:

[Flags]
public enum Biomes
{
    Habitable = 0x01,
    Uninhabitable = 0x02,
    Barred = 0x04 | Uninhabitable,
    Dead = 0x08 | Uninhabitable,
    Radiated = 0x10 | Uninhabitable,
    Inferno = 0x20 | Uninhabitable,
    Toxic = 0x40 | Uninhabitable,
    Frozen = 0x80 | Uninhabitable,
    Glacial = 0x100 | Uninhabitable,
    Dune = 0x200 | Habitable,
    Desert = 0x400 | Habitable,
    Minimal = 0x800 | Habitable,
    Savannah = 0x1000 | Habitable,
    Steppe = 0x2000 | Habitable,
    Tundra = 0x4000 | Habitable,
    Swamp = 0x8000 | Habitable,
    Jungle = 0x10000 | Habitable,
    Forest = 0x20000 | Habitable,
    Ocean = 0x40000 | Habitable,
    Terran = 0x80000 | Habitable
}





从enum(而不是在课堂上定义)中可以清楚地看到什么是适合居住的不适合居住,对旗帜非常好用。您也可以像解决方案2中的谢尔盖所说的那样使用移位运算符,但是我发现它们在理解能力方面很受欢迎。我更喜欢使用直接十六进制,但你喜欢的是你的电话。



现在你的旗帜检查将适用于任何星球,因为你已经将它们定义为旗帜的组合。我认为这是一种比最初定义的更好的方法,因为你只需要检查Habitable或Uninhabitable标志,看看行星是否是一个,而不是检查某个行星的组合。这也是非常可维护的(例如,改变,例如,从Habitable到不可居住的最小行星只需要对枚举进行小的改动)。



Which makes it very clear from the enum (instead of defining it in the class) what is habitable and uninhabitable, and is a very good use for flags. You can also use shift operators like Sergey said in Solution 2, however I find that they are hit and miss as far as understand-ability. I prefer to use straight hex but your preference is your call.

Now your flag checking will work with any planet since you've defined them as a combination of flags. I think this is a better way than originally defined, since you only have to check for the Habitable or Uninhabitable flag to see if a planet is one or the other, rather than check for a certain combination of planets. This is also very maintainable (changing, for example, the Minimal planet from Habitable to Uninhabitable only requires a small change to the enum).


这篇关于我不知道为什么这样做的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆