首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以简化检查组合的if-语句?

是否可以简化检查组合的if-语句?
EN

Stack Overflow用户
提问于 2016-04-17 04:19:48
回答 5查看 2K关注 0票数 55

我目前正在努力为游戏添加声音效果,尽管我当前的代码运行良好,但我正在寻找一种简化它的方法。基本上,游戏中的每个对象都有一个字符串值,表示它的材料(即。“木头”、“金属”等),当两个物体相撞时,在组合的基础上播放声音效果。代码实质上如下所示:

代码语言:javascript
复制
if( (matA == "metal" && matB == "wood") || (matA == "wood" && matB == "metal") )
{
    //play sound for metal-wood collision
}

但我想知道是否有办法将if -语句简化为这样的东西:

代码语言:javascript
复制
if( one of the materials is wood && one of the materials is metal )
{
    //play sound for metal-wood collision
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2016-04-17 09:29:33

你应该用一个enum来代替字符串,你可以用一个Dictionary来保存相应的声音组合。您可以跳过多个if语句,并使用Dictionary自动为每个材料选择相应的对象。例如:

代码语言:javascript
复制
[Flags]
enum Material  
    {  
        Wood=1,
        Iron=2,
        Glass=4
        //...  
    }  
Dictionary<Material,SoundObject> sounds = new Dictionary<Material,SoundObject>();  
sounds.add(Material.Wood,woodSound);  
sounds.add(Material.Iron,ironSound);  
sounds.add(Material.Wood | Material.Iron,woodAndIronSound);

// And play corresponding sound directly without any if statement.  
sounds[object.Material].Play();  
sounds[matA | matB].Play();  

业绩优势:

您还将通过使用这种方法来提高性能。因为对Enum值或散列代码的绝对整数比较比字符串比较更容易,速度更快。关于字典和多个if-else语句,if/else if语句序列是线性执行的;因此,它的性能很大程度上取决于if语句的数量和对象的相等比较器;而Dictionary是基于哈希表的。它使用一个优化的索引集合来存储值,有效地保持了恒定的访问时间。这意味着无论字典中有多少键,您都将在固定的时间内访问值,而且在大多数情况下,它比多个if语句更快。

业绩比较:

在本例中,我们将比较两种方法的性能:

代码语言:javascript
复制
//If you want to try, just copy the code and see the result.  
static Dictionary<char, short> myHashTable = Enumerable.Range((short)'A', (short)'z').ToDictionary((ch) => (char)ch, (sh) => (short)sh);  

static void Main(string[] args)  
{  
    System.Diagnostics.Stopwatch SW = new   System.Diagnostics.Stopwatch();  
    short temp = 0;  
    SW.Start();  
    for(int i=0;i<10000000;i++)  
    temp = getValue('z');  
    SW.Stop();  
    Console.WriteLine(SW.ElapsedMilliseconds );  
    SW.Reset();              
    SW.Start();  
    for(int i =0;i<10000000;i++)  
    temp = myHashTable['a'];  
    SW.Stop();  
    Console.WriteLine(SW.ElapsedMilliseconds);  
}  
static short getValue(char input)  
{  
    if (input == 'a')  
        return (short)'a';  
    else if (input == 'b')  
        return (short)'b';  
    else if (input == 'c')  
        return (short)'c';  
    else if (input == 'd')  
        return (short)'d';  
    else if (input == 'e')  
        return (short)'e';  
    else if (input == 'f')  
        return (short)'f';  
    else if (input == 'g')  
        return (short)'g';  
    else if (input == 'h')  
        return (short)'h';  
    else if (input == 'i')  
        return (short)'i';  
    else if (input == 'j')  
        return (short)'j';  
    else if (input == 'k')  
        return (short)'k';  
    else if (input == 'l')  
        return (short)'l';  
    else if (input == 'm')  
        return (short)'m';  
    else if (input == 'n')  
        return (short)'n';  
    else if (input == 'o')  
        return (short)'o';  
    else if (input == 'p')  
        return (short)'p';  
    else if (input == 'q')  
        return (short)'q';  
    else if (input == 'r')  
        return (short)'r';  
    else if (input == 's')  
        return (short)'s';  
    else if (input == 't')  
        return (short)'t';  
    else if (input == 'u')  
        return (short)'u';  
    else if (input == 'v')  
        return (short)'v';  
    else if (input == 'w')  
        return (short)'w';  
    else if (input == 'x')  
        return (short)'x';  
    else if (input == 'y')  
        return (short)'y';  
    else if (input == 'z')  
        return (short)'z';  
    return 0;  

} 

结果:

包含26个条目的if语句,包含122个条目的字典。

593 254

579 256

572 252

570 246

587 248

574 291

576 246

685 265

599 282

723 338

这表明字典比if/else if语句快2倍多。

票数 56
EN

Stack Overflow用户

发布于 2016-04-17 09:56:37

当您发现自己是重复代码时,通常的方法是提取一个方法:

代码语言:javascript
复制
if (IsWoodAndMetal(matA, matB) || IsWoodAndMetal(matB, matA))
{
    // play sound for metal-wood collision
}

其中IsWoodAndMetal被定义为:

代码语言:javascript
复制
public static bool IsWoodAndMetal(string matA, string matB)
{
    return matA == "wood" && matB == "metal";
}

这将与原始代码一样快,不像所有分配内存的linq/list和string级联解决方案那样快,这是用于频繁的游戏循环的坏消息,因为它会导致更频繁和/或更长的垃圾收集。

如果||仍然困扰您,我们可以更进一步,提取:

代码语言:javascript
复制
public static bool EitherParameterOrder<T>(Func<T, T, bool> func, T a, T b)
{
    return func(a, b) || func(b, a);
}

现在的案文如下:

代码语言:javascript
复制
if (EitherParameterOrder(IsWoodAndMetal, matA, matB))
{
    // play sound for metal-wood collision
}

与其他解决方案相比,我仍然希望它的性能(除了字典解决方案,当您有几个条目时)。

票数 13
EN

Stack Overflow用户

发布于 2016-04-17 10:47:03

它可能不是最现代的解决方案,但使用素数作为参考你的材料可以提高你的性能。我知道并理解“在必要之前进行优化”是许多程序员不建议的,但是在这种情况下,我认为它并没有增加代码的复杂性,而是提高了这个(相当微不足道的)任务的性能。

代码语言:javascript
复制
public static class Materials
{
   public static uint Wood = 2,
   public static uint Metal = 3,
   public static uint Dirt = 5,
   // etc...
}

if(matA*matB == Materials.Wood*Materials.Metal)
{
   //play sound for metal-wood collision
}

//or with enums but annoying casts are necessary...

enum Materials:uint
{
   Wood = 2,
   Metal = 3,
   Dirt = 5,
   // etc...
}

if((uint)matA*(uint)matB == (uint)Materials.Wood*(uint)Materials.Metal)
{
   //play sound for metal-wood collision
}

这种方法不依赖于物质的顺序(交换乘法),不需要对字符串进行任何长的比较,也不需要比整数更复杂的结构。

假设您希望保持所有的引用数4字节整数和最大的4字节整数的平方根约为65535,那么您将有大约6550个可能的素数低于65535,这样没有任何积会导致整数溢出。到目前为止,这对于任何普通的游戏来说都是足够的了。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36672631

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档