首先,我想指出这是服务器端的Node.js代码,而不是普通的客户端Javascript。我不想使用jQuery,但使用任何本机Node.js方法(如果你知道有任何潜在有用的方法)都可以。
这是纸牌游戏中的机器人玩家的代码。机器人有一手牌,结构如下:
[ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ]
所以8张牌中的每张牌都是value+suit
字符串。这是无法更改的,因为整个应用程序都适用于此结构。
现在,机器人必须分析此手以搜索某些卡片组合。例如,它应该找到任何“第三位国王”(国王至少有2张相同花色的小牌),“第二位数”(女王至少有1张相同花色的小牌)或“第三位皇后”。
在上面的例子中,它应该提出:第三王钻石和第三王牌俱乐部。
我正在寻找实现搜索算法来找到这些组合,但我担心这会非常低效。我的第一个想法是遍历数组以找到所有的国王,王后和10并将这些数据保存在某处,然后再次迭代它以计算我们拥有的同一套牌的其他牌数。例如,对于国王:
var kingsuits = [];
for(var i=0;i<8;i++){
if(hand[i].substr(0,1) == "K")
kingsuits.push(hand[i].substr(-1));
}
//now kingsuits has the suits of all kings, and we can go through our hand again and check how many cards we have in each of these suits...
我的问题是,有没有更有效的方法来实现这一目标?问题是,还有很多其他组合也应该被寻找,而不仅仅是我上面举例说明的那些组合。
另外 - 也许更重要的是 - 如果我们找到“第三位国王”,我们根本不需要寻找“第三位女王”或“第二位女王”。这些组合有一个明确的层次结构,所以如果我们找到第一个组合,我们根本不需要关心其他组合。
答案 0 :(得分:3)
使用二维hashmap或数组或其他类型的直接访问数据结构,在该数据结构中存储特定类型的(布尔)或多少(int)卡。例如:
[ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ]
=>
| A K Q J 10 9 8 7 6 5 4 3 2
--+--------------------------------------
C | 0 0 1 1 0 0 0 1 0 0 0 0 0
D | 0 1 0 0 0 1 0 0 0 0 0 0 0
H | 0 0 0 0 0 1 0 0 0 0 0 0 0
S | 0 0 0 0 1 0 0 0 0 0 0 0 0
这应该允许在该结构中进行非常快速和简单的搜索 - 通过循环,您可以快速识别出有多个9,并且俱乐部女王旁边有2张俱乐部卡。
是否为黑桃选择一个对象或一个数组并且哪些(套装或值)是第一维或第二维并不重要。对于值,您将需要使用数组来获取定义的顺序,即使映射(例如A-> 0,K-> 1,... 2-> 12)是非常规的。
答案 1 :(得分:2)
快速解决方案是先将手快速分类为套装/数字顺序,即:
[ '9H', '10S', '7D', '9D', 'KD', '7C', 'JC', 'QC' ]
然后在列表中进行单次传递,跟踪到目前为止发现的单一套装中最长的卡片序列,例如:
var lastCard
var currentSequence
var bestSequence
for card in cards:
if suitOf(card) = suitOf(lastCard) and numberOf(card) = numberOf(lastCard) + 1:
append to currentSequence
else:
if currentSequence better than bestSequence:
bestSequence = currentSequence
clear currentSequence
当您找到“最佳”序列时,可以轻松中止搜索。
答案 2 :(得分:2)
由于关于您正在搜索的内容存在很多未知数,因此可能只需对卡进行排序即可,但您可以考虑将卡排列在对象(哈希表)中以快速查找条件。
function value(s) {
return s.substr(0, s.length - 1)
}
function suit(s) {
return s.substr(-1)
}
function search(arr) {
var suits = {
S: {},
C: {},
D: {},
H: {}
}
var count = {
S: 0,
C: 0,
D: 0,
H: 0
}
for (var i = 0; i < arr.length; i++) {
var card = arr[i]
var s = suit(card)
var v = value(card)
suits[s][v] = true
count[s]++
}
// hunt in the structure here
}
这将允许您获取第三个皇后,例如:
var thirdQueens = ["S", "C", "D", "H"].map(function (s) {
var hash = suits[s]
if (hash.Q && count[s] - (hash.K ? 1 : 0) >= 3) {
return "Q" + s
}
}).filter(function identity(x) { return x })
答案 3 :(得分:1)
...以下是你的hashmap的构造方式......我猜其他任何东西都已在我面前解释过了。
var input = [ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ]
var M = [ [], [], [], [] ]
var values = {
2: 0,
3: 1,
4: 2,
5: 3,
6: 4,
7: 5,
8: 6,
9: 7,
10: 8,
J: 9,
Q: 10,
K: 11,
A: 12,
}
var suits = {
C: 0,
D: 1,
H: 2,
S: 3,
}
input.forEach(function(x) {
M[suits[x.slice(-1)]][values[x.slice(0, -1)]] = 1
})
答案 4 :(得分:1)
要回答问题的“更重要”部分,您可以按优先顺序创建一系列规则,为每个规则创建一个函数,然后迭代它。这是一个非常简单的例子:
var hand = [ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ];
var rules = [
function(hand) {
if (hand.indexOf('9H') !== -1) {
return {
rule: "Has a 9H",
cards: [ "9H" ]
};
}
},
function(hand) {
if (hand.indexOf('7D') !== -1) {
return {
rule: "Has a 7D",
cards: [ "7D" ]
};
}
}
];
var match = false;
for (var i = 0, len = rules.length; i < len && !match; ++i) {
match = rules[i](hand);
}
console.log(match);
编写完成后,您可以查看规则并检查逻辑的重复,并开始重写规则:
var rules = [
matchCardFn("9H"),
matchCardFn("7D")
];
function matchCardFn(matchCard) {
return function(hand) {
if (hand.indexOf(matchCard) !== -1) {
return {
rule: "Has a " + matchCard,
cards: [ matchCard ]
};
}
};
}