1

So I decided to build a little Tic-Tac-Toe game, I'm storing the X's and O's in an array and have a function to check the array to see if anyone has won.

Right now I'm just doing a big giant IF

if ((board[0] == valueToCheck && board[1] == valueToCheck && board[2] == valueToCheck) ||
    (board[3] == valueToCheck && board[4] == valueToCheck && board[5] == valueToCheck) ||
    (board[6] == valueToCheck && board[7] == valueToCheck && board[8] == valueToCheck) ||
    (board[0] == valueToCheck && board[3] == valueToCheck && board[6] == valueToCheck) ||
    (board[1] == valueToCheck && board[4] == valueToCheck && board[7] == valueToCheck) ||
    (board[2] == valueToCheck && board[5] == valueToCheck && board[8] == valueToCheck) ||
    (board[0] == valueToCheck && board[4] == valueToCheck && board[8] == valueToCheck) ||
    (board[2] == valueToCheck && board[4] == valueToCheck && board[6] == valueToCheck)) {

I'm just wondering if there's a more optimized way to do this as I'm about to build a computerized opponent and it should check to see if it's opponent is about to win, oh and I'm not using jQuery

3
  • This might give you an idea Commented Feb 1, 2014 at 1:33
  • 2
    When you say optimized, do you mean to run faster, or to use less code? Commented Feb 1, 2014 at 1:34
  • "Optimized" means fewer cpu cycles. "Obfuscated" is less code. :) Commented Feb 1, 2014 at 2:16

4 Answers 4

1

You can simplify it by using an array to store the possible combinations :

var combinations = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
];

var win = false;
for(var i = 0 ; i < combinations.length ; i++) {
    var c = combinations[i];
    if(board[c[0]] == valueToCheck && board[c[1]] == valueToCheck && board[c[2]] == valueToCheck) {
        win = true;
        break;
    }
}

if(win) {
    // ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

How is this any more efficient than the code in the OP? It's the exact same comparisons, except this answer has the additional overhead of a loop. This is LESS efficient than the OP.
0

I would serialize the board somehow, (for instance as a string of spaces, X's and O's) and then simply compare the current string to a known ending game string.

 | |
-+-+-
X| |
-+-+-
 | |O

Becomes

var gameState = "   X    O";

3 Comments

There are a lot of possible winning states, but this is an interesting idea.
I don't see any benefit to this. If you implement the comparison with a basic string compare, you require a giant list of all possible ending configurations. If you implement the comparison with a more sophisticated method, you could do it as easily without the serialization.
I was going for easy to implement, and an incremental step up from where the poster is now.
0

Represent each square as two bits in an 18-bit number:

00=blank, 10="O", 11="X"

and the squares are in the following order:

1|2|3
-+-+-
4|5|6
-+-+-
7|8|9

so that X's in the top row (with all other squares empty) is represented by the integer 258048 (which in binary is 111111000000000000).

Now, if you're wanting to see if X has won, you use bitwise AND (&) against the 8 possible winning combinations:

if (
    (gameBoard & 258048 === 258048) ||   // top row full of X's
    (gameBoard & 4032 === 4032)     ||   // middle row full of X's
    // etc.
   ) { // X has won }

Ideally, you put each winning combo (again, there are only 8) in an array and run through them like so:

if (
    (gameBoard & winningXCombo[0] === winningXCombo[0]) ||   // top row full of X's
    (gameBoard & winningXCombo[1] === winningXCombo[1]) ||   // middle row full of X's
    // etc.
   ) { // X has won }

And, if you truly want to optimize, check for the 4 winning combos that go through the center square first. In a game against an intelligent opponent, the winner will most likely have the center square. Checking those combos first will let you take advantage of short-circuiting in evaluation of the conditional.

Comments

0

Here's a short way using Array's some and every. Not compatible with old browsers.

var wins = [
   [0,1,2], [3,4,5], [6,7,8], // rows
   [0,3,6], [1,4,7], [2,5,8], // columns
   [0,4,8], [2,4,6] ];        // diagonals

var is_value = function(i) { return board[i] == valueToCheck; };

if( wins.some(function(a){return a.every(is_value);}) ) { ... }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.