Implementing a Tic-Tac-Toe game app in Ionic+React
In a recent blog post, Ionic Framework announced general availability for Ionic React: "a native React version of Ionic Framework that makes it easy to build apps for iOS, Android, Desktop, and the web as a Progressive Web App." React is a javascript library suitable for building user interfaces. React claims its added value in being declarative and component based thus making it simple and straight forward to implement user interfaces that render based on data and state changes.
In this article I'll explore developing a web app based on Ionic React starting from the single page react app template that the Ionic CLI generates for you and the starter React tutorial for a Tic-Tac-Toe game. Since that code base only provides the UI for playing the game against two humans, I decided to implement some more logic into the app making it a human against computer game. In order to build playing strategy on the computer side I used the Minimax algorithm for choosing the best move. Minimax is a recursive algorithm that finds the optimal move for the game assuming that the opponent is also playing by applying the best move. Basically the algorithm explores the tree of all possible moves returning a score indicating if there's a win or a loss. Such procedure will be used by the computer logic to choose the optimal move in response to the human.
I will not go in detail on the code implementation; you can download all the source code that I developed or modified here. Instead, I will go over the most important steps taken to assemble the final App. If you follow the links that I provided above in order to get the Ionic starter app created and to download the additional code, you'll fin yourself with the following:
- a Ionic react app project in typescript/jsx
- a game UI in javascript/jsx
- a recursive function implementing the minimax algorithm in swift
In the rest of this article, I will discuss the code changes to the starter Ionic app needed to include the React UI from obtained from the tutorial source and the modifications made to the game in order to add the logic for the computer play.
The following steps will create the Ionic starter app. We will need a recent version of Node installed in our development environment. In order to create the game project we will leverage the Ionic CLI to install Ionic and create a starter app named "TicTacToe".
npm install -g ionic@latest ionic start TicTacToe blank --type=react cd TicTacToe
As a start lets take a look at the file App.tsx. We will load an additional css (./theme/tictactoe.css) that will help us in rendering the game board.
The additional .css file defines two classes that we will use in order to render the game board in the file Game.tsx: centerRow and centerCol. The two classes defined will draw horizontal and vertical borders in order to render the classical 9 boxes in the "hashtag style: #".
Before we explore the rendering functions implemented within the React components, let's take a look at one more modification that we need to make to the Ionic starter app load the Game UI. In the file Home.tsx we will remove the html generated by default for the default page and insert the react component named Game (we also changed the page title).
The corresponding React component class that implements the Game is implemented in the Game.tsx file placed in the same folder of the Home page. In order to create the Game.tsx file, we start from the index.js of the tutorial and we need to make some adjustments as this code needs to be converted to typescript. Therefore some typing is required in order to get through the Ionic compiling and publishing cycle.
We also change the render() function for the Board class so that the UI is able to draw the game board by using the Ionic components. We use here the two css classes defined in our additional stylesheet (.centerCol and .centerRow).
So, now we have imported the game from the tutorial into the Ionic app and we are able to play with another human opponent using the smartphone or the browser as out game board. What we want to do now is add some logic so that we can play against the computer. Fo the sake of simplicity we will assume that we go first and we get the X while the computer gets the O mark.
First, we need to implement some logic in order to let the computer make its move.
We add the function computerMove() the Game class. In order to choose the move the computer will, in the first place, look for a defensive move: it needs to find out if the human has a winning move and therefore take that square. It this is not the case, the computer applies the MiniMax in order to end the optimal move. The implementation of the MiniMax, ported from the swift code, is shown below.
Finally we need to make sure that the computer makes its move after the human. In order to do so we implement the componentDidUpdate() of the Game class. This function is called by the react framework right after the component, ad all its children, have updated and the rendering has completed. In our case, this happens after the human clicks one of the buttons that constitute the playing board.
We also need to make sure that the computer does not start playing against itself, therefore we call the computerMove() function only if X (the human) is the next player.
Here's a small video of me playing against the computer from my smartphone.
In conclusion it was straightforward to modify the starter app in order to include a react component and create a fully functional Ionic React app.
References:
- Announcing Ionic React, Max Lynch
- Tutorial: Intro to React, React Web Site
- Tic Tac Toe - Creating Unbeatable AI, Greg Surma
Download the source code files here.