我在javascript中构建一个小模块,就像一包卡片一样。我的第一种方法很有效,但很简单,所以我想创建一些模拟真实世界卡改组背后的想法的随机方法。
在其他一些有用的功能中,我创建了riffle,overhand和cut功能,所有这些功能似乎都在那里工作,但是当按顺序重复调用它们时,返回的包装数量是不一致的,一次又一次地运行它它似乎是某种竞争条件,但似乎无法理解如何避免它。
相关的私人方法是:
riffle : function riffle() {
var top = Pack.slice(0, 26);
var bottom = Pack.slice(26, 52);
Pack = [];
console.log('top is '+top.length+" and bottom is "+bottom.length);
var hand = 'right';
var result = [];
var i = 52;
while (i > 0) {
var drop = Math.floor(Math.random()*3)+1;
var cards;
if (hand === 'right' ) {
if (drop >= top.length) {
cards = top;
} else {
cards = top.splice(0, drop);
}
hand = 'left';
} else {
if (drop >= bottom.length) {
cards = bottom;
} else {
cards = bottom.splice(0, drop);
}
hand = 'right';
}
result = result.concat(cards);
i -= drop;
}
Pack = result;
console.log(Pack.length+" after riffle");
return this;
},
cut : function cut(fn) {
var top = Pack.slice(0, 26);
var bottom = Pack.slice(26, 52);
Pack = [];
console.log(top);
Pack = bottom.concat(top);
console.log(Pack.length+" after cut");
if (fn && typeof(fn) === 'function') { fn(); }
return this;
}
后来我有一个名为shuffle的特权方法,它调用它们:
shuffle : function shuffle(cb) {
State.cardsOut = [];
Internal.generatePack().cut().riffle().riffle()
.riffle().riffle().riffle();
if (cb && typeof(cb) === 'function') { cb(); }
}
注意:我从一个生成函数开始,该函数创建一个对象的arrray,代表一整套52张牌。当我在洗牌和削减后的不同时间登录包时,我得到的结果各不相同,我似乎无法弄清楚原因。
你可以看到我在这里工作的公里
https://gist.github.com/Pushplaybang/66bc7a1fa5d84eee2236
任何帮助都会很棒。
答案 0 :(得分:1)
drop
变量存储了你应该从左手或右手翻转的牌数。但是,有两种情况:
if (drop >= top.length) {
cards = top;
}
和
if (drop >= bottom.length) {
cards = bottom;
}
其中drop
可能大于包裹中一半剩余卡片的数量,因此从i
中减去的卡数将比您实际上减去的数量更多。您可以通过以下方式解决此问题:
if (drop >= top.length) {
drop = top.length;
cards = top;
top = [];
}
和
if (drop >= bottom.length) {
drop = top.length;
cards = bottom;
bottom = [];
}
(您需要清空阵列,否则最终可能会添加两次相同的卡片。)
其他问题
26
和52
中有魔术数字)这些可以是在类中定义的常量并给出适当的名称(即PACK_SIZE = 52
),这意味着如果你创建一个代表不同数量卡片的子类,它仍可以使用。hand
有两个可能的值,可以表示为布尔值,但是你可以为它分配字符串(同样可以使用常量LEFT_HAND = true, RIGHT_HAND = !LEFT_HAND
)。Pack
似乎是一个全局变量 - 我原以为它应该是该类的成员。riffle : function riffle() {
只能是一个匿名函数riffle : function() {
。这样的事情:
PACK_SIZE: 52,
riffle : function() {
var index_of_cards_riffled_from_top = 0;
var index_of_cards_riffled_from_bottom = this.PACK_SIZE / 2;
var riffled_cards = [];
while ( index_of_cards_riffled_from_top < this.PACK_SIZE / 2
|| index_of_cards_riffled_from_bottom < this.PACK_SIZE ) {
var num_cards_to_riffle_top = Math.min( this.PACK_SIZE / 2 - index_of_cards_riffled_from_top, Math.floor( Math.random() * 3 ) + 1 );
var num_cards_to_riffle_bottom = Math.min( this.PACK_SIZE - index_of_cards_riffled_from_bottom, Math.floor( Math.random() * 3 ) + 1 );
while ( num_cards_to_riffle_top > 0 ) {
riffled_cards.push( this.Pack[ index_of_cards_riffled_from_top++ ] );
num_cards_to_riffle_top--;
}
while ( num_cards_to_riffle_bottom > 0 ) {
riffled_cards.push( this.Pack[ index_of_cards_riffled_from_bottom++ ] );
num_cards_to_riffle_bottom--;
}
}
this.Pack = riffled_cards;
}
答案 1 :(得分:0)
虽然@MTO的答案确实解决了我的问题,但我想了解一下我如何选择开始重构这个功能。
riffle : function riffle() {
var cutPos = Math.floor(Math.random()*rv)+( (cardCount-rv) / 2 );
var splitPack = {
left : Pack.splice(0, cutPos),
right : Pack.splice(0, Pack.length)
};
var hand = 'right',result = [], i = 52, cards;
while(i > 0) {
drop = Math.floor(Math.random()*3)+1;
if (drop >= splitPack[ hand ].length) {
drop = splitPack[ hand ].length;
}
cards = splitPack[ hand ].splice(0, drop);
hand = (hand === 'left') ? 'right' : 'left';
result = result.concat(cards);
cards = [];
i -= drop;
}
Pack = result;
console.log(Pack.length+" after riffle");
return this;
},
一些事情: