
Discover building a react native tic-tac-toe app with single-player bot modes, adjustable difficulty, and optional sound and haptic feedback, plus multiplayer login, sign-up, invites, cross-device play, and game tracking.
Enhance your learning in React Native: customize video quality up to 1080p, adjust playback speed, access notes and transcripts, and explore lecture-specific code branches with Q&A and VSCode tips.
In this lecture we will briefly discuss what TypeScript is and what problem does it solve. Then we will install TypeScript using npm.
In this lecture we will discuss basic types in TypeScripts. This includes numbers, strings, booleans, arrays and more.
In this lecture we will discuss interfaces and types. These are ways to define the shape of an object in TypeScript.
In this lecture we will briefly introduce a great TypeScript feature called generics.
Let's discuss what expo is and how is it different from vanilla React Native.
Let's install Expo, create a new Expo project and run it on our physical device.
In this lecture we will see how to run our Expo app on the iOS simulator.
Let's take a look at the steps required to install and run the Android emulator.
Let's take a quick look on how to run typescript in our Expo project. Since we choose the Typescript Expo template; this should be pretty easy to do.
Let's now create a script for code formatting. We will do that with the help of a great tool called prettier.
Let's finalize our scripts by writing a script that will check for JavaScript errors using ESLint.
Let's now use the scripts that we've created to check our code before committing to Git.
Let's see how are we going to organize our folders & files through out the project.
In order to make it easier for us to import modules from our project folders, let's setup some plugin that will allow us to have aliases for folders in our project.
Let's discover how can we use expos font package to load custom google fonts.
In this lecture we will create a custom text component instead of the default react native one. The benefit of that is that this component will use our custom font by default. We will also see how can we make out component inherit props from the native text component.
In this lecture we will refactor what we've done in the last lecture. We will move our font loading logic into a separate component.
Let's use a famous library called React Navigation in order to set-up our navigation for the app. Also let's see how can we use typescript together with React Navigation.
Let's create a reusable component that will add a gradient background to our screens.
Let's carry one with our home screen by adding a logo and creating a button component.
Let's in this lecture prepare our single player game screen files and boilerplate code.
Let's create a simple tic-tac-toe board component so that we can be able to get more into our game functionality.
Let's create a utility function that will print a tic-tac-toe board in a formatted way.
Let's now add more utility functions; isFull, isEmpty and getAvailableMoves.
Let's now create a lecture that will help us figure out the winning symbol and winning direction for a given board state.
Let's start working on making our board a little bit more interactive by inserting a symbol when clicking on a cell.
Let's discuss the algorithm that we are going to use to create our computer player. And this algorithm is called the minimax algorithm.
Let's take a look at a quick introduction to recursive functions in case you are not familiar with them.
Let's know implement what we have discussed in the minimax algorithm theoretically but now in code.
Let's carry on with our getBestMove function and see how can we store the indices for each move.
Add a maximum depth parameter to getBestMove to control search depth and difficulty in tic-tac-toe, using maxDepth in getBestMoveRecursive to stop at terminal states.
Integrate the getBestMove function into the single-player tic-tac-toe user interface and initialize a board with a random starting player. Use useEffect to drive bot moves, including first-move center or corners.
Let's do a little improvement to our game by adding a sound and haptics feedbacks when a cell is inserted into the board.
Now that we know how to load and play sounds; let's add some more sounds for winning, losing or drawing a game.
Currently the code for loading and playing sounds is too much for our single player game screen. Let's move that code into a custom hook!
Let's create a new component that will be responsible for displaying a line for the winning row/column/diagonal.
Now that we have setup our BoardLine component; let's now style it either vertically, horizontally or diagonally depending on the result object.
Now that we have our line styling done; let's work on animating the line when it's first rendered.
Let's now improve the styling for our board so that it looks like our design.
Now that we have our board ready, let's add the rest of our single player game UI.
Let's add the functionality for the UI that we worked on in the previous lecture.
Let's now create a page for the settings. For this lecture, we will setup our page and customize the page header.
Now that we have set-up the files for our settings page, let's work on the UI.
Now that we have our settings page UI ready, let's now work on the functionality for persisting the settings.
Now that we are retrieving the settings from the AsyncStorage, let's finally save the setting to the AsyncStorage when an option is chaanged.
Let's now improve our settings logic by moving the settings code into a react context to be able to access our settings anywhere easily.
Let's continue with our settings context and make use of it in the single player screen.
Let's take a look on what AWS Amplify is and how are you going to use it in our App.
Let's take a quick look on what Polices, roles, groups and users are in the AWS console.
Let's configure AWS Amplify on our machine by using a simple CLI tool.
Now that we have Amplify configured. Let's use the CLI to add services to our project.
Let's take a look at a great tool provided by Amplify. This tool allows us to mock our generated GraphQL API locally before pushing any code.
Let's install some client libraries that we are going to use in order to communicate with Amazon Cognito. Let's also create a screen for user login.
Let's initialize the login screen by adding a text input and style it so that it matches our App.
Since our TextInput styles will be re-used in multiple screens, let's create a custom TextInput component. We will also use forwardRef which is a react feature that is used for forwarding component refs.
Let's now communicate with cognito and send our form information to authenticate.
Now that we are able to login, we need to find if there's a user logged in locally whenever the app is opened.
In order to easily access the logged in user object through out the app, let's create a context to get and set the user.
Let's now move our context into a separate file and use it in our home screen to display different UI based on whether a user is logged in or not.
In order to do something whenever a user is logged-in, logged-out or any other auth related event; we can use an event listener provided by AWS in the Hub module.
Let's setup a new screen that will contain our registration form.
Now that we have set-up our register screen, let's work on the UI for the form and the API functionality.
Now that we are done with the registration form, now we need to allow the users to confirm their account by entering the code they get sent via email.
In this lecture we will add a button to resend the confirmation code. In addition to that we will also handle users who did not confirm their account when registering and try to login later.
Let's go through the code for forgot password and reset password features.
Let's start by creating a scheme for our users that we will store in the database.
Let's discover how can you restrict who can access our AppSync models based on their authentication type.
Let's see how can we use cognito triggers in order to run a lambda function whenever a user is confirmed.
Now that we have seen our event and environment variables. Let's start writing our post confirmation login.
Let's tackle the problem where a user who exists in cognito is trying to login but this user for any reason does not exist in the database. This can be done by running a lambda function before the user is authenticated.
Let's add a new model in out schema for the Game table.
Before writing our relation in our schema, let's first try to visualize what we are going to create.
Let's now start writing the scheme for the intermediate model that will be used to create a many-to-many relation between Games and Players.
Let's now limit who can access our PlayerGame model by adding auth rules.
In this lecture we will initialize a new lambda function that will be responsible for starting a new game. We will discover what will our event contain and see how we can trigger the function using a custom mutation.
Now that we have our function setup, in this lecture we will write the steps for our function.
Lets initialize a lambda function that will be responsible for playing a move in a game. In this lecture we will initialize our function and discuss the steps that will have to take.
Now that we have setup our function and written our steps, let's start implementing the playMove function.
Let's deploy and run some tests for our playMove function.
Let's take a look at the onUpdateGame subscription, try it out and see if it's suitable to use in our game.
Let's create a custom subscription to listen to only a specific game by its ID instead of listening to all games.
In this lecture we will take a look at how can we add custom resolvers to our subscriptions using the vtl language.
Let's see how can we add the ability to search players by name and username efficiently using Elasticsearch.
Since AWS Amplify created a folder in our project; This folder might interfere with our JS bundler and cause some errors. Let's fix that in this lecture.
Let's take a look at the design for our multiplayer game and start by creating the boilerplate for the screen and configuring its navigation.
Let's now do some checks in order to only allow logged in users to access the multiplayer game.
Let's now see how pagination & sorting can be achieved with amplify. Then we will prepare the query that will be used to get the games of the logged in player.
Let's now see how we can call our API in our app using the aws-amplify package.
Let's now see how can we generate typescript types for the shape of the response that we get from our GraphQL API. This will be very helpful in avoiding typos and getting autocompletion.
Now that we are getting our data, we need now to store them in a react state. This should be a simple task; however we also need to set proper typescript types for our games.
Now that we have our data ready, let's start displaying the UI using a FlatList component.
Let's now implement our load more pagination in addition to puling to refresh functionality.
Let's now work on displaying our game content. We will start by displaying the opponent's name and the turn.
Let's now do some checks to decide what to display as a result for the game.
In order to listen for changes for each game that we render, we will have to move the game item into a separate component so that we can subscribe & unsubscribe to events using useEffect.
Let's now subscribe to our custom subscription (onUpdateGameById) in order to get notified when a game is updated.
Now that we are getting updates whenever a game is updated, let's now reflect these updates in our UI.
Let's now add a modal that will open when the "New Game" button is clicked.
Since we are using the @searchable directive in our Player model, we can now easily use the searchPlayers query to search for players by name or username.
Let's now add a search input in our modal. We are also going to autofocus this input when the modal is opened.
Now that we have our search input, let's work on our functionality by calling our API and fetch players whenever the search button is clicked.
Let's add our final touches to our modal by styling the search results and moving styles into a separate file.
Let's now create a new screen for our multiplayer game and see how can we manage its navigation.
Let's now write a function that will either fetch an existing game if we navigated using the games list, or create a new game if we navigated using the search players modal.
Now that we have our game fetched, let's use the Board component to display the state. Also let's create a new function that will be responsible for playing a move.
Let's now update our game state when we play a move so that the board will be updated with the latest state.
Instead of repeating our logic when displaying an error message, let's create a helper function that will extract an error message from our API error response.
We now need to update our board whenever the opponent player plays his turn. So let's do that by using our custom subscription onUpdateGameById.
Similar to our single player game, let's add a winning line and sound effects for playing a move, winning, losing or drawing.
Now that we are done with our functionality, let's work on styling our screen
Let's take a quick look on how I implemented the header of the multiplayer game screen.
In this course we are going to create a Tic-Tac-Toe game using React Native (Expo). Although the Tic Tac Toe game is simple, our project won't be very simple. We are going to use Typescript in the project. Typescript is a tool that adds types of the JavaScript language. Having types allows us to avoid certain bugs in our code in addition to many other benefits.
Our app will contain a single player game. For that we are going to use an algorithm called the Minimax Algorithm in order to create a bot with different difficulties. In addition to that, we will also have a multiplayer game. In the multiplayer game we are going to create an API and manage Authentication using a service called AWS Amplify. AWS Amplify allows us to easily build a GraphQL API that we will use in our game.
Let's breakdown what will be discussed in each section:
Section 1
This is an optional section for students without or with limited Typescript knowledge. We are going to have a very quick introduction to Typescript. We will discuss things like basic types, types, interfaces and generics.
Section 2
In this course we are going to use a tool called expo. Expo is a tool that simplifies building apps using React Native. We will see what is the difference between expo and normal React Native. And then we will install expo, create a new expo project and run it on a physical device, Android emulator and the iOS simulator.
Section 3
In this section we are going to setup some tools that will be very helpful in our workflow. First we will install Typescript for type checking. Then we will use Prettier to automate formatting our code. We will also use ESLint to enforce JavaScript rules. Husky to make sure we run all these tools before committing our code to git. And we will finally install a module resolver to make importing files and components in our project a lot easier.
Section 4
In this section we are going to do some general setup for our application. Including loading fonts, creating a custom text component, setting up navigation and more.
Section 5
In this section we will build our single player game. This includes the UI, the bot player, adding sounds and haptics, creating a settings page to choose difficulty and other options and persisting the settings on the phone using react context and AsyncStorage.
Section 6
This section will just be an introduction to AWS Amplify and some AWS concepts like IAM. We will also install amplify and set it up in our project.
Section 7
Here we will use AWS Cognito which is a service that comes with Amplify to add authentication in our app. This includes login, register, otp confirmation, resend password, reset password, forget password and more.
Section 8
This section will cover creating a GraphQL API using Amplify for the multiplayer game. We are going to learn how to create a model in our database and add authorization rules for this model to restrict its access by the API depending on authorization methods. We are going to create models for our players and our game and connect these models together. In addition to that, we will create multiple lambda functions that will handle different parts in the game like starting a new game and playing a move and we will see how to trigger these functions using our API. We will also create the necessary GraphQL subscription to listen for changes for each game so that we can have a real time experience.
Section 9
After completing the API for the multiplayer game, here we will start building our UI. This includes listing games, paginating games, searching for players, starting a new game and handling updating the game in real time. When consuming our API, we will learn how to use amplify to generate typescript types for our queries, mutations and subscription for a great development experience.
Section 10
This section is entirely dedicated to sending push notifications with expo. Sending notification may seem simple; however there are a lot of stuff that need to be handled that we will discover in this section. Eventually we will be able to send a notification to a player when he is invited to a new game.
Section 11
This short section will show you how simple it is to add ads in your game using AdMob which is integrated in expo.
Section 12
In this final section we will discover how smooth building and publishing your app with expo is. We will build our apps for Android and iOS and publish the builds to the App and Play stores.