在Javascript(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字符串的形式给出。这是无法更改的,因为整个应用程序都使用这种结构 现在,机器人必须分析这只手来搜索

首先,我想指出这是服务器端Node.js代码,而不是普通的客户端Javascript。我不想使用jQuery,但使用任何原生Node.js方法(如果您知道有任何潜在的有用方法)都可以

这是纸牌游戏中机器人玩家的代码。机器人有一手卡片,其结构如下:

[ '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 ]
            };
        }
    };
}