【问题标题】:How could I optimize this long line of "if" statements?我该如何优化这一长串“if”语句?
【发布时间】:2016-12-26 17:04:47
【问题描述】:

所以,我正在使用 Javascript 制作一个点击游戏,我遇到了我需要制作很多东西,我说的是 300 个 if 语句。我完成了所有极其乏味的工作,并开始了我的游戏。

为了向您展示问题,我需要向您展示我的游戏。 所以基本上,每次我点击一个按钮,十张图片中的一张都会更新。

问题是,我为每个数字以及您可以收集的每种材料都做了大量的 if 语句。

我想知道是否有办法摆脱所有这些 if 语句,让游戏正常运行,或者有没有办法优化它。

代码: JSFiddle 大部分代码是这样的:

if (A == 18) {
    document.getElementById("A1").src = "images/blocks/2A.png";
    document.getElementById("A2").src = "images/blocks/2A.png";
    document.getElementById("A3").src = "images/blocks/2A.png";
    document.getElementById("A4").src = "images/blocks/2A.png";
    document.getElementById("A5").src = "images/blocks/2A.png";
    document.getElementById("A6").src = "images/blocks/2A.png";
    document.getElementById("A7").src = "images/blocks/2A.png";
    document.getElementById("A8").src = "images/blocks/2A.png";
    document.getElementById("A9").src = "images/blocks/1A.png";
    document.getElementById("A10").src = "images/blocks/1A.png";
}

如果您需要实际游戏的链接,请告诉我,因为 JSFiddle 没有我的图片。

【问题讨论】:

  • 使用重构过程来设置 SRC。开关是转换和分配值的更易读的方式之一。
  • 当您发现自己使用许多 if 语句时,Switch 语句通常是更好的选择
  • @Fuzzybear 我不知道那是什么,也不知道该怎么做。我是一个非常新的程序员。所以我可能需要更多的线索。
  • 如何拥有一个类似const rules = [ {rule: 18, imagePaths : [ {A1: "2A.png" }...{A10: "1A.png" } ]}, {rule: 19,.....} ] 的规则数组,然后根据规则编号,从规则中读取图像路径并进行相应设置。
  • 如果你发现自己复制并粘贴了一段代码一次,你应该已经停下来想想你在做什么。请不要做300次,那太疯狂了。 总是比复制粘贴更好。

标签: javascript html if-statement refactoring


【解决方案1】:

这一切都取决于重构后的内容。你说你有很多 If 语句,如果这些是比较同一个变量 A 那么可以使用 switch 语句,例如:

switch (A)
{
   case 18: 
    document.getElementById("A1").src = "images/blocks/2A.png";
    document.getElementById("A2").src = "images/blocks/2A.png";
    document.getElementById("A3").src = "images/blocks/2A.png";
    document.getElementById("A4").src = "images/blocks/2A.png";
    document.getElementById("A5").src = "images/blocks/2A.png";
    document.getElementById("A6").src = "images/blocks/2A.png";
    document.getElementById("A7").src = "images/blocks/2A.png";
    document.getElementById("A8").src = "images/blocks/2A.png";
    document.getElementById("A9").src = "images/blocks/1A.png";
    document.getElementById("A10").src = "images/blocks/1A.png";
    break;
   case 19: 
    document.getElementById("A1").src = "images/blocks/2A.png";
    document.getElementById("A2").src = "images/blocks/2A.png";
    document.getElementById("A3").src = "images/blocks/2A.png";
    etc...
    break;

   default: 
       document.getElementById("A1").src = "images/blocks/2A.png";
       break;
}

看起来您可能想要创建一个函数,该函数传入 elementID 并返回图像字符串作为第二次重构。

【讨论】:

  • 看起来不错!我肯定会使用它,但我有一个问题。开关 (A) 是什么意思?
  • 所以代码正在获取您的变量 A 并检查它的值以查看它是否与 1819 或默认为...如果满足这种情况,则代码将进入该情况
  • @TheVoidChaos 真棒,很高兴我能帮上忙 :) 看看 Caelan 的重构。为您的 src 图片提供建议
  • 酷,仍在导入所有内容,只是想确保我做的一切正确。 imgur.com/a/odKeh
  • @TheVoidChaos 是的,看起来非常适合切换 :)
【解决方案2】:

拥有一个类似的规则数组怎么样

const rules = [ 
      { rule: 18, imagePaths : [ {A1: "2A.png" }...{A10:    "1A.png" } ]}, 
        { rule: 19 , imagePaths:[....] }          
      ] 

然后根据规则编号,从规则中读取imagePaths并进行相应设置。即,如果选择的值为18,则从rules数组中获取基于18的规则,然后循环imagePaths并根据规则中的值设置src。

