在Javascript(Node.js)中分析此数组的最有效方法是什么?
首先,我想指出这是服务器端Node.js代码,而不是普通的客户端Javascript。我不想使用jQuery,但使用任何原生Node.js方法(如果您知道有任何潜在的有用方法)都可以 这是纸牌游戏中机器人玩家的代码。机器人有一手卡片,其结构如下:在Javascript(Node.js)中分析此数组的最有效方法是什么?,javascript,node.js,algorithm,Javascript,Node.js,Algorithm,首先,我想指出这是服务器端Node.js代码,而不是普通的客户端Javascript。我不想使用jQuery,但使用任何原生Node.js方法(如果您知道有任何潜在的有用方法)都可以 这是纸牌游戏中机器人玩家的代码。机器人有一手卡片,其结构如下: [ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ] 因此,这8张卡中的每一张都以value+suit字符串的形式给出。这是无法更改的,因为整个应用程序都使用这种结构 现在,机器人必须分析这只手来搜索
[ '9H', '10S', 'KD', '9D', '7D', 'QC', 'JC', '7C' ]
因此,这8张卡中的每一张都以value+suit
字符串的形式给出。这是无法更改的,因为整个应用程序都使用这种结构
现在,机器人必须分析这只手来搜索特定的卡片组合。例如,它应该找到任何“第三个国王”(国王至少有两张相同花色的小牌)、“第二个十”(王后至少有一张相同花色的小牌)或“第三个王后”
在上面的例子中,它应该是:第三个钻石王和第三个梅花皇后
我正在考虑实现一个搜索算法来查找这些组合,但我担心这会非常低效。我的第一个想法是遍历数组,找到所有的国王、王后和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...
var kingsuits=[];
对于(var i=0;i而言,快速解决方案是首先将手快速分类为套装/号码顺序,即:
[ '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
当您找到“最佳”序列时,搜索很容易中止。使用二维哈希映射或数组或其他类型的直接访问数据结构,在其中存储特定类型的(布尔)卡或(整数)卡的数量。例如:
[ '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
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 })
这应该允许在该结构中进行非常快速和简单的搜索-通过循环,您可以快速识别有多个9,并且俱乐部女王旁边有2张俱乐部卡
选择黑桃的对象或数组,以及哪个(适合或值)是第一维度或第二维度并不重要。对于值,您需要使用数组来获得定义的顺序,即使映射(例如A->0,K->1,…2->12)是非传统的。…下面是如何构建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
})
因为对于你所搜索的内容有很多未知数,可以简单地对卡片进行排序就足够了,但是你可以考虑将卡放置在对象(哈希表)中以快速查找条件。
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 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);
如果需要更复杂的卡片组合,我看不出这将如何工作,因为这些只是示例?例如KD、QC、JD、10S、9D将是最好的手牌?手牌已经按花色/号码排序,只是在我的示例中它是按递减顺序排序的…@MaunoV。按花色/号码排序很容易识别出适合大手(例如,他自定义的手和冲水),然后再次按数字/适合进行排序,以处理大手的数量(对、直等)。考虑到Node.js的异步性质,有:-)这是可行的吗?绝对可行。您提到的异步性仅与冗长的“外部”过程(例如,文件I/O、数据库访问、网络通信等)相关。“最有效”的方法可能涉及一个非常大的预计算值表,类似于您在最快的扑克手签中看到的值。一个非常合理的解决方案是按套装/号码对卡片进行排序,然后按照下面描述的答案之一顺序扫描它们。
var rules = [
matchCardFn("9H"),
matchCardFn("7D")
];
function matchCardFn(matchCard) {
return function(hand) {
if (hand.indexOf(matchCard) !== -1) {
return {
rule: "Has a " + matchCard,
cards: [ matchCard ]
};
}
};
}