25

I am new to JavaScript, I have been learning and practicing for about 3 months and hope I can get some help on this topic. I'm making a poker game and what I'm trying to do is determine whether i have a pair, two pairs, three of a kind, four of a kind or a full house.

For instance, in [1, 2, 3, 4, 4, 4, 3], 1 appears one time, 4 appears three times, and so on.

How could I possibly ask my computer to tell me how many times an array element appears?

Solved, here's the final product.

    <script type="text/javascript">
    var deck = [];
    var cards = [];
    var convertedcards = [];
    var kinds = [];
    var phase = 1;
    var displaycard = [];
    var options = 0;
    var endgame = false;

    // Fill Deck //
    for(i = 0; i < 52; i++){
        deck[deck.length] = i;          
    }

    // Distribute Cards //
    for(i = 0; i < 7; i++){
        cards[cards.length] = Number(Math.floor(Math.random() * 52));
        if(deck.indexOf(cards[cards.length - 1]) === -1){
            cards.splice(cards.length - 1, cards.length);
            i = i - 1;
        }else{
            deck[cards[cards.length - 1]] = "|";
        }
    }

    // Convert Cards //
    for(i = 0; i < 7; i++){
        convertedcards[i] = (cards[i] % 13) + 1;
    }


    // Cards Kind //
    for(i = 0; i < 7; i++){
        if(cards[i] < 13){
            kinds[kinds.length] = "H";
        }else if(cards[i] < 27 && cards[i] > 12){
            kinds[kinds.length] = "C";
        }else if(cards[i] < 40 && cards[i] > 26){
            kinds[kinds.length] = "D";
        }else{
            kinds[kinds.length] = "S";
        }
    }

    // Card Display //
    for(i = 0; i < 7; i++){
        displaycard[i] = convertedcards[i] + kinds[i];
    }

    // Hand Strenght //
    var handstrenght = function(){
        var usedcards = [];
        var count = 0;
        var pairs = [];
        for(i = 0, a = 1; i < 7; a++){
            if(convertedcards[i] === convertedcards[a] && a < 7 && usedcards[i] != "|"){
                pairs[pairs.length] = convertedcards[i];
                usedcards[a] = "|";
            }else if(a > 6){
                i = i + 1;
                a = i;
            }
        }

        // Flush >.< //
        var flush = false;
        for(i = 0, a = 1; i < 7; i++, a++){
            if(kinds[i] === kinds[a] && kinds[i] != undefined){
                count++;
                if(a >= 6 && count >= 5){
                    flush = true;
                    count = 0;
                }else if(a >= 6 && count < 5){
                    count = 0;
                }
            }
        }
        // Straight >.< //
        var straight = false;
        convertedcards = convertedcards.sort(function(a,b){return a-b});
        if(convertedcards[2] > 10 && convertedcards[3] > 10 && convertedcards[4] > 10){
            convertedcards[0] = 14;
            convertedcards = convertedcards.sort(function(a,b){return a-b});
        }
        alert(convertedcards);
        if(convertedcards[0] + 1 === convertedcards[1] && convertedcards[1] + 1 === convertedcards[2] && convertedcards[2] + 1 === convertedcards[3] && convertedcards[3] + 1 === convertedcards[4]){
            straight = true;
        }else if(convertedcards[1] + 1 === convertedcards[2] && convertedcards[2] + 1 === convertedcards[3] && convertedcards[3] + 1 === convertedcards[4] && convertedcards[4] + 1 === convertedcards[5]){
            straight = true;
        }else if(convertedcards[2] + 1 === convertedcards[3] && convertedcards[3] + 1 === convertedcards[4] && convertedcards[4] + 1 === convertedcards[5] && convertedcards[5] + 1 === convertedcards[6]){
            straight = true;
        }
        // Royal Flush, Straight Flush, Flush, Straight >.< //
        var royalflush = false;
        if(straight === true && flush === true && convertedcards[6] === 14){
            royalflush = true;
            alert("You have a Royal Flush");
        }
        else if(straight === true && flush === true && royalflush === false){
            alert("You have a straight flush");
        }else if(straight === true && flush === false){
            alert("You have a straight");
        }else if(straight === false && flush === true){
            alert("You have a flush");
        }
        // Full House >.< //
        if(pairs[0] === pairs[1] && pairs[1] != pairs[2] && pairs.length >= 3){
            fullhouse = true;
            alert("You have a fullhouse");
        }else if(pairs[0] != pairs[1] && pairs[1] === pairs[2] && pairs.length >= 3){
            fullhouse = true;
            alert("You have a fullhouse");
        }else if(pairs[0] != pairs[1] && pairs[1] != pairs[2] && pairs[2] === pairs[3] && pairs.length >= 3){
            fullhouse = true;
            alert("You have a fullhouse");
        }
        // Four of a kind >.< //
        else if(pairs[0] === pairs[1] && pairs[1] === pairs[2] && pairs.length > 0){
            alert("You have four of a kind");
        }
        // Three of a kind >.< //
        else if(pairs[0] === pairs[1] && flush === false && straight === false && pairs.length === 2){
            alert("You have three of a kind");
        }
        // Double Pair >.< //
        else if(pairs[0] != pairs[1] && flush === false && straight === false && pairs.length > 1){
            alert("You have a double pair");
        }
        // Pair >.< //
        else if(pairs.length === 1 && flush === false && straight === false && pairs.length === 1 ){
            alert("You have a pair");
        }
        alert(pairs);
    };
    while(endgame === false){
        if(phase === 1){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }else if(phase === 2){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + displaycard[2] + " " + displaycard[3] + " " + displaycard[4] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }else if(phase === 3){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + displaycard[2] + " " + displaycard[3] + " " + displaycard[4] + " " + displaycard[5] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }else if(phase === 4){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + displaycard[2] + " " + displaycard[3] + " " + displaycard[4] + " " + displaycard[5] + " " + displaycard[6] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }
        switch(options){
            case 1:
                    if(phase === 5){
                        handstrenght();
                        endgame = true;
                    }else{
                        phase++;
                    }
                    break;
            case 2:
                    endgame = true;
                    break;
            default:
                    endgame = true;
                    break;
        }
    }


