【问题标题】:Shuffling array JavaScript洗牌数组javascript
【发布时间】:2013-06-28 21:04:15
【问题描述】:
<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf=8" />
        <title>Blackjack</title>
        <link rel="stylesheet" href="blackjack.css" />

        <script type="text/javascript">

            var H2 = 2; var S2 = 2; var D2 = 2; var C2 = 2;
            var H3 = 3; var S3 = 3; var D3 = 3; var C3 = 3; 



            var deck = new Array(H2, S2, D2, C2, H3, S3, D3, C3);

            var new_deck = new Array();

            var r;

            document.write("deck = ")

            for (r =0; r<deck.length; r++){
                document.write(deck[r]);
                }

            document.write("</br>")

            document.write("new deck = ")

            for (r=0; r<new_deck.length; r++){
                document.write(new_deck[r]);
                }

            document.write("</br>")

            for (r=0;r<deck.length;r++){
                var randomindex = Math.floor(Math.random()*deck.length);
                new_deck.push(randomindex)
                deck.pop(randomindex)
                }

            document.write("deck = ")

            for (r =0; r<deck.length; r++){
                document.write(deck[r]);
                }

            document.write("</br>")

            document.write("new deck = ")

            for (r=0; r<new_deck.length; r++){
                document.write(new_deck[r]);
                }

            document.write("</br>")


        </script>

    </head>
    <body>
    </body>
</html>

显然这不是完整的二十一点游戏。这只是一个测试,通过在洗牌前后打印两个牌组(数组)的内容来查看洗牌是否有效。 我目前只使用 8 张卡,4 张 2 和 4 张 3。 我从中得到的是:

deck = 22223333
new deck = 
deck = 2222
new deck = 7502

我希望得到的是:

deck = 22223333
new deck = 
deck = 
new deck = 23232323 (or any of the 8 numbers, generated randomly)

所以应该洗那8张牌,我做错了什么? 我只是 javascript 的新手,但我以前使用过一些 python。我在 python 中做了类似的事情并且工作得很好,但我不确定这里有什么问题。 感谢您提前提供任何答案!

