Win32: Tic Tac Toe

Tic Tac Toe

In this video, we use the material from previous C++ Win32 lessons to write a Tic Tac Toe video game. This version of Tic Tac Toe is event-based. We use left-mouse clicks for player 1 to place Xs: WM_LBUTTONDOWN. We use right-mouse clicks for player 2 to place Os: WM_RBUTTONDOWN. Lastly, we use a menu-click event to reset the game: IDM_NEW_GAME.

In the game, we needed to write a WM_PAINT handler to repaint the window. This handler draws the board on the screen, but it also serves as a point in the code where we can the end of game conditions.

The reason that WM_PAINT works well for the checking for the end of the game condition is because every event causes a window repaint. When player 1 places an X, player 2 places an O, or a player click "New Game" in the menu, we call InvalidateRect() to repaint the window. Since the game can only end after an X or O is placed, checking for the end of game condition after a repaint is an ideal place.

We handle an end of game conditions after our repaint inside of the WM_PAINT handler. This way, we can be sure that the final repaint happens before the board is reset. Popping up a message box freezes the window, so that the players can clearly see how the game has ended.

Our end-of-game conditions are checked by the functions HasWon() for wins and IsBoardFull() for draws. The check for win condition is similar to what we did in C++ Console Lesson 9: Tic TacToe, where we check for two wins through the upper-left corner, four wins through the center, and two wins through the lower-right corner. These conditions are illustrated above. Our check for a draw just calls IsBoardFull() to make sure that no squares are blank.

Since our program is not loop based and we are using two separate events for each players move, we need to be sure that the correct player is moving or the correct click is occurring before we change a square on the board. These checks are done in the PlaceX() and PlaceY() functions. In addition to these checks, we need to verify that the click occurred inside the game board and on an empty square. Otherwise, we pop up a message which say "Invalid Move."