我试图产生一个桥牌交易,四个玩家,每个获得13张(随机)牌。
我想我会先宣布一些变量,比如西装,包含套装的套牌,以及玩家手:
var deal = function() {
var spades = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];
var hearts = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];
var diamonds = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];
var clubs = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];
var deck = [spades, hearts, diamonds, clubs];
//Next to do: get 13 random cards dealt to each player
var northHand = [ [], [], [], [] ];
var eastHand = [ [], [], [], [] ];
var southHand = [ [], [], [], [] ];
var westHand = [ [], [], [], [] ];
}
然后我遇到了基于fisher-yates算法的这种随机函数:
function shuffle(array) {
var m = array.length, t, i;
// While there remain elements to shuffle…
while (m) {
// Pick a remaining element…
i = Math.floor(Math.random() * m--);
// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
问题是我的编程(和/或逻辑)技能太差,无法找到我如何在我的场景中应用这个算法,处理多个数组。
这是我的问题的良好开端,还是我应该研究一下更好的方法?
答案 0 :(得分:1)
我认为你的问题是你正在构建你的套牌的方式。这对于顺序的逻辑访问来说很好。你想要西装混合以及西装卡。使用包含字符串2H
,QD
等的简单对象{'Suit': 'Hearts', 'Value': 'Q'}
一旦你有一个数组,使用你提供的代码,shuffle实现变得微不足道
一旦你洗牌,你可以给1号牌0-12号,2月13-25号等,或者你可以“正确”处理它们,这样玩家1可以从0,4,6,12等位置获得牌。 ..
不要命名4个数组N / E / S / W,而是使用2d数组,以便轻松访问它。
然后在卡片上循环......
for(var i=0;i<52;i++) {
Pos = i % 4;
Hands[Pos].push(Deck[i]);
}
假设你的手被定义为
var Hands = [ [], [], [], [] ];
你应该好好去(未经测试)
答案 1 :(得分:1)
每张卡的适用性和价值都很重要,因此您需要将它们保持在一起。卡片可能更好地表示为{suit: 'spades', value: 'A'}
。
我会沿着这些线构建牌组:
var deck = [];
var suits = ['spade', 'heart', 'club', 'diamond'];
var values = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2'];
for (var sIdx = 0; sIdx < suits.length; sIdx++) {
for (var vIdx = 0; vIdx < values.length; vIdx++) {
deck.push({suit: suits[sIdx], value: values[vIdx]});
}
}
然后使用你的shuffle来洗牌,slice()
将它分成13只4手。
您概述的方法(每个套装都有一个单独的数组)可以完全奏效。但我觉得这是将数据表示映射到所表示事物的干净利落的情况之一,这使得您想要对数据执行的每个操作都更容易。
答案 2 :(得分:1)
首先,您需要一种方法来区分每张卡片。假设所有卡的编号从0到51如下:
在每件套装中,卡片的编号如下:
请注意,这些数字仅用于识别卡片。它们不代表任何卡的价值。因此,它们可用于所有纸牌游戏。鉴于一个数字,你可以找到它的诉讼和排名如下:
var suits = ["Hearts","Spades","Diamonds","Clubs"];
var ranks = ["Ace","2","3","4","5","6","7","8","9","10","Jack","Queen","King"];
function getSuite(card) {
return suits[Math.floor(card / 13)];
}
function getRank(card) {
return ranks[card % 13];
}
现在你的套牌只是一个从0到51的数字数组。因此你可以使用Fischer Yates来洗牌:
function deal() {
var deck = shuffle(range(0, 51));
var northHand = deck.slice(0, 13);
var eastHand = deck.slice(13, 26);
var southHand = deck.slice(26, 39);
var westHand = deck.slice(39, 52);
}
function range(from, to) {
if (from > to) return [];
else return [from].concat(range(from + 1, to));
}
就是这样。
答案 3 :(得分:0)
你不能在这里使用Fisher-Yates shuffle,因为你想在数组之间随机移动值。这应该做到并且仍然是随机的:
var hands = [northHand, eastHand, southHand, westHand];
var numberofcards = 4*13;
for (var i=0; i<4; i++) {
for (var j=0; j<13; j++) {
// draw card:
var card = Math.floor(Math.random() * numberofcards--);
// check which card it is:
for (var suit=4; suit-- && card > deck[suit].length; )
card -= deck[suit].length;
// remove from deck and assign to player
hands[i][suit].push(deck[suit].splice(card, 1)[0]);
}
}
然而,将单张卡片作为具有西装和价值的物品代表可能会更容易处理 - 然后您也可以在将牌组切成四个部分之前使用随机方法。