【问题讨论】:

    标签: javascript html javascript-events


    【解决方案1】:

    第一个问题始于for 循环,您可以在其中随机化牌组。您需要在包含甲板长度的循环之前创建一个新变量。见:

    for (r=0;r<deck.length;r++){
        var randomindex = Math.floor(Math.random()*deck.length);
        new_deck.push(randomindex)
        deck.pop(randomindex)
    }
    

    您在这里所做的是r 增加 1,同时 deck.length 减少 1(由于 for 循环中的 pop) .所以,这就是为什么你的洗牌套牌中只有四张“牌”。第二个问题是你不是push将一张牌放入新牌组,而是pushrandomindex本身。

    这段代码应该可以解决问题:

    var i = deck.length;
    for (r=0;r<i;r++){
        var randomindex = Math.floor(Math.random()*deck.length);
        new_deck.push(deck.splice(randomindex, 1));
    }
    

    (P.S.:最初,上述for 循环中的两个语句都没有最后的分号。)

    编辑:您也可以使用while() 循环。见meiamsome's answer

    编辑 2: 正如 Joe 下面提到的,pop() 不接受参数。 splice() 做你想做的事。

    【讨论】:

    • pop 不带参数。
    • 你也可以for(var r = deck.length; r &gt; 0; r--)
    • 根据@JoeFrambach,您应该将deck.pop(randomindex) 替换为deck.splice(randomindex, 1),以防万一您被卡住了。
    【解决方案2】:

    您的 new_deck 只包含索引,而不是值,并且在选择下一个随机值之前,您不会删除先前选择的值。 .pop() 不带参数,因此您无法使用它删除特定索引 - 您必须为此使用 .splice()。总而言之,由于多种原因,您没有获得新的值数组。

    如果您只是想要一种简单的方法来随机化一个数组,而无需重新发明轮子并且知道随机性实际上很有效,您可以使用以下方法:

    function fisherYates ( myArray ) {
      var i = myArray.length;
      if ( i == 0 ) return false;
      while ( --i ) {
         var j = Math.floor( Math.random() * ( i + 1 ) );
         var tempi = myArray[i];
         var tempj = myArray[j];
         myArray[i] = tempj;
         myArray[j] = tempi;
       }
    }
    

    您可以在此处阅读有关 Fisher-Yates 方法的信息:http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

    您可以阅读为什么其他一些随机化方法无法正常工作,您可以在此处阅读:http://www.robweir.com/blog/2010/02/microsoft-random-browser-ballot.html

    所以,你可以替换这个:

           for (r=0;r<deck.length;r++){
                var randomindex = Math.floor(Math.random()*deck.length);
                new_deck.push(randomindex)
                deck.pop(randomindex)
                }
    
            document.write("deck = ")
    
            for (r =0; r<deck.length; r++){
                document.write(deck[r]);
                }
    
            document.write("</br>")
    
            document.write("new deck = ")
    
            for (r=0; r<new_deck.length; r++){
                document.write(new_deck[r]);
                }
    

    用这个:

            document.write("deck = ")
    
            for (r =0; r<deck.length; r++){
                document.write(deck[r]);
                }
    
            document.write("</br>")
    
            document.write("shuffled deck = ")
    
            // shuffle the deck and then output it
            fisherYates(deck);
    
            for (r=0; r<deck.length; r++){
                document.write(deck[r]);
                }
    

    【讨论】:

    • 非常感谢!工作完美。现在它可以工作了,我将不得不研究 Fisher Yates 函数并完全理解它,并了解所有数组方法之间的差异。我认为现在创建这款二十一点游戏可能需要比我想象的更长的时间,但无论如何我都会继续进行
    • 一个问题:'while (--i)' 是什么意思?
    • @DennisCallanan - while (--i) 表示递减i,如果结果为真(例如非零),则继续使用while 循环。如果递减后i的值为零,则停止while循环。
    【解决方案3】:

    您需要为此更改随机播放:

    while(deck.length > 0 ){ //for loop won't work
        var randomindex = Math.floor(Math.random()*deck.length);
        new_deck.push(deck[randomindex]);//Move onto new stack
        deck.splice(randomindex,1); //Take from old.
    }
    

    这就是 for 循环不起作用的原因: 说deck.length = 4

    for 循环的开始:r = 0

    一个项目被压入新堆栈并弹出:deck.length = 3

    r 递增 r = 1

    r 小于 deck.length,继续

    一个项目被压入新堆栈并弹出:deck.length = 2

    r 递增r = 2

    r 不再小于deck.length,循环已完成,但只有一半的元素被转移!

    【讨论】:

    • pop 不带参数。
    • @JoeFrambach 没错,固定
    • 有趣的是,自从我在公共汽车上时,我在手机上输入的内容与您相同。其他人纠正了我,我无法让“编辑”按钮工作,所以我把它删除了。投赞成票。
    • @JoeFrambach +1 为这个悲伤的故事。呵呵:P
    【解决方案4】:

    另一种超级简单的数组排序技术:

     deck.sort(function() { return Math.random()-0.5})
    

    【讨论】:

    • 我有点担心——虽然它看起来很棒,但它有可能(取决于所使用的排序,我认为)它永远不会返回? JavaScript 可能使用了一种不适用的类型,因为它们通常是最快的。
    • 传递给 sort 的函数应该为任何两个值返回一致的结果,而不是随机结果。这可能很麻烦。
    • 有趣的是,那篇文章中的建议是我在回答中使用的 Fisher Yates shuffle。
    【解决方案5】:

    你得到的是随机值,而不是牌组中的随机索引

    for (r=0;r<deck.length;r++){
        var randomindex = Math.floor(Math.random()*deck.length);
        new_deck.push(deck[randomindex]);
    }
    

    【讨论】:

    • 这会导致新牌组出现重复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    • 2019-02-07
    • 1970-01-01
    相关资源
    最近更新 更多