Multiplayer Tic-Tac-Toe Game in React Native Mobile
Note: This is part one of building an online multiplayer tic-tac-toe game in React Native using PubNub. If you have finished part one, please view part two of the tutorial where you will implement more backend functionality and play the game. You can view the completed application on GitHub.
Tic-tac-toe is a classic paper-and-pencil game that consists of rudimentary rules: two players, X and O, take turns placing their pieces in a square on a 3×3 table. A winner is declared when one of the two players places three of their pieces in a horizontal, vertical, or diagonal row.
Tic Tac Toe Multiplayer Gaming and PubNub
This game is meant to provide a connected shared experience for players, where they can play with their friends anywhere around the world. To do so, you’ll use PubNub to power the game’s real-time infrastructure. All you have to focus on is developing a great experience for the players.
PubNub provides a secure, scalable, and reliable infrastructure to power any application through its real-time data APIs. With multiple SDKs available for your application needs, PubNub makes it easy to send and receive messages on any device in under 100 milliseconds.
You will use the PubNub React SDK to connect two players to a game channel where they will play against each other. Each move the player makes will be published to the channel (the lobby room), as a JSON payload, so the other player’s game board updates with the current move. By updating the table in real time for each move, players will feel as if they are playing next to each other.
Multiplayer Tic Tac Toe Game Functionality
The completed application, available on GitHub, will function and publish on both Android and iOS devices.
You'll add a lobby where players can join or create a room. If a player creates a room, they become the room creator and wait for another player to join their room.
If another player wants to join that same room, they enter the lobby room name (channel name) in the alert prompt and become the first player's opponent. If a player tries to join a room that already has two people, they will be unable to join.
Once the game starts, the tic-tac-toe game board is displayed, along with the initialized score for the players.
If the game ends in a draw, then neither player gets a point. But if there is a winner, the winner’s score is updated. The room creator gets an alert asking them if they want to play another round or exit the game. If the room creator continues the game, the board will reset for the new round. If the room creator decides to exit the game, both players will return to the lobby.
Before you can begin implementing the game, you'll need to set up your environment.
React Tic-Tac-Toe Environment Setup
If you don’t already have React Native set up on your machine, then be sure to follow React's getting started guide - a fantastic beginner walkthrough in getting started with React Native. Follow the rest of the instructions in the documentation to install any essential dependencies.
In your terminal, go to the directory you want to save your project in and create a new application.
You need to install five dependencies and link them to the app you just created. To make this easy, add the following script file dependencies.sh to your app’s root directory.
You'll need to make the script executable with the
Run the script by calling dependencies.sh from the terminal.
Finally, now that your machine is set up, you'll need to create a free PubNub account, as you'll need your publish/subscribe keys to send information across the PubNub Network.
Initializing the Multiplayer Tic Tac Toe Project
Create a file named
index.js in your app’s root directory and add the following code.
You'll need to create a new file named App.js. This is the main file for the game and it contains the components for the lobby and the table. Begin by importing the components and dependencies that will be used throughout the project.
Add the base constructor where you will insert your Pub/Sub keys to connect to PubNub, initialize the local state objects, and initialize the variables.
Each state object and variable will be discussed later on. Ensure you initialize PubNub after initializing the state.
Next, subscribe to the channel
gameLobby when the component mounts.
gameLobby is the main channel that players publish (send messages to) and subscribe to (receive messages from) when they are in the lobby. More logic will be added to this functionality later on, but for now, focus on the render method.
Lobby component is shown first because
this.state.is_playing is initialized to false. Once an opponent has joined a room channel that is waiting for another player, then
this.state.is_playing is set to
true and the
Lobby component will be replaced by the
Game component. The
Spinner component is displayed to the room creator as long as the room creator is waiting for another player to join the game.
Add the CSS styles at the end of the file.
Before you finish the rest of App.js, take a look at the
Implementing the Lobby Component
In the lobby, players can enter their usernames and create or join a room. The logic that saves the username and calls the right method when a button is pressed is implemented in App.js. All the methods in the lobby component are used to style the buttons, but there are only three methods of focus in this tutorial:
onPressJoinRoom, which are passed in as
props from App.js.
In the app’s root directory, create a new folder named src and within that folder, create another folder named components. Inside of components, create a new file named Lobby.js. Add the following to the new file.
In summary, the logic in Lobby.js is setting up the username field and the two buttons. As previously mentioned, the only logic you do is to style the buttons. In this case, the buttons' background color, border color, and text color change when the button is pressed.
Make sure to add the CSS styles to the end of the file:
Saving the Username
Whenever the player types in the username field,
onChangeUsername is called. This method, along with the rest of the methods in this post, is found in App.js.
You need to save the username in the
username state and limit the number of characters to 15 characters so the username won’t be too long. You can increase or decrease this number if you wish.
Creating the Room Channel
Next, implement the method for
onPressCreateRoom, which is called when the user presses the Create button.
The first check is to see if the username field is not empty. If the field is empty, the player is alerted to enter a username. A random room ID is generated and truncated to five characters. The ID is then appended to tictactoe–, which will be used as the game channel that players will subscribe and publish to in the PubNub Network. Below the
if statement, add the following code. In order to obtain the number of people in the channel, PubNub's Presence function is used.
Once the room creator subscribes to the new channel, you alert the room creator to share the room ID with other potential players.
Add the following code to the
else statement used above to alert the room creator to share.
Since you want to change the state for certain objects,
setState is used to perform this change. Below the alert, in the else statement, add the following to set the state and close the else statement.
After changing the state of four objects, the boolean
is_room_creator and the room creator’s
username will be published to
Spinner component will be displayed to the room creator while they wait for someone to join the game.
Back in the
componentDidMount function, you need to set up a listener to listen for certain messages that arrive in
You need to get the room creator’s username, so an
if statement is used to check if the message arrived is
true, change the state
x_username to the room creator's username.
Joining the Room Channel
The last method
onPressJoinRoom is needed to finish setting up the lobby.
Ensure that the username field is not empty. If it’s not empty, then a prompt is shown to the opponent to enter the room name.
Since you need to consider both platforms (iOS and Android), check which platform the app is running on and use the appropriate prompt. For Android, use the prompt dependency
Alert.prompt is only supported for iOS devices.
Essentially, both prompts accomplish the same goal: call
value is the room name and cannot be an empty value when OK is pressed.
Since there can't be more than two people in the same lobby,
hereNow is used to check the total occupancy for the channel. If the total occupancy is less than one, the player is trying to join a room that has not been created or there is a typo in the room name.
If the total occupancy is two, then there is a player in the channel, the room creator, who is waiting for another player to start the game.
If the total occupancy is greater than two, then the player is trying to join a room with a game in progress, so an alert tells the player that the room is full and to join another room.
Once the opponent successfully subscribes to the game channel, a message is published with the opponent’s username and
readyToPlay set to true. Since the player is not the room creator,
not_room_creator is set to true.
Finishing the Lobby Component
To finish the
Lobby component, add the last logic for the listener in
Both players will unsubscribe from
gameLobby since they are subscribed to the game room channel. In
setState, three actions are performed:
Set the opponent's username to
is_waitingto false so the
Spinnercomponent will disappear from the room creator’s view
trueso the game between the two players can start.
The last method to implement before finishing the lobby is
This method is called when the component is unmounted and destroyed. The player is unsubscribed from
this.channel, the channel the player is subscribed to for the game.
You've successfully set up your React Tic-Tac-Toe game and initialized the lobby room. Now that you have finished the logic for the lobby, you'll continue in Part Two of this tutorial by setting up the Tic-Tac-Toe Table and adding the game logic, and implementing real-time interactivity between the players.
Be sure to continue in Part Two to complete building your own Tic-Tac-Toe real-time multiplayer game in React Native.
If you have any other questions or concerns, please feel free to reach out to email@example.com.