0

I'm working on a simple Tic Tac Toe game in Javascript. Right now, to check for a winner, I have a function that first gets whose turn it is and then finds wherever they have an X or an O on the board. The spaces they have are numbered (1-8) and added to an array. So far so good.

Now I'm trying to compare another array, the array with all of the winning combinations:

var winningCombinations = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]];

with a test array, that should come up a winner as it contains 2, 5, and 8.

Source of my test:

<script>

    var test = [2,4,5,8]
    var winningCombinations = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]];

    for(var x=0; x<winningCombinations.length; x++) {

        if (winningCombinations[x].indexOf(test) > -1) {
            alert("Win!");
        } else {
            alert ("No win.");
        }

    }

</script>

I think right now it's only testing for [2,4,5,8] as an entire value--not for an instance of the individual numbers inside. This is where I'm stumped. How can I check to see if the test array, in any order, matches any of the winningCombinations values?

Tim Aych
  • 1,365
  • 4
  • 16
  • 34
  • 2
    This might help: http://stackoverflow.com/questions/1885557/simplest-code-for-array-intersection-in-javascript – ediblecode Oct 08 '13 at 14:31

4 Answers4

2

Try this:

var test = [2,4,5,8]
var winningCombinations = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]];
var combLength = 0;
for (var i in winningCombinations) {
    combLength = winningCombinations.length;
    for (var j in winningCombinations[i]) {
        if (-1 == test.indexOf(winningCombinations[i][j])) {
            break;
        }
    }

    if (combLength - 1 == j) {
        alert("Win!");
    }
}

in the first if statement we're checking if the currently looped item in currently looped array (seems confusing, I know) is present in the test array. If not we already know that test array is not a winning array.

Moreover, I suggest wrapping all this stuff in a function like this:

function isWinner(playerNumbers, winningCombinations) {
    var combLength = 0;
    for (var i in winningCombinations) {
        combLength = winningCombinations.length;
        for (var j in winningCombinations[i]) {
            if (-1 == playerNumbers.indexOf(winningCombinations[i][j]) {
                break;
            }
        }

        if (combLength - 1 == j) {
            return true;
        }
    }

    return false;
}

var test = [2,4,5,8]
var winningCombinations = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]];

if (isWinner(test, winningCombinations)) {
    alert("Win!");
} else {
    alert ("No win.");
}
Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
matewka
  • 9,912
  • 2
  • 32
  • 43
1

You really arent checking equality, you're checking if one array is a subset of another. For this, I would recommend changing test to an object in the form {2: 1, 4: 1, 5: 1, 8: 1}. The ones are in there just to evaluate to true, they don't really matter. The important thing is the key.

function checkSubset(a, b) {
    //returns true if EVERY element in the array causes the next function to return true
    return a.every(function(e) {
        return !!b[e]; //returns true if b contains e
    });
}

Then call checkSubset(winningCombinations[x], test). That being said, there are much better ways to evaluate the state of a tic tac toe board.

mako-taco
  • 722
  • 5
  • 10
1

The naive method would just check every combination and make sure test contains every element of one of the combinations:

var winner = false;

for (var i = 0; i < winningCombinations.length && !winner; i++) {
    var matches = true;

    for(var j = 0; j < winningCombinations[i].length && matches; j++)
        if(test.indexOf(winningCombinations[i][j]) == -1)
            matches = false;

    if(matches)
        winner = true;
}

If you encapsulate these in functions and return matches and winner you can get rid of the ugly loop conditions:

function matchesCombination(test, combination)
{
    for(var i = 0; i < combination.length; i++)
        if(text.indexOf(combination[i]) == -1)
            return false;

    return true;
}

function isWinner(test, combinations)
{
    for(var i = 0; i < combinations.length; i++)
        if(matchesCombination(test, combinations[i])
            return true;

    return false;
}
lc.
  • 113,939
  • 20
  • 158
  • 187
0

It may not be the best answer, but off the top of my head you could loop through the values in the winning conditions and do an if statement that requires all 3 indexOfs to be != -1.

i.e. for each array in winning combinations, loop through each value in the array and do test.indexOf(value) and check to see that it's not -1. If all 3 values come back as not equal to -1 then you have a win condition.

AlexF
  • 124
  • 1
  • 3