</script>
Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
Frederic Daniel
  • 297
  • 2
  • 4
  • 8

7 Answers7

38
  • Keep a variable for the total count
  • Loop through the array and check if current value is the same as the one you're looking for, if it is, increment the total count by one
  • After the loop, total count contains the number of times the number you were looking for is in the array

Show your code and we can help you figure out where it went wrong

Here's a simple implementation (since you don't have the code that didn't work)

var list = [2, 1, 4, 2, 1, 1, 4, 5];  

function countInArray(array, what) {
    var count = 0;
    for (var i = 0; i < array.length; i++) {
        if (array[i] === what) {
            count++;
        }
    }
    return count;
}

countInArray(list, 2); // returns 2
countInArray(list, 1); // returns 3

countInArray could also have been implemented as

function countInArray(array, what) {
    return array.filter(item => item == what).length;
}

More elegant, but maybe not as performant since it has to create a new array.

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
14

With filter and length it seems simple but there is a big waste of memory.

If you want to use nice array methods, the appropriate one is reduce:

function countInArray(array, value) {
  return array.reduce((n, x) => n + (x === value), 0);
}
console.log(countInArray([1,2,3,4,4,4,3], 4)); // 3
Oriol
  • 274,082
  • 63
  • 437
  • 513
4

Well..

var a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
  if (typeof acc[curr] == 'undefined') {
    acc[curr] = 1;
  } else {
    acc[curr] += 1;
  }

  return acc;
}, {});

// a == {2: 5, 4: 1, 5: 3, 9: 1}

from here: Counting the occurrences of JavaScript array elements

Or you can find other solutions there, too..

Community
  • 1
  • 1
