我正在编写一个将数组中的项目混洗的函数:
this.shuffle = function () {
...
首先,我得到数组的两半并设置第三个空数组:
this.leftHalf = this.cards.slice(0, this.size() / 2);
this.rightHalf = this.cards.slice(this.size() / 2);
this.result = [];
接下来,我将每一半的一张卡放入结果数组中:
for (var i = ...) {
this.result.unshift(this.leftHalf[i]);
this.result.unshift(this.rightHalf[i]);
}
最后,我将结果数组分配给原始数组并删除“临时”变量:
this.cards = this.result;
delete this.leftHalf;
delete this.rightHalf;
delete this.result;
}
我的问题:这是解决此问题的明智方法,还是有更好的方法不涉及设置临时变量?我考虑使用私有变量(但不确定它是否会更好地表现性能),如下所示:
var leftHalf, rightHalf, result;
this.shuffle = function () {
leftHalf = ...
只是好奇是否有任何明显的错误,或者在这些情况下是否有最佳做法。
答案 0 :(得分:1)
有许多好的算法可以随机化一组元素的顺序。一个简单的方法是将最后一个元素与列表中的随机元素交换。然后将n-1个元素与前n-1个元素中的随机元素交换(假设您的列表为n long),然后将n-2个元素与前n-2个元素中的随机元素等交换(注意)您可以将元素与自身交换。)
这个天真的实现将使用一个临时变量,但有一些技巧可以使它完全到位。这几乎是不必要的,通常会降低可读性。
答案 1 :(得分:1)
你可以在没有任何私有变量和循环的情况下完成它,尽管我怀疑会有很多性能差异。假设你想要一个左手洗牌,那么顶部的卡片最顶端,中间的卡片朝上,卡片的长度为偶数N ...
for(var i=...) {
if(i%2 == 1)
newdeck[i] = oldeck[N/2+(i-1)/2];
if(i%2 == 0)
newdeck[i] = oldeck[i/2];
}
这将像你原来的算法一样完成所谓的完美随机播放,但正如人们所说的那样,这是不可随意的,因为它是可预测的。有一篇着名的报纸称,要从有序的那个到达一个随机的看似甲板,你需要运行7次完美的洗牌。您还可以使用this article中的右侧和左侧随机播放控制卡片中的卡片。
答案 2 :(得分:1)
当我们说Shuffle一词时,它必须是随机的。下面是我创建的片段,用于演示以随机方式重新排列arral值。
var shuffle = function() {
var _deck = [ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M" ],
_shuffle = [],
_slice;
do {
// return's a random index
_splice = Math.floor( Math.random() * _deck.length );
// store the random value in new array
_shuffle.push( _deck[ _splice ] );
// splice the random value
_deck.splice( _splice, 1 );
} while ( _deck.length );
};
正如@hackartist所提到的,你可以阅读这个http://blogs.discovermagazine.com/crux/2012/07/16/surprising-connection-between-card-shuffling-higgs-boson/并进一步扩展到shuffle方法以自行执行X次