【讨论】:

    【解决方案3】:

    如果你使用 jQuery,你可以试试这样的:

    if (A == 18) {
        $('[id^=A]').each(function() {
            $(this).attr("src", "images/blocks/2A.png");
        });
    
        $("#A9").attr("src", "images/blocks/1A.png");
        $("#A10").attr("src", "images/blocks/1A.png");
    }
    

    它的工作原理是抓取每个 ID 以“A”开头的img,然后在末尾添加特定的src 属性。

    对于两个独特的,一旦完成,它就会改变它们。

    我知道它并不能完全解决 if 语句问题,但是,它会大大减少您的代码 :-)

    【讨论】:

    • 看起来很酷!我不知道如何使用 jQuery,所以我没有使用它。
    • 哦,导入真的很简单。在您页面的<head> 内,将其放在那里:<script src="/squad/js/jquery-3.1.1.min.js"></script> :-)
    • 它让生活变得如此轻松哈哈
    • 我喜欢你的解决方案,非常好的 +1 和 @TheVoidChaos 易于将 jQuery 添加到 html 页面
    • 酷!刚刚得到它。我应该只导入代码,然后我就很好了吗?
    【解决方案4】:

    你可以使用for循环来设置A+i,但我建议你为具有相同内容的dom设置相同的类。您可以使用 getElementsByClass 或 jQuery 选择器,然后批量设置 src。

    function changeSrc(){
      $(".type1").attr("src", "https://i.stack.imgur.com/zU4NZ.jpg?s=32&g=1");
    }
    .type1 {display:block;}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <img class="type1" src="https://i.stack.imgur.com/xdrQi.jpg?s=48&g=1"/>
    <img class="type1" src="https://i.stack.imgur.com/xdrQi.jpg?s=48&g=1"/>
    <img class="type1" src="https://i.stack.imgur.com/xdrQi.jpg?s=48&g=1"/>
    <img class="type1" src="https://i.stack.imgur.com/xdrQi.jpg?s=48&g=1"/>
    <img class="type1" src="https://i.stack.imgur.com/xdrQi.jpg?s=48&g=1"/>
    <button onclick="changeSrc()">chang src</button>

    【讨论】:

    • 我该怎么做?我对编程很陌生。
    • @TheVoidChaos 我已经做了demo,看一下,你可以用一个代码批量修改同一个类的src,这样可以省很多ifs
    【解决方案5】:

    您拥有的唯一变量是计数器。从字面上看,如果您只写下规则,则可以直接从该计数器计算其他所有内容。

    规则是,

    部分值 A、B 和 C

    您想要创建标记为 A、B 和 C 的数字范围,每个范围从 0 到 99 并代表计数器的不同部分,如下所示:

    123456
    CCBBAA, i.e. A = 56, B = 34, C = 12
    
      8921
    CCBBAA, i.e. A = 21, B = 89, C = 0
    

    这可以通过将数字除以 100 的幂并计算 the remainder(模)到 100 来完成:

    (123456 DIV 100^0) MOD 100 = 56
    (123456 DIV 100^1) MOD 100 = 34
    (123456 DIV 100^2) MOD 100 = 12
    

    在 JS 中,整数除法可以通过向下舍入来执行。 Math.floor(140 / 100)不是1.4,而是1。MOD运算由%运算符进行,幂运算由Math.pow()函数进行。于是上面就变成了:

    Math.floor(123456 / Math.pow(100, 0)) % 100 // = 56
    Math.floor(123456 / Math.pow(100, 1)) % 100 // = 34
    Math.floor(123456 / Math.pow(100, 2)) % 100 // = 12
    

    这些是您的 A、B 和 C 部分的值,直接来自您的计数器值。

    每部分十张图片

    您希望用十张图片显示这些部分中的每一个。它们的名称范围从“0X”到“10X”,其中“X”是相应的节字母。

    假设部分值为 37,您希望前 7 个图像为“4X”,后 3 个图像为“3X”。

    同样,我们可以直接从节值中导出图像名称。让我们通过整数除法和模数将 37 分解为 3 和 7:

    div = Math.floor(value / 10); // 37 => 3
    rem = value % 10; // 37 => 7
    

    现在图像名称取决于我们正在处理的图像。使用从 0 到 9 的计数器 k,我们可以决定图像名称应该以 4 还是 3 开头。

    imageName = (k < rem ? div + 1 : div) + letter;
    

    对于任何小于 7 的k,我们得到“4X”,另一个得到“3X”。

    在代码中,这就是它的样子:

    var total = 0,
        letters = ['A', 'B', 'C'];
    
    function add() {
      total++;
      showState();
    }
    
    function showState() {
      var letter, range, value, imageName, div, rem, i, k;
    
      for (i = 0; i < 3; i++) {
        letter = letters[i]; // "A", "B", "C"
        range = Math.pow(100, i); // 1, 100, 10000
        value = Math.floor(total / range) % 100; // 0 .. 99
    
        document.getElementById(letter + "_Check").innerHTML = letter + ": " + value;
    
        for (k = 0; k < 10; k++) {
          div = Math.floor(value / 10); // 37 => 3
          rem = value % 10; // 37 => 7
          imageName = (k < rem ? div + 1 : div) + letter;
          elem = document.getElementById(letter + (k + 1));
          elem.src = "images/blocks/" + imageName + ".png";
        }
      }
    }
    

    这就是你需要的所有代码,没有一行是复制粘贴的。

    这是小提琴:https://jsfiddle.net/4kr2xwyq/2/

    练习:看看你是否可以完全用 HTML/CSS 替换图像(条形图之类的东西在 HTML 中很容易做到,颜色和元素尺寸可以即时计算和修改)或canvas。这最终可能比维护数十个静态图像文件更容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-12
      • 1970-01-01
      • 1970-01-01
      • 2015-07-27
      • 1970-01-01
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      相关资源
      最近更新 更多