Filkor
  • 642
  • 6
  • 18
  • Nice sophisticated answer, but I think this may be a bit over the OP's head. At least it doesn't give the answer away, since it will still take a lot of learning for the OP to understand what is happening. On the other hand, they may use your method without ever understanding it, which would defeat the point of SO. – Ruan Mendes Nov 15 '12 at 00:01
2

When targeting recent enough browsers, you can use filter(). (The MDN page also provides a polyfill for the function.)

var items = [1, 2, 3, 4, 4, 4, 3];
var fours = items.filter(function(it) {return it === 4;});
var result = fours.length;

You can even abstract over the filtering function as this:

// Creates a new function that returns true if the parameter passed to it is 
// equal to `x`
function equal_func(x) {
    return function(it) {
        return it === x;
    }
}
//...
var result = items.filter(equal_func(4)).length;
millimoose
  • 39,073
  • 9
  • 82
  • 134
  • It's supported since IE9 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Browser_compatibility – Ruan Mendes Mar 16 '16 at 20:23
  • @JuanMendes - Thanks, I made the phrasing of the answer more accurate. – millimoose Mar 17 '16 at 03:07
  • 1
    This wastes too much memory. – Oriol Jan 30 '17 at 17:23
  • 1
    @Oriol It uses O(N) memory, worst-case, for presumably tiny values of N, the memory overhead is completely irrelevant in a practical context. If you can't spare that much memory, you probably can't store the original array. If you need to process vast dataset and are looking to SO answers to school assignment questions for hits you've got worse problems. – millimoose Jan 30 '17 at 18:29
  • 1
    A reduce-based version would be more efficient, but reduces aren't too readable at what I guessed the OP's skill level to be, and a loop version is already the accepted answer, so I'm not going to edit a 4-year old answer to make it substantially different than what was voted for unless it's patently wrong. – millimoose Jan 30 '17 at 18:34
1

Here's an implementation of Juan's answer:

function count( list, x ) {

    for ( var l = list.length, c = 0; l--; ) {

        if ( list[ l ] === x ) {

            c++;
        }
    }

    return c;

}

Even shorter:

function count( list, x ) {

    for ( var l = list.length, c = 0; l--; list[ l ] === x && c++ );

    return c;

}
David G
  • 94,763
  • 41
  • 167
  • 253
  • Why trying to make it short? Make it simple, no need for optimizations. Also, if you make it a method, you have to pass the array in, please don't rely on a global. – Ruan Mendes Nov 15 '12 at 00:39
  • @JuanMendes I'm not passing an array in, just the value. `list` is the array the OP declares in his question... :) – David G Nov 15 '12 at 00:41
  • My point is that you should be passing it in. `count` should take the array to count as an argument instead of using a global. Otherwise it makes no sense to make it a function since it can only work with that global you setup. See my answer. – Ruan Mendes Nov 15 '12 at 00:42
1

Here's an implementation that uses the Array Object Prototype and has an extra level of functionality that returns the length if no search-item is supplied:

Array.prototype.count = function(lit = false) {
    if ( !lit ) { return this.length}
    else {
        var count = 0;
        for ( var i=0; i < this.length; i++ ) {
            if ( lit == this[i] ){
                count++
            }
        }
        return count;
    }
}

This has an extremely simple useage, and is as follows:

var count = [1,2,3,4,4].count(4);  // Returns 2
var count = [1,2,3,4,4].count();   // Without first parameter returns 5
Dendromaniac
  • 378
  • 1
  • 14
  • 2
    Avoid messing with the prototype of native objects, it may be incompatible when an `Array.prototype.count` method is standardized. – Ruan Mendes Mar 16 '16 at 20:20
  • This returns 3 for `[1,2,3].count(0)` I would get rid of the case where you're just returning length – Ruan Mendes Sep 11 '16 at 20:45
0

Avoid messing with the prototype of native objects, it may be incompatible when an Array.prototype.count method is standardized.