Help with my Tic Tac Toe Game

Hi all - I’m working through an attempt at the Tic Tac Toe game. I have not implemented any AI at all (I am lost right now on how to do this), but I have built a game where the computer can make a selection based on a random number and assign the “O” value.

The codepen is:
Tic Tac Toe (version 1)

I have a couple of questions with my code:

#1: When Player 1 wins, it console logs “Player 1 Wins” two times. I can’t figure out why.

#2: When Player 2 wins, it doesn’t console log right away, you have to make another selection as player 1 before it registers the win.

I am trying to figure out why this is happening. I’m sure that there is an obvious answer, but I’m just not seeing it. I’ve been working on this for a long time (weeks :)) so if anyone has some time and wants to look through my code and figure out what I’m doing, I’d appreciate.

In order to see the Player 2 console log issue, you have to try to lose the game to “O”. “O” is not smart, so losing can be very difficult. :slight_smile:

Thanks!

1 Like

Ok, I’ve had a play with this and can replicate both issues.

The double console.log issue is odd. If you create a blank target div under your tic-tac-toe board and write the result to that on the page, it only writes one response:

I think you can ignore the double console.log issue, and you can be confident that it will only trigger one actual on-page response (like if you use a pop-up, modal or something to report the win.)

I’m looking at the second problem now…I imagine it’s just because you’re checking for the win conditions at the wrong time, but I haven’t looked too closely yet.

HTML I added

<div class='result></div>

JS I modified

function gameOver(playerWins) {
  if (playerWins === 1) {
    $(".result").text("1 wins");
  } else if (playerWins === 2) {
    $(".result").text("2 wins");
  }
}
1 Like

Ok, issue 2.

My hunch was right, you are calling checkForWin() at the wrong time.

Read your code carefully - you actually have some redundant calls to checkForWin()!

Think carefully about whether you want to run checkForWin() on each user click event, at the beginning of each getSquare() call, or at some other time.

Teaser:

2 Likes

Thanks for the help! I have made some changes based on your suggestions and the problems have been fixed.

Now to just implement some useful AI…

Thanks a lot for your thorough response, it helped me a great deal.

1 Like

Hello,

I’m wondering if you might be able to help me with (yet another) issue.

I’ve updated my code here and now, when the game should show a tie, it instead freezes and then posts a player win.

I added code that tracks the number of turns, and then when turns === 8, I run the endGame() function and pass a different parameter into it.

Thanks.

I’m finding it really hard to follow all the logic in your code as it stands!

I’m not sure why it is so slow to allow the final click or why it behaves oddly, but I do notice that you read directly from the DOM a lot, which could be the culprit slowing you down. It might not be that, but it certainly doesn’t help readability in any case.

Take for example your numberOfSquares variable. You get your code to search through all the HTML looking for ‘square’ classed elements. Why don’t you just set the variable var numberOfSquares = 9?

I know later on you want to access the text from that numberOfSquares behemoth you’ve stored, but there are cleaner ways to do that, too. In that later case, ‘numberOfSquares’ becomes a bad variable name because what it actually represents to you in your use case is an object containing all sorts of data relating to the HTML entities that have ‘square’ classes.

Look at the console.logged object you’re loading into your code:

That’s a lot of cruft considering you just want to see if there’s an X or O in a square.

I think the broader problem is that you are looking at this game as a human with eyeballs and fingers, and you are asking the computer to do the same.

The computer doesn’t actually need to ‘physically observe’ (i.e. search the DOM) for every move you make.

Instead, think about the mental model that might represent this game if there were no squares at all. Ultimately the game can be played with 9 possible moves, which alternate between players until there are no moves left or one of the players has picked a winning combo.

So you might have an store of possible moves, which gets smaller every time a valid move is made, and a store of player moves, which gets bigger. Imagine this like a card game with a pile in the middle and each player holding the cards they pick up…this can be achieved with arrays.

Sure, you need to watch for DOM events so you know which ‘card’ the player wants to pick up, but you shouldn’t need to have the computer keep looking at the page to track what’s going on. It can just look at the arrays (which is much faster, and easier to reason about yourself)

I know that’s not the exact answer you were looking for, but I think in the end you’ll be able to continue adding features and fulfill the remaining user stories more easily. You also suggested you wanted to try to implement a better AI…I haven’t tried that, but using a method that relies on arrays and simple numbers will be easier than your current method as well.

1 Like