Building a Tic Tac Toe game using React.js | Daryl Duckmanton | Skillshare

Building a Tic Tac Toe game using React.js

Daryl Duckmanton, Experience is our biggest asset

Building a Tic Tac Toe game using React.js

Daryl Duckmanton, Experience is our biggest asset

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
25 Lessons (1h 49m)
    • 1. Introduction

    • 2. Tools and Resources

    • 3. Creating our React project

    • 4. Adding our game template

    • 5. Creating the Game Component

    • 6. Creating the Board Component

    • 7. Creating the Cell Component

    • 8. Populating Cell Content

    • 9. Dynamic Classes

    • 10. Dynamic Cells

    • 11. Dynamically Highlighting Cells

    • 12. Lifting Game State

    • 13. Configuring Cell Clicks

    • 14. Populating Cells

    • 15. Changing Turns

    • 16. Prevent Overwriting Cells

    • 17. Creating the Result Modal Component

    • 18. Controlling Modal display from the Game.

    • 19. Setting Up Game Over State

    • 20. Setting up the Calculate Winner Function

    • 21. Calculating A Winner

    • 22. Calculating A Tie

    • 23. Showing the game's result

    • 24. Fixing the Winning Combinations

    • 25. Starting a new game

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

In this class I take you through how to build out a local 2 player Tic Tac Toe game using React.js. By the completion of this class you will be able to say you can build a reasonably sized application using some of the best practices in React. This class assumes you already know how to install Node and NPM and are ready to just get started building a React.js project.

This class will take you through the following:-

  • Creating a new React project
  • Migrating a HTML template with CSS into React
  • Breaking up and application into multiple components
  • Component properties
  • Managing state (using the useState hook)
  • Handling DOM events
  • Building Tic Tac Toe calculation logic

This class is for students who have some knowledge in React.js already and are looking to:-

  • Get more experience in how to build a moderately sized application
  • Add another project to their React or overall web development portfolio
  • Just want to make some interesting web based games

Meet Your Teacher

Teacher Profile Image

Daryl Duckmanton

Experience is our biggest asset


I am a full stack web developer, who has been developing websites for 12 years, both from a back and front end. I have been working in the areas of HTML5, CSS3, Javascript, Typescript, .NET, Windows Azure, AWS and Angular 2-7 in recent years, and also have approximately 12 years in ASP.NET.

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
  • Yes
  • Somewhat
  • Not really
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Your creative journey starts here.

  • Unlimited access to every class
  • Supportive online creative community
  • Learn offline with Skillshare’s app

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. Introduction: Hello and welcome. In this series, we're going to build at a tic-tac-toe game using React JS. Over the next 25 videos and roughly two hours of content, we will start a brand new react project. Populating, organize a pre-designed HTML CSS template into a collection of reusable components, as well as focus on all the tasks necessary to make our game interactive. If you like, which is say, let's get started. 2. Tools and Resources: Okay, so before we get started in actually building our game, I just want to quickly talk about the tools and resources that you will need for this class. So one of the tools we'll be using is Visual Studio cut. So if you haven't downloaded that, I suggest you download that first. I'm going to be using the Mac version, but you can use this for Windows or Linux or whatever you're using. It will always the sign. The other thing I'm doing is I'm taking advantage of the Create React app executable. So you can come to the Create React app.js website. And you can pretty much run the script that's here in the quickstart and you should be ready to go. Now I'm most likely going to be using a different version of Create React app. And then so I can vision more particular application. However, I do recommend you follow the standards here and use that in px command to ensure that you're creating your React apps using the latest version. So that's the second thing. The third thing is that I'm going to be using a template for this application. So there is some custom HTML and CSS that I've written earlier just to save time that we will use to build at the main UI of our game. This is available in a just and will be used throughout this crash course, including this little snippet of JavaScript in here that says matrix. I'll explain what that does a little light up. Anyway, that's it. I will leave all links to the just that we have here, plus all the tools that are needed for this class in the project and Resources section. So with that said, let's move on and actually get started. 3. Creating our React project: Okay, so obviously, this is a brand-new React app that we're going to be making. So I'm going to use the command Create React app to create the React application that we are going to be using to set up this tic-tac-toe game. Now the thing is, I want to make sure that people understand the version of Create React app on using. So I'm going to do an npm view here of the particular library with a version on the end. And that will tell us that we are using Create React app version 3.4.1, nebula Tom, you get to this recording. You might be using a lighter version of this executable. Now everything should still be fine. But if it's not, please let me know and I'll do my best to correct the issues that you may find in later versions of react. Now if you happen to be using an early vision, I'm not really going to worry too much about what is wrong about earlier versions. You'll have to upgrade to this version at a minimum and go from there, a cat. So now that we know what version of Create React app I'm using, I'm now going to cold Create React app and create my project, which I'm going to call just tic tac toe and execute that. And now it will start creating my React application. Now with the power of video editing, we'll just skip ahead and let this complete. So few minutes lighter. And you should see something that looks like this, where we have a success. And it gives you a set of instructions that you can use to run your application. So it's telling me to use yarn to start the application. But you can also use npm. But I'm not gonna do that here. I'm going to open up with source code first, and then we'll run it in the browser. So here I am now on my main Mac desktop screen. And I've got a browser open with just one tab open at the moment. And I've also got my project loaded individual CDI cut. So all I'm going to do here is quickly check to make sure that the app is going to load by doing an npm start. And then we'll let that run through. And there we go. We have ourselves a default React project up and running. So that's cool. We're now ready to get started on building our game. 4. Adding our game template: So now that we've got our application up and running, I'm going to now grab the templated HTML and CSS that I provided in a just and paste it into our application. So this is what I'm going to do. I'm going to come over to the browser and access to just, I'm then going to take this pre-compute HTML snippet that I've called index.html. I'm then going to come over to our app.js and I'm guaranteed to replace the contents of the return statement inside the app function with the HTML from the just, just like that. Now I'm just going to format a few things such as give me a moment. And there we go. I've now formatted HTML so that it's indented a little bit better. Now the problem is right now, if I save it as is, we're actually going to get an error. And the error is simply because we have two root nodes in our return here. So in React, you must always have one root node in whenever you're trying to return from your component. So to get around that, I'm going to use the fragment syntax, which looks like this. So you can have it like that. And at the very bottom, just after the overlie, I'm going to come and close off that same bracket like son. I'm then just going to indent the rest one lot in. Now if I save it, well, we're going to get a warning about the logo, but I'll fix that in a moment. So if I come back over to the React app, well, it doesn't look that great right now. But that's what we've got for the moment because we don't have the CSS. So let's add the CSS now. So coming back over to our adjusts, if I scroll up, I have some CSS for the index.js file. So I'm going to just copy everything that is in here. And we'll take a look at what it does in a minute. And we come to index dot CSS. And I'm literally going to replace everything that's inside here right now with what I have there. And save. And we'll just take a quick look. And now we can say we're getting a little bit closer. I'll come back to what is in here in a moment. I just want to get the other CSS in play. So the last piece I want to grab is the CSS for the app dot CSS file that we will be using. Basically, we will copy everything there, come over to our app dot CSS. And once again, just replace everything in here with everything we just copied. And if we save this, now we have our tic-tac-toe app. Now doesn't do anything. It's not functional, but it should look like this if you've done everything right, okay. Now I just want to clean up two more things. And that is basically, if I come to app.js, we have a reference to the logo here. We don't need that anymore, so I'll delete that. And I'll also come in and delete the logo dot SVG because we're not going to be using it in. Location. So that's now gone and we get an error, which is interesting. My understanding is that's because I haven't saved the file and now it goes away. Cool. Alright, the other thing I want to quickly do is I want to replace this world-class we className. And that's just basically what React tells you to do it. We shouldn't be using class inside our GI OSX. We should be using the word class_name. So to get around that, I'm just going to quickly do a find and replace IA. So whenever class is, I'm just going to change it to className and replace all. And that deals with that problem. So I still Dan here or good, no errors. And the page still loads. Cool. Now let's just quickly cover what we've got here. So basically how I built this up is that you've got the main body which has the background on it with that gradient. And then inside of that, we have our tic-tac-toe game. And the tic-tac-toe game is made up of this yellow board here, as well as the actual board itself with the cells on it. And what you can't see at the moment for what you'll say LIDAR is kinda like a modal that will show when the game is over, okay? Currently that is set up to display none. And that represents all of this overlay stuff, Dan here. Okay. So I wouldn't worry too much about explaining this until we get to it. But for the rest of it, basically you've got a main game element. Then you've got h one, which is our Tic Tac Toe heading. There. We've got our board, which basically represents this grid of cells. And then we have multiple buttons representing cells on our board. So these are clickable buttons. Inside of that, we'll have some cell content, which I'll explain later why that's there. For now. Just know that each button has some content that will be populated a lightest stage, ok. Now terms of CSS, I'll quickly go to index.js says, I quickly explain what said. We have a whole set of colors that you can basically update yourself if you want to. Tragedies app looks and feels. So say for example, say you want to use red for the background light color. Or once you do that, you get that color there for the gradient. Alright? And we can do it for a whole bunch of things. Society, the primary color, which is what I primarily used for all the grains. Say I'll want to sit that to now be blue. Alright. Then you'll see that everything that has a primary color settler won't be set to blue. So you know, just some variables to change some of the colors within the application. So it just allows you to theme stuff. Then I have some variables around gradients. So this main background gradient matches the properties needed with the colors necessary, so that we get that gradient in the background here. I have some primary grades as well, which is to represent the gradients here for the cells. We have got a highlighted version of it, which when we hover over there is that highlighted version. And we've got some box shadow for things. So you can say stuff kind of pops up a little bit. And just basically other bits and pieces around font sizing. And as you will see later, we've got some animation here as well. We've got some default styling for everything. So no margin, no padding. We're sitting box-sizing, border-box. And that's just to make sure that when we size any element and say it should be a 100 pixels, it actually will be a 100 pixels. Without this, sometimes elements are larger than we anticipate. So that's what, that is. Therefore, we have a height of a 100% for HTML and body. And that's just to ensure that the body takes up the full height of the window. So if you take this away, like so and save, you can see that the game has been pushed to the top. And that's because the higher the body is based on the high of the content sided. So that's what this is. Therefore. Then I'm using display grid for the body. Said I can place everything into the middle of the screen. And that's just using some CSS grid properties. And I also have a background set to that green one that you see here. For the application itself. Well, we'll go through this bit by bit, but essentially we have a background color for the game. So the gamma represents this pace here. Then we have the H one properties for the H1. Then we've got our board which assist the grid using CSS grid. Once again, we've got cells were set in flexbox property sit on it and other bits and pieces. Then we have different toggling stage for active. And this winner thing, which we'll say a little bit laid out on the cell. And then for the content, I'm actually hiding the content for the moment. I'll explain that a little bit later as well. Then we've got the populated class. I was financial layer as well, and in some CSS in the modal. Okay. And that's pretty much how it broken this up at the moment. So that's pretty much everything for this video. In the next video, we'll start breaking this down into React components, starting with the main game component. 5. Creating the Game Component: So we've created our React application using Create React app. And we've imported the HTML and CSS to show the presentation for our guy. Now what we wanna do is take this game element and create a React component that encapsulates everything. Now why am I going about creating an individual component for the entire game? Considering it seems to be the root of our application. Well, that's because I'm a little bit more future thinking. And I'm always concerned that I need to add more to my app later on down the line. And the guy really should be just encapsulating everything. That's for the game itself. Ok, so that's kind of why I'm doing this. I don't necessarily have to do this step and needed the you, you can leave everything inside of app if you want. And whenever I talk about main.js or the game compiling, it is referred to as your application component. But for me, I like to create an individual container element for my game. And that's what I'm going to be doing. So to do that, I'm going to come over to my source folder. And I'm gonna create a folder called components. And the components folder, I'm gonna create another folder called game. And then inside of that, I'm going to create two files, I guess main.js rare component, and also a gave dot CSS for the styles. Now all I really wanna do here is grab everything that's pretty much in app. Copy it. So I selected all copy it. Come I would say main.js and pasted if I selected properly. And now I'm just going to clean a few things up. So I'm going to remove that default export at the bottom. Because what I'm gonna do for this particular component, I'm going to G is a constant. So I'm going to go const game equals function. And I'm going to convert this to an Arab function because our lock arrow functions and I'm going to export that instead. What I'm also going to do is change this import to gain dot CSS rather than app dot CSS. And for the moment, that's all I'm going to change in here. And getting the save that. And nothing's going to change yet because we haven't removed 18 from app.js. So that's where I'm going to come up with my app.js. And I'm going to cut everything here. We'll just delete it. Like Saad. And I'm going to reference the game element that we just created and doing give me the intellisense. So if I try this the second time, there we go. It's just important that gang component if assignment now, well, we still get everything the same. And that's because S is, S is still in. App.js says, well, if I cut this out and I click save, now we go back to this ugly looking thing. But I'm going to come to main.css instead. Paste it in there, save that. And everything's working again. What I'm also going to do is I'm now going to remove the app.js file, which is going to break the app. But then I'll just come in and remove the import. And that just basically moves or the Logic App, cage app very Lane and moves all the complexity into the game compiler. And that's all we're going to do for now. So the next video I will look at breaking the HTML NEA in game, starting with the board. 6. Creating the Board Component: Okay, so we have the Galerkin finite imply and it will act as a main entry point to our guide. But it's doing a lot. It's displaying the board as well as it's displaying the modal overlay at some point down the line. So we really want to break these two things out. So we need a component for the modal overlie, AML, need one for our board. So for this video, which is getting into Preet board, will do that first. So what I'm gonna do is come over to components again. And I'll create a new folder for board. And the board, I'll create two more files for ab.js and vote dot CSS. Then for the contents of both OJS, we're going to come over to gain JS, copy everything, come back to both js, then pasted all in. And we're going to remove some mock up. So we're going to remove everything by the board curd. So I'm just going to grab that caveat and then remove the rest of this h3 bell. So now we have an empty component. Now I'm going to paste that both towed back in and just have everything in appropriately, so everything is back to where it should be. And then what I'm gonna do is rename this to board, obviously, like Sol, change, import to board dot CSS and signs. And well, nothing changed yet, but that's fine. We need to reference this board inside of our game component. So in again component, we now need to cut out the board. So all of this stuff here can say good-bye. And that didn't work. We will literally come down and do this instead. And they're carried out. And now I'll just add the bulk component directly into here, like so. And I'll probably even bringing these inputs then, because I like a lot of space between my mind imports and the application specific inputs. So if I save this, we still get our Board. And now what I'm gonna do is also bring the CSS that's inside of game and put it into a bowl as well. So come to gain. And I'm gonna grab everything pretty much from the top of the CSS file. After the height one, everything from this hash board all the way down to where it stands on metal overlie. I'm going to select all that chatter dad. Safe. They will see the Volcker's y will come over to board dot CSS, pasted in and save. And now we can say it's all back again, okay? And that's pretty much all I wanted to do for this video. What I'm going to do for the next video isn't going to break this board down even further, so that it has multiple child cell components that make up that button. There. 7. Creating the Cell Component: Okay, so we've got our ball component. But if we look at what the board is currently doing, it repeating a cell button multiple times. So we can say the same button with the same classes is set nine times, okay? Inside of this component. Now actually the cell is going to have interactivity on it. So we're going to want to be able to click on the cell and it's going to do something. Now rather than trying to manage this within the board. I think that we need another component to manage an individual cell. So that's what we're gonna do in this video. So to do that, I'm going to come over to components. I'm going to create another folder called cell. And once again, I'm going to create two files called Soul dot js and also sell dot CSS. And just like I did in the previous video, I'm going to come out with support dot js. I'm going to copy everything that's in here for the moment and paste it in cell but js. And then I'm going to change a few things. So I'm going to have cell dot CSS that will reference the component will be called cell. And I'll just take one of these buttons because really any one button, Canada, and remove the rest of the HTML that we have here and paste. Once I remove all that, now we have L1 button. Okay? Next thing I'm gonna do after saving is that I'm going to come over to my board. So this over here. And I'm going to remove all these buttons. So literally cut all of this out as we don't need it anymore. And I'm going to start using that cell component. So I'm going to import it and throw it in life that if I say this at the moment, well, now we're only going to get one cell because we've got only one so component. So just for the moment we're not going to do is I'm actually going to duplicate this particular cell non times. So 123456789. And we'll leave that and save. And now we've got Add New and cells again. Okay? What I'm also going to quickly do is come over to my board dot CSS and everything to do with the cell, which is pretty much everything below dashboard. So other than that first selector, we're gonna grab everything here. We're going to cut all that out. Save the file. You'll see that we lose all the cell styling coming into my cell dot CSS, paste in near siphons again. And now we've got our so components working akin to alright, so now we're ready to start working with functionality. Starting with actually populating the cells when we do something. 8. Populating Cell Content: Okay, so now that we've created our cell component, we need to now learn how to populate it. So obviously when we click on a cell, eventually we want to show value. Now we haven't gotten to the click part yet. Let's just get into this grid cell in the first place. So if we look at what we've got, we've got a button. And inside that button we have span with a class name, cell content. So the various she really go inside of the span. So if I put an x in here and we save it, well, what you see right now is we still don't see anything in any of the cells. Okay? Now why is this going on? Why is it still empty? Well, if we look at the cell dot css file, if you look at the cell contents selector At the moment, I'm sitting in a width and height to 0. And I'm also sitting an overflow to him. And this means that any content that goes inside of here, it will currently be cut off and basically not show up. Okay? So that's what these three values is doing. And why am I doing this? Well, what I wanna do later on, when I click on the cell is I wanna trigger and transition. So I'm going to transition the width and the height to certain size. Okay? I ever said animation period. What is this size? Well, it depends on what we apply to the cell content class. Directly underneath it, we have a populated class that can also be applied to the same cell that has the cell content class. And what I'm doing here is I'm saying the width and height to 12 V min. Now, what will happen is when we dynamically add the populated class to the cell content element, it will trigger this transition and basically shower an X or an O with a bit of animation. Okay, navigators to show up at the moment. I'm going to add this populated class to the actual class name here. So space than populated. And when we save this, now we can say all the x's show up, but it shows up in every single cell. Now why is that? Well, we're using the cell component, nine tons on their board. So this here, right, we're not passing in a value of the cell at this point. We just hard coding it into the span. So we need to change this and wanted to do is take advantage of component props. And I'm going to bind that in here. Like SON. Oops, she's said value. So I'm gonna create a prop covariate and a sonnet here. Then that means it will go back to Planck again because none of the cells and our board, our policy in a value. So let's do that. So for the first one, let's say it's an x. And then I will just copy this a few more times. Copy of a cell in fact. And I might change a few values here. So in why I made these ones empty, we'll make this one an IO and leave this one as an x. Maybe made this one and oh, and maybe this one and I will keep it like that for now. And if I save this, and now you can see that the x is sharp in the fishery cells for 012 here. And then we've got two O's which showed there and there, and then an x, then an O, and then the last two cells are blank. Okay? Now the key thing we need to take care of going forward is when we have a winning combination like this one here, we really need to give that highlight, basically this kind of Tony for that particular cell, right? Or for these three cells in particular. We also wanna make sure that we only add that conditional populated class when we actually have a value inside the cell are, are what we're going to take care of all that in the next video. 9. Dynamic Classes: Okay, so I've got value's going to eat cell confinement and we've got it coming from the board at the moment. So values are passed through the very property for each cell in the board component. And then in cell that a is assigned to this location. We've got that working. But what we need to do now is we need to conditionally add certain classes to Bert, the button and the span. Okay? So at the moment, we always have the popularity class set on the span that is inside the button. But what I said in the previous video is I really only want this class when there is a value inside of the cell. So I don't want it to currently be applied to these two down here. So if I have a look at what's inside those cells right now, by expanding the window and inspect the element, we can see there is a popular class on here. We don't want that. Okay? So we want to remove that in a conditional Y. So I'm just going to close it up again and say that we can see what we're looking at. And so there are a couple of ways to attack this. I'll show you the bad way first, and then I'll show you a slightly better way after that. So now I don't want that. I'm going to actually remove it for the moment. So everything goes away. And what I'm gonna do is I'm going to up here the final led and I'm gonna call it cell contact classes, okay? And I'm going to set it to so content by default. And then I'll pass it down here as an input to className. Whoops, white zone and save. And well, that was still have cell content in there. And we can just double-check that again by once again expanding this out and making sure that this little element here, when I can get a hold of it, they all have cell content. Say they're all there. So that's still working. But what I can do now is I can conditionally add another class. So if I go, if prompts the very, So I have a value attribute of our props, then I can go self-contained classes plus equals space, and then the word populated. Now if I do this, you're going to sail the values come back. And it's going to look like maybe populated with added to every single cell. And if I expand this out again, and we do a good ol inspect here, will come down to the cell that isn't populated. You can see for the ones that are populated, there is no unpopulated class. If I choose one that is populated, say this button here. You see it is set, okay? So that conditional logic is in fact working. So I'm going to minimize this again so we can get back to our code. Now, that's cool. But I said we also want to set up a class for the winning combination we have here, right? So how do we do that? Well, if we look at our CSS. We can say basically on the cell, there is a winner class that we can apply that will give us the highlight that we see when we hover over things. And we want to use that. So if we want to quickly see how this looks, I can add the winner here, just like sun and save. And now everything is highlighted, right? Which is what we want. So we need to add that conditionally. So same deal. I can go let cell classes, set up a default to sell, and then passed setting conditionally over here. And as you can see, it's gone back to no heavier winner anymore, which is fine. Then basically strive to this. I can add another if condition and go if. And I'm going to call this prompts dot can highlight like psi. And I haven't created this on the cell yet, but I will in a moment. And I can go so classes plus equals space. And in that window flag. And if I save this right now, it's still not going to show anything because we haven't set that can highlight flag on air cell yet. So for Canada with the blog.js, I'm going to set a kinda highlight over here. And I'm going to set it to true for the first three and then false for the rest. Now why do I say true for the first three? Well, basically the cell 123 here, or index 012, or have a value of true. They're all part of a winning combination. So from here onwards, I am going to say everything else to false because they're not part of a winning combination. And when I do this and I add them all in successfully, then save. Now you can see we get that winning combination rule, highlight those three cells at all times. And the other is still work as they did before. We still hovering over them and see that same state. So this is what we want. However, if we look at our code here, it's a little bit messy. Alright? We don't really want to be doing this whole. If a value is set, we're going to use plus, equals and stuff like that. It's not the best way to maintain your code. So how can we improve this and make it better? Well, there's a library that react recommend cold class names. So they come over and I'm going to go npm install class names or one word, all lowercase. And when I run that, it's going to go off and install that library. So I'll come back in a moment. Okay, so now it's installed. So now we can use it. So it's pretty ADD US. We can just come to the top via and we can go important class names from class nine. And mom state, this should be a capital N, like so. I believe. Yes. And then I can save that. And now we can use this class that I've defined to define a few extra attributes that we have here. But it is slightly better. Why? So let's attack the subclasses 1 first. Firstly, I'm going to do is set this to a const. And instead of setting it directly to sell, I'm going to call this function class names. Now in sort of this class names, it takes an object and what it is, is it's like a key value map. So you say, or classes, do you want to apply? So they say by default, we want to have the cell class set. We say that we always want that to be set by setting a value true. However, for the winner class, we only want this to be applied when prompts dot can highlight is set. So we can do something like this. We can Joe winner and we can set that to props, dot can highlight. And when that has a value of true, right? That will mean that the winner class will be set to the button as well. By doing this, we can then get rid of this logic like SAT. And I'll just add a space here. And now I can just leave it as it is here and it should still work. So if I save it, we can see that we still get that same behavior on the first three headache can highlight set. The rest did not. So that's why I have that winner class. Now going to do exactly the same thing for the cell content classes one here. So I am going to carry out that nine. So now this one has a definite, so you're probably wondering how it works with properties. Well, the cool thing about JavaScript is if you do have properties name one, that you just put them in sort of quotes and save it like that. Okay? And then for the secondary, which is populated like that, we are doing this when Prop stock value is set to something. So we can just do something like this. Alright? So if prompted by a is equal to an empty string, or now or undefined or something like that. This will return false. Otherwise, if it has some value in it, there's going to be set to true. And that means I can remove all of this stuff and everything should work to sign. So save this. And now you can say everything is still there. And we just check the DOM one more time just to make sure that they don't have the popularity class. So if I do that and I come down to this button, open it up. And now we can see the cell content class is set only here. If we choose one that is populated, say this arm here. We can see it is said, okay, sign with the cells. We can say sell dot winner. Yeah. So when a cell winner, and then when it's not pi of a winning combination, there is done when a class CU, and I think this is a better way of conditionally handily classes on elements. 10. Dynamic Cells: So a game is time to take a bit of shape. We have cells that have values in them now. And we have certain classes set on the cell based on a given input data going to each cell. The polymer is at the moment. If we look at our bull component, this is all hard-coded. Essentially, we're saying in nine different occasions what the value is going to be and what the value of can highlight is going to be. Okay? We really want to make this more dynamic. So the first step I'm going to take to make it more dynamic is decided least, let's get it from an array that allows us to generate the cells. Ok? So what I'm gonna do is the first step is I'm going to create a constant here called cell values. And what this will contain its just the value of each cell. Okay? So we've got the first three, which will be x, then x, and then, and then two empty values. So that's an X, another X. Now even do it like that. Then we have an OH, then we got our again there, we've got an x. There. We've gone to the R. And then finally to the values. Ok. Now to get from this cell values array into an array of these cell elements, I'm going to call, well first I'm going to assign to a variable, sorry, the result of cell values dot map. So we're going to start mapping each value to something else. And I'm going to grab each atom in cell values. And I'm also going to grab its index. And I'm going to return a cell element. So cell, I might just put this on the next line. So the value will be, well, the vary from cell values and we'll just set for the moment, can highlight to false, will deal with can highlight in the very next video. So once I've done this, I can get rid of the cells and replace it with just cells. Now why is that? Well, the result of cell values dot map or map each value that's in the cell values array to I sell element. Since the value to that value. And just for the moment and can highlight set to false. So this cells variable here will contain nine actual cells because we have done in values. So if I save this, now we can say we get a similar result of what we had. It's just that the difference is we don't have the highlights working at the moment. Co. Now just one thing I need to quickly mention here before we move on is there if I come over to the console, you'll see that we get this era, okay? And that's because in react, whenever we want to use arrays in Agile OSX, like this, expects us to define a unique value for a gentleman. And does that using this key property. Said that the purpose of this, we have access to the index. So I'm going to pass in the index as the value to key. And when I do this, well, we don't see anything different. But because we said that vary the errors, they are gone away. Okay, so that's it. In the next video, we'll focus on getting those winning combinations, working again. 11. Dynamically Highlighting Cells: So now we've got dynamic value's going to add tic-tac-toe board. Nadh, still copying from just a steak array here at the moment. But we'll deal with that problem a little bit lighter. What I want to cover in this video is basically getting this can highlight flag to work appropriately based on the fact that we have a winning combination right here. Okay? So to do that, I'm going to model I knew constant under cell values. And I'm going to call it winning combination. And inside of this, we will contain the index of the cell values that make up the winning combination. We can see here x, x and x, that's 012. So in here I'm going to put 012, okay. That doesn't do anything on its own at the moment. But now when I come down to this map function, before we return the cell, I'm going to get the value of ten highlight and pass it to this can highlight property here. So the first thing I need to do is make this a regular function now, because we're gonna be doing more than one thing. My disa return and just quickly make sure it still works. And it does. And then just before the returns diamond here, I'm going to add a constant called can highlight. And what this will be equal to is whether the index that is passed here is inside this wood in combination or not. So we look for it and say this is 0. Well, we say 0 is here, that this will be set to true. Let's say this is a full, then four is not inside this list, so this should be set to false. And how I'm gonna do that is by doing the following. First, I'm just gonna make sure wood in combination exists, right? So it's not undefined or an empty array or something like that. If it does exist, then I'm going to do winning combination. And I might even put this dam on the next line so that we can say it. We need combination dot index of the index of the current item being processed in cell values. Whether that's inside of winning combination. So that's whether it's equal to 0 or higher. All right? And this is true when index is 0, y. Let us, because if we do an index of policy in index, which in the first loop it will be 0. We can say that exists at the 0 position of winning combinations as it 0, ultimately this will return true. Be confusing, but that's how it works. Then all we need to do here is set that today. And in fact, I might go one step further and just do a bit of formatting here just to make things look a little prettier. So it properly is on its own line. Just like that. So what will happen now is if the index of the survey is in the array, this will be true past in history and that will be highlighted. So let's just quickly test this. And there we go. So now if we say all of a sudden that we want 0 for an ICT three part of the winning combination. Then all I need to do is update these values here to say 0 for an ICT apart of the winning combination. When I do that now you can see those cells are highlighted. Or we can say year maybe 036, which is equal to this one, this one, and this one, right? If I save that, and then you'll see those ones are highlighted. But obviously this is not correct based on the inputs in there. So I'll set it back to 12 and save. And there we got. That's all I want to cover in this video. In the next video, we're gonna go another step up. Let's start moving the state of this board into the game component. 12. Lifting Game State: So we have ourselves now being populated dynamically from the perspective of the board. But the problem is the body is not really the right place to capture the data. We need a centralized place or centralized component that captures all the information and propagates down through the board. So what I'm gonna do is I'm going to move this game data that we have here into the actual gain component. And this is kind of known as lifting state, so to speak. So I am going to cut out these two values. They're from board. I'm going to save it at the moment and it is going to break. That's okay. I'm going to come to game. I'm actually going to paste the data on the top of game here. Now it's still not going to work because I need to pass cell values and winning combinations down to the board now. So to do that, I'm literally going to do cell values as an attribute here and make it equal to cell values. And then I'm also going to grab winning combinations. Set that as a value here as well. Now on its own, if I save this, it's still not going to work. And the reason for that is because the Board still looking for local versions of these values. So we really need to get these ne'er from props. So I just go probes. And in front of surveys are go props dot surveys. And for the winning combination, I do the same thing. Just like that. And I'll just tap this over again. And now if I save this, now we've got the state working as it did before. But now all the data is defined in our gain. And this is the place where we're now going to start handling all the interaction of our game. 13. Configuring Cell Clicks: So our gain is starting to look a little bit better. We've got dynamic cells being created inside of our board. And this creation is based on the data that's coming into the board. The cells are showing, either highlighted or not highlighted is surely an X or an O and things like that. The problem is, it's not very interactive right now. In fact, all the data is coming from to static arrays that we have here in our game. So the first thing I'm gonna do is I'm going to empty out all the data that's in this array and leave it as a default blank. I'm also going to empty out the winning combination and get it back to an empty board like side. Now the main focus of this video is to start working with cookie on things. So for each cell that we click on, I want to be able to handle that in sort of a game can pilot. So the first step to do that is to come over to our cell component. And on the actual cell button itself, we need to add an onclick event handler. So I'm just going to go on click. And I'm gonna set this to props, dot on click, OK. And I've got two dots there. So all my prompts in my board, I'm now going to have to handle an onclick event handler for each button feed cell. Okay, so to do that, I'm just going to save what I've got here and come over to my board. And I'm going to define Just before I return or create the cells, I'm going to create a function here. And that function is going to be called cell clicked. And this would just be a simple error function that takes in the cell index. So whenever index of the cell that we're going to be using here. And then what it's gonna do for the moment is it's just going to log out. We'll say cell, or maybe we'll do this, even sell and then sell index. Clicked. So this will be just to check that when I click on the cell, the board has detected that a cell was clicked. So I am going to do that for now. And then Dan in the cell itself, I'm going to have the onClick property set, and I'm going to set it to basically sell clicked passing in index. Now I should make this as an error function. Otherwise it's going to call cell clicked immediately. So omega is an area function, so this will get triggered when the cell is clicked now. So let's quickly test this out. And that should have a semicolon at the end. I just realized. So let's test this out. So let's click on one of the cells. And in fact, before I do that, I'm going to make it a little bit bigger so that we can say our console window here. So when I click on one of the cells live, so you'll see it says Selzer I clicked. If I click on the second one, cell one clicked, or click on the last one, cell, right-clicked, and so on and so forth. So that appears to be working from the board level. Problem is we want to add the game level, right? So all we really want to do here is make this something that we can pass in. Alright? So instead of calling so clicked, I'm going to pass in prompts dot cell clicked Dan here. And I'm going to remove this function and save and come up to my gang. And just before the returns Diamond, I'm going to add in this cell click event handler. And then all I have to do is on the board where I put so clicked. I just pass in cell clicked. And in fact, I might even call this on cell clicked just to be different and pass that here. Just so it's a little bit different. So when this happens and on-air save, hopefully we should get the same behavior, but it's handled at the game level. So let's just quickly check this out. So if we click 0, we can see cell zeros clicked 147 and so on and so forth. Okay, so I think that's enough for this video. In the next video, we'll start maybe potentially populating the cells based on, when we click on it. 14. Populating Cells: So we've got as cell click event up and running and ready guy. Now we can start working towards getting data into each cell when we click on something. So the first course of action you may take, if he don't know, react very well, is to just come in and say, I've got my cell values. And I'm just going to come down here and I'm going to target the option at cell index and say he said something like x, right? If I run this right now and then try and click on a cell, well, guess what? It doesn't actually work. Now why doesn't this work? Well, simply because this game component needs to be re-ran whenever you change this value, right? And currently, that doesn't happen when you basically have a local variable that's changed, okay? What we need to do is we need to convert this local variable into state. So then when we update the state, it's going to rerun this functional component. So to do that, I'm just going to come up to the top ea and import a hook cold months. And then we need to update this declaration here. So the first step is I'm going to put the cell values inside of an array. Sad, because we're going to restructure it from the coal to you state here. And sort of you state. It takes an optional first parameter, which is the default value, which I'm going to keep as an array of nonempty values guide. Because if I take one of these add, for example, we're going to lose one cell. So let's add in all non-empty options so that we have known Celsius. Now IMRT that would work. Alright? Where if we try running this again and clicking on something, you say it still doesn't update the cell or R. So even though we're updating the values, still not updating the cells. And again, it's because it's not running the gain function, right? So just to give you an idea of what I mean, if I say rendering gain component here. And save. And I made this a little bit bigger. If I open it up right now, you're going to see it's being called twice. But that's just for initialization. But if I click on this, you'll see it's actually not calling that ever again, is just calling that click event handler. And in fact, just to make it easier, I'll just get rid of that. So when you get rid of that and we'll check again, and we can see it's called rendering the game twice. But then after that, whenever I click on this, it's not calling it again. So we can't just use data like this. We have to use the second option that we destructor called Set varies, right? Cell values I'll call. Now this can be any Nano wants to be the, usually you just put the same name you have here, just with the set in front of it and using camel casing, OK, so if it's called cell values, its sets of values. So that means I can potentially come down here. Now go set cell is, and then I make it equal to the cell values that said here, because we've changed it. So if I do this, for example, and save, well, will this work? The answer is no, it doesn't. It still doesn't trigger that new update of GAD. Now, the reason for this not working is because we need to create a new array instead of replacing the contents of the current one. In react, the stable only update if the very you are sitting points to a different location in memory. For rise, this means that it has to be a completely new array entirely. So I'll create a copy of cell values. So just say I'm going to create a new concept called new cell values. And I'm going to make it equal to. And you can use the spread operator to get all the values of the current surveys and put it inside of the URI. And that creates a new array. And then because the reference of this has changed, and that's what has happened here. The reference has changed because this is changed when I said the very here. And then save it like so. When I click on the cell this time, it will now start adding in that x. Okay? Now this is all great. This is the first step. But obviously we want to be able to trigger the next ten. So at the moment, the x's are dominating and we don't have any logic that handles when it's O's turn. Well, we'll deal with that next. 15. Changing Turns: So now we've got our game populating cells. But the moment we are just populating the x-value. So rather than using x like this, what we want to be able to do is change turns. So we want x to go first, then we want outer guy, then X, then r, and so on. Until against complete, we filled in all nine cells. So to do that, what we need to do is we need to create more state to determine who's going next. Ok. And how I'm gonna do that is by coming over and setting a new set of state they appear to x's next or art. So that's a very ongoing to use. And then I'm going to have a set X is next to set that value. And I'm going to set it to use state. And by default, I'm going to make sure x starts off as the first person to take action. Save that. Now issue. We just need to now use X's next and set X is next in the logic Dan here in the click event. So for the new value, I'm gonna set this to if x is next, then it has the value of x. Otherwise, it's our lotsa. Now if I set this right now and save and I play my game, well, it's x. Now it should be o. But actually no, it's still x. And that's because we still need to call set X is next. So set x is next. And what we said it to is the opposite of what it currently is. So you can use the expression to do that. And you go not x is next and save. And that will total it back and forward between true and false. So if that's the case now, and our logic works properly, we start off with an X, then we get an hour. Then we get an x that an, that an X than an, than an X and an R and so on and so forth. Ryan Koh. So now we've handled that situation. Let's move on. 16. Prevent Overwriting Cells: So I'm not sure if you guys pick this up in the previous video, but we actually now have a bug in our gain. And what is the bug? Well, it's simply this. If I come over to my game and I click on this first cell, I said to X. If I click on it again, I can change it to o because it's O's turn. If I click on again, well, it's X's turn. So he can continue to toggle back and forth. Now, we don't want this. We want to make sure that once a cell is populated, that the contents inside the cell can't be changed, right? Because that's how Tic Tac Toe works. So to fix this, it's pretty easy. I'm going to create a function just above the on cell click function. And I'm going to call it is cell empty. Because if the cell is empty, we should be able to update the value. If it's not, then we shouldn't write pretty straightforward. So I'm going to create it as an error function taking the cell index. And all this is gonna do is check to see if cell values at that index is equal to an empty string, right? So if it is an empty string, it's empty. And then all I have to do is inside the on. So click event handler is wrapped everything inside here in an if condition. So if is cell empty, passing in the cell index. If it is empty, then we can actually change the state. Otherwise we shouldn't, right? So if I save this, and now we try to do the same thing again, I can click on the cell and then I click on it again. It won't change them at a how many times I click on it. If I click here, it's r. If I click on the same sell multiple times, you can say it will never change. So x, r, and so on, right? So we can't change them anymore. So that's cool. We've fixed the bug. So now that we've done that, we're going to move into handling the result of again, we'll do that next. 17. Creating the Result Modal Component: So we're in a situation now where we have game working in the sense of we can take turns and we can add X's or O's into different cells until we get to the very end and then we can't do anything else, right? We need a result at some point. And so we need the ability to show who won or whether it's time. Now that involves two things. It involves basically having a visual representation of the win or a tie. So in the case of this particular application, we're going to be showing some kind of modal overlay or some kind of overlay presentation, show who won. And the second part is the calculation function that will need to be used to determine who the winner actually is. Now that calculation part will leave for a future video. All focus on in this video is getting this modal ready. Distinct Dan here, which we have left dormant for a firewall. Now, what I wanna do is quickly show you what it looks like. So if I come over to game and go into gained dot CSS in the modal overlay selected here, I've got Display set to none. I'm going to swap this over to grid and see what we say. Which is this. Ok. So we have this yellow little strip thing and a button that's surrounded by an overlay. The overlay sits on top of the game. So I can't click anything in the game because of the fact that even if I refresh the overlays in the y, OK. So that's what the modal overlie HTML and CSS is doing. Now I really want to get this into a comparative its own. So let's go ahead and do that first. So I'm going to come up to components and I'm going to create a new folder. And I'm gonna call it result modal. Inside that folder, I'm going to create two more files, result modal ab.js and result modal dot CSS. Inside of result module.js, I'm just going to pretty much grab everything that's inside the board like so, and paste it into result module.js. Okay? Now what I'm also going to do is I'm going to cut out the CSS from gang, from the modal overlay all the way down. So all of this CSS here will be cut out leaving the game. And which ones like that in this guy main.css file. And I'm going to move that into the result modal dot CSS file. Like sad. Now at the moment the modal has disappeared. But that's because we haven't referenced the modal yet in our game. We need to make more changes to this result modal file anyway. So the first thing I'm gonna do is I'm gonna get rid of this important. I'm going to rename this import here to result modal. And I'm going to rename the functional component to resolve Maital. And then for the moment, I'm going to get rid of props. And I'm going to delete all this functionality here. And what I'm gonna do now is I'm going to remove the cells and even our mood, the ID of the div like that and save. And then what I'm gonna do is come over to main.js and then collect the stuff we have here, like site, so that no longer exists in this file. And then I'm going to paste it where this div is like that. Okay? So I'm just going to fix some indentation issue there. And if I save this, we still don't see the result modal at the moment. And that's not because of the fact that on hiding it, I'm actually, I'm showing it CSS, but the game is an actually referencing it. So directly under this game element, I'm going to add a reference for that result, Maital. And we'll just check to make sure it was referenced at the top ea. It is. And now if I save this, well, there's our modal again. Okay? So that's good. We've got everything out of game now from the modal perspective, and we've moved it out of game dot CSS as well. So this is all nice and somewhat clean. I'm just going to fix it indentation issue here that are saying this fall when I did the import initially. So just clean it up a little bit. And even here, I'm wiped clean some of this up just to get the indentation right. And I knew that was going to happen. So just indent this, fix this up a bit. And that's all where I want it. Cool. And now all I need to do is at least for the moment, we're just going to hide it again. So it goes away. So I'm happy where everything is now. We're going to now put more focus into this result modal and the game itself. And work on the logic that actually shows the modal when we have a result. And we'll do that next. 18. Controlling Modal display from the Game.: So we have our result modal into a result modal compiled it. And by default, we are not showing in, okay, which is the right course of action. However, we want to have the ability to tell our result modal when it should display. Now, if you look at the CSS for the result model, we can see that by default, we're saying the display to none. So what I'm going to do here is I'm going to actually add a new class directly underneath it, which I'm going to call dot modal Dash Open. And all this is going to do is going to set a display of grid. Okay? Now this is not going to affect 18 that's there at the moment. But if I come over to my result modal and I add the class here. So class name equals modal dash open, like that, and save. Well, that should have shown the modal open. Very interesting. What did that not happen? Probably because we have an ID selector here at the class selector there. So let's do this. Let's target the id with a class combined to get a better specificity. And there we go. We've got ourselves a modal showing when we applied that modal Dash Open class. So if I take it away and save, it goes away. Okay, so obviously we want to add this conditionally. So let's do that. So I'm gonna come up above here. And I'm going to once again, after I fixed this indentation of this returns diamond, that I just noticed this wrong there yet. I'm going to now have a const here for, let's say, result modal classes. And I set it to class names. So I should be importing that library up here. So import class names from class names. And for this one, well, we're only really important one top of class. And that is that modal Dash Open, Right? So the single quotes and have collimated meal of this. In single quotes, we're going to say that we want this class to be applied when we have something called props, let's say game over. So when these prompts has a value of game over, it's true. We're going to set modal open on this div here. So now I come down here. I've got a class name equals result modal classes. Now by default, we know that it isn't going to change anything over here. However, it will come to main.js and scroll down to resolve modal I can put in here, game over is equal to, let's say, true. And when we do that, then we can say that the modal shows up. Let's set this to false and save. And then it goes away. Now I'm just going to make this a different name and put is Game Over to be precise. So save that. And then over in my result modal, I'm going to change it to game over, over here. Just a better name for me personally, I think. And that's all I'm going to do for now. So in the next video, what we're going to do is focus on how we get this GameOver state based on where we are in the game. 19. Setting Up Game Over State: So in the previous video, we looked at showing the result modal based on a given input cold, it's game over, right? And whether this was totally into true or false, that will indicate whether the modal was shown or not. Ok? Now, obviously we're not just going to have it hard coded like this. We need to track this in state. So let's quickly set that up. So I forgotten to the top here where I've got x's next. And just underneath that, I'm going to create another set of data in state. So I'm going to put is game over, like so. And set is Game Over lifestyle. And I'm going to put equal to U state where the default is going to be false obviously, because when we start the game is not going to be over. Okay. So I'm going to pass that narrowed down into his game over like that. And when I save this, well, we can see that it's not changed the game at this stage. But if I said the default heated jury, then obviously it's reading that value and showing the result stripe from start. But we don't want to do that. What we wanna do is at some point during when a cell is being clicked, we want to calculate the result. Now as I said, I'm probably going to wait to calculate the result until an upcoming video. So what I'm gonna do for now is just go set is game over. So I'm just gonna set it to true here. Just for the moment. I just want to test the theory that when I click on a cell, we get a game over. So obviously we need to trigger this based on the result that comes back when calculating the winner. And I'm also just going to move it from here and put it under there. And that should be it for this video. So now we've boiled up the game overvalued. So we've got it in state. We can change it in state. And we know that eventually we'll change it in state based on the incoming result of when we calculate the winner. So that's what we're going to start looking at in the very next video. 20. Setting up the Calculate Winner Function: So we're at a point now where we're showing the modal based on this flag is Game Over. And currently we're setting the state flag to true. When we click on any cell. Right? Now we don't necessarily want to do that. What we wanna do is when we click on a cell, we want to trigger a calculation to determine if we have a winner. And if that returns a result, then we want to say the game is over. Okay? So that's what we're gonna be focusing on in this video. Now, how I'm going to do this is by doing the following. Firstly, I'm gonna do is move this. So value snippet up here above the comment, calculate the result. Now, there is one doing this is because I need the new cell values to be passed into my calculator function. And it's going to look a little something like this. Constant. Calc result is equal to this function. I'm going to create cold calculate winner, Right? And we'll take it as the first parameter, those new surveys. And then as a second parameter which may not be obesity stage, is going to be the cell index. And then because these calculate winner is always going to return a result, what I'm gonna do is set this Dan here to calc result, dot has result. Okay? So now let's go back creating this calculate winner function. So if I come over to my source folder, I'm gonna create a new folder called utils. And then inside of there, I'm going to create a new JS file called when our calculator dot js. Now inside of here, I'm just going to export a constant which is going to be called calculate winner. And this will be an error function that takes in those cell values and then sell index. And it's going to return some result. Now I'm just going to save this. And then over here, I want to make sure that we fix this compilation sheet. So I'm just going to quickly call calculate winner year and let it important. So it's up here in the our imports. And then I'll save that. And we can see now it's loading again. Now if I click on something, it's gonna break still. And that's because we're not returning anything from calculate winner. So when it calls has result, this is obviously undefined. So let's go about returning just the default template for now. So what I'm gonna do is I'm going to return an object. And the object will have three properties on it. Now there has result will return for the moment as let's just say true. And the other two properties I want to include is a winner self. We have a window which are currently set to undefined because we haven't defined a winning yet. And then the last one would be a winning combination. And that memory ability. And we'll just set that to an empty array for now. Now if I save this, we should, as a result, when we click on a cell, once again, get that modal right. Now if I change has resulted to false, and I click on a cell on that doesn't pop up and we can continue to click on other things. So just a little bit more control there as it allows us to continue with their game until we get this flag set to true. So that's it for the game part of things were pretty much got everything or mice where we want it, not quiet but we're close. But what we're gonna do in the next video is we're actually going to focus on how we actually calculate a winner. 21. Calculating A Winner: So it is time now to actually calculate a winner for again. And I'm going to be honest with you right now, this is probably going to be the most complicated video in the series. Navigate started. I'm going to jump over to my Just that I have in GitHub. And I'm going to grab the last one, which is called matrix dot JS. I'm going to copy this matrix object that I have here. And I'm going to paste it just above the calculate when a function. Now, when you first look at this, you might go, oh boy, what is this doing? Well, just tell it you know, what it's actually doing. It's actually working at the potential possible combinations that are combined with this first number here in the object. So for example, say I choose the cell 0 here, which is the top left one. What it is saying is here all the combinations that when combined with 0 makeup a winning combination. So you can have 0, then either one or two. So that's 01 or two, which makes a straight line. Then it can be either 036, which makes up this 1036, or it can be potentially 0 for an ICT. So that's this 1048. And if we think about it from this 0 position, we can win by getting this y, this y, this y. Ok? Now what you'll see is if we choose the number four, for example, we have four options in which we can win. So we can go from two to four to six. So that's two to four to six, right? We can also go from 345. So that's 345. We can also go one, then four, then seven. So that's 147. And lastly, we can start at 0 and go for an eye like we saw before, 04 and I. Alright, so they're the four possible outcomes that we can get if we choose this particular cell. So hopefully that makes sense. It's a little bit tricky. I understand that there are otherwise to set up the winning combinations for a game like this. But it's to use double dimensional arrays and stuff like that, or an array of values. I didn't wanna do that. I think it's better to have a lookup. So I'm looking up on the actual number that I'm passing in. And then I can live through only three potential options rather than all of them. Okay, so that's how I've chosen to do it. Hopefully that made sense to you. If it doesn't, please reach out, let me know and ask me whatever you need to ask. In regards to this. Now, how does this matrix thing work in regards to how we calculate a winner? Well, we have the current cell values and we have this current cell index that we just clicked on. Now, each of these numbers inside of this winning combination make up an index that's inside of surveys. Say for example, if I want to get the value of the cell we just clicked on, I can do something like this and go const. And we can say, let's go. Term value is equal to cell values at cell index. Okay? So that's how we can get it. Now potentially we may have a winning combination. So let's grab those potential winning combinations based on the cell that we just clicked on. So if I say sell index in this case is 0, the one I'm about to grab is what are referred to as wooden ranges. And that would be equal to winning matrix at cell index. So if this is 0, what this is going to now return is this thing right here. Ok? This two-dimensional array, an array with basically arise inside it. Okay? So that gives you all the potential combinations that when combined with the first value, will make up the winning combination. A little bit confusing, but hopefully you get more of an understanding as we go through it. Now what I wanna do is I want to determine based on the fact that I've chosen 0 here. With any of these combinations combined with easier, I've actually got the same value. Alright? So say that currently the cell value, the 0 position is x. Then we want to say with index 12 is also x, or 36 is also x, or foreign aid is also x, right? And if any of these are true, then we've got ourselves a winning combination. So to do that, I have to look through this. And to do that, I'm just going to go for let i equals 0. I is less than winning ranges dot length. Because we're looking inside of this, right? And we grabbing that length there. And then what we're gonna do is we're going to go I plus, plus. Now, once we've got access to all of these numbers, we can pull them out. In fact, what I'm gonna do is I'm going to move this into the for expression. So we keep all of them together. Now basically when I need to grab Next is the first value of each set, right? So keep in mind that when he ranges, we'll have three. It'll be the three options right here, right? I want to grab the first value of each set and have that as a potential option, right? So what I'm going to write is const. And I'm going to go first option that aren't going to make it equal to cell values. And what I'm going to pass in as an index here is winning ranges of i. So that gives me this particular pair. If this is 0. So say currently I 0, it'll give me this. But I want to get the first number. So I'm going to put 0, okay? And then if I want to grab the second value, this one right here, that all I have to do is do a similar option here for the second option. And I can just pick one. Now I can get away with code like this, because every single array inside of this massive array always has just two options, okay? No matter where you look at it inside of this matrix, it's always got to options. So that's why I can write code like this. But then I'm using the index that comes back from this result, passing it to cell values to work out what the current value is at that particular index. Now what I'm gonna do now is I'm going to evaluate if all three of these variables here are equal. And if they're all equal, either all X's or O's. And typically they are also not empty. And that's the other thing to keep in mind here. You know, they're not empty. They're all the same. Then technically we have a winner, a cat. Now there should never be empty because when you click on a cell, you're going to be adding a value here. So this current value should always be either an X or an R. So once I've got all this, I'm now going to have to have an if condition that goes if the current value is equal to the first option. So this is saying, say current value is x. If x is equal to whatever is stored in, we'll say for the first loop, index one of cell values. If that's also an X, right, then that should be true. And if this first option also is equal to the second one. So what we're saying here is that all three of these have to be equal, okay? Essentially what I'm running here, if that is true, then we have a winning combination, right? So to do that, we just guard returned that same object. We have below. We need these three values, right? But this time we do have a result. We have a winner. So we're going to have, has result set to true. The winner is just going to be the value that was basically selected when it first came into this function will be just current value in this case. So with the edge just had their turn and updated this cell, then that's the winner. And for winning combination. Well, all we have to do in this situation is say all the indexes, right? All the indexes that are part of the winning combination. So cell Index is one of them, right? So say this is 0, that's one of them. Then because we are using winning ranges and we have indexes in this matrix, all we need to do is just grab the other two options here. So this would be i and then 0, because that's what we've got here. And then obviously I N1 as well to get that secondary index. So a little bit confusing, I understand that. But this is all the logic that we need to determine a winner. Ok? So if I save this now and I play my game, so this time we'll go for a win. So we'll have x when this one. So starting at 0, then one, and then finally to now we get a win, okay? Now we haven't updated who the winner is yet. We'll do that a little bit lighter. But the game has stopped because it's established that we've got a combination that's a winning combination based on the fact it's gone and said, okay, I clicked on to last, right? This is the one I clicked on. So it comes up to the matrix, looks at the matrix, goes, I can see I've got three potential winning combinations. If I click on this cell, it's looked at the first one and said, OK, the first combination that could be potential is 201. I'll then get the values inside of our cell values array at each of those indexes. So at 012, and in the case of this example, they all equal to x. So then we say, okay, we do have a result. The winner is x and the winning combination is, well, in this case two, then 0, then one. Okay? So that's kinda what this code is doing. And what I understand, as long as this matrix is correct, then all the winning combination should be correct regardless. So if we try another combination, so let's say this time we go downward. Now we can see we've got a winning combination here. Now I just used X so far. What if we choose o, for example? Then it's still understands it o is a winner. And obviously, if we don't get a win, so say we do something like this, then the gain doesn't actually end stage. Ok. We haven't found a winner at any stage. So that's it. Now what I'm going to focus on in the next video is how we determine a tie. 22. Calculating A Tie: So congratulations to those of you who have gotten this far, we're almost harm. We're now in a situation where we can play a game. We can determine a winner. And we can show basically a modal, even no, that's not fully complete. We know that we can get a game over status. Now we just need to handle the situation over time. So a tie in tic-tac-toe when all cells are filled in and we didn't have a winning combination. Okay, so that's what this video is going to be about, is handling ties. Now if we think about it, that means that we really just need to keep track of how many turns are lifting and gain. And if that reaches 0, then we know that we had a tie. Okay? If it doesn't reach 0, then we know if somebody had a win, right? So that's how I'm going to handle it. So the first thing I'm gonna do is come over to my game and I'm going to capture some more state. So I'm going to come here and go const. And I'm going to put number of turns left. And set number of turns left is equal to u states. When I spell it right? And I'm gonna put non hea, because we're going to start off with no internet right at the start of our game. And then basically I'm going to come down to my ensemble clicked event. And just before I call Calculate result, I'm going to reduce the number of tens. So I'm gonna do that by just applying it to a new variable. So I'll just go, The number of tens left is equal to number of tens left minus one. Ok? Pretty much. That's the logic on going to use here. And then obviously, at the end of each click, I'll just set that set number of tens left to that new number of turns left. So that's handling the state part. The second part of this is now we're going to have to pass in the number of turns left into our calculator when a function. So I'm going to pass it as the second parameter, yeah, like psi. So I'll just copy this and paste it and save that. And now I'm going to go over to my calculator winner function and handle the logic in here. So number of turns left. And then just after we try and establish a winner here. So this for loop is the logic for that. I'm going to now come down and have an if condition. And all it's going to be is if we have no turns left. So I'm going to say that based on the number of tens left is 0, then we return a result. Alright? So we have a result. So has result is going to be equal to true. However, we don't have a winner. So that will be undefined. And we don't have a winning combination. That will just be an empty array. And this should be pretty much all we need to do to establish a time. So let's go and test that out. So we'll come over to my game and we'll now go, X. X will go over here, are down there. And we'll put an x here. I'll put the out here, and then finally an X. And now we can say that we get that game over screen. Now we don't have the status in the box yet, but that's what we're going to handle in the very next video. So let's quickly make sure that when still work. So we'll get x and then x, say we still get it on a when. We'll just try for all this time, just to be sure. Yep. So everything seems to working the way that we wanted, including ties. So now what we wanna do is just focus on that yellow box that we just saw. So if I get a win here, we want to be able to establish the status in here. Okay? So that's what we'll focus on next. 23. Showing the game's result: So we've got the gain now operating where it can determine a winner or it can determine a tie. And I will show you a result modal. The problem is if I do something like psi, when again, it doesn't say that X12 moment, nor does it say if we don't get them winner society, I do something like this. Like that. We don't have a message saying it's a tie EDA, right? So that's what we're going to be handling in this video, is gonna come out into my result model. And I'm going to create a new constant here. And I'm just going to call it message. And what this message is going to do is it's going to put a special message inside the span element down here. So if I save this right now, it's not going to break anything, but it's also not going to do anything. I'll just click around until we get a tie. We say we still get no message. So instead of being empty, I'm going to set it to if there is a prompts dot winner that exists and it has a value that I'm going to set it to a string that will say when a is. And then I'll put in prop stop winner. Otherwise, if it's not that, then I'm going to set it to a string that says it is a time, and that's it. Alright? So if I run it as it is right now, so I'll just even establish a winner here. Well, it's still going to say it is a tie. And the reason why it says it is a tie and not x wins is because we're not Parsi in this winner, right? So there's a couple of things we need to do in our game. First, we need to keep track of a winner on each turn, just in case we do get a winner, right? So I'm going to come in and set a new one here called Winner and set winner, like so. And then let's go, you state. And by default it's going to be undefined. So I'm not going to set a parameter here, okay? I'm then going to set when again here. So when basically just after, say the game is over, or in fact, I can do a right at the very bottom and just go set winner. And this will be equal to calc result dot went up. Okay? So remember to calculate when it returns back a property of winner whenever we actually do calculate a winner. So that's this part here. And then in other circumstances, it returns undefined. So it's going to be undefined until we find a winning combination two, which then it will have a value. So that's what, that's sitting there. And then basically, once I do that because that's still not going to be everything we need, right? Even if we still do this and we get a win, It's still going to say it is a tie. And that's because we still need to pass down to the modal, the actual winner. So I'm gonna go winner is equal to that new state variable winner. Now if I've done this right, hopefully, if we have a winning combination, will say when a is x. Cool. If I refresh. And now we may, Oh, the winner this time. Now it says when a is our great. And then we'll check for a tie just one more time. And that was silly of me. I shouldn't have done that. We'll go this way. Put x here, who are there, and then x. Now we have a tie. Okay? So there's now working exactly the way we want it to. Cool. So now we've got a message in indicating what has happened in our game and why the game has been deemed over, right? So there's a couple more things that we need to handle before we're done here. The first one is, well, the winning combination is no longer highlighting even when there is a win. So I don't know if you know, sat lately, but we're not handling this winning combination thing anymore. It's now broken again. We need to fix this again, and then we need to handle this Start New Game button down here. So in the next video, I will focus on the winning combination. And then we'll worry about the button after that. 24. Fixing the Winning Combinations: So we're almost time, which has got a couple more things we need to work on before our game is completing. One of them is to fix this bug where we no longer showed the winning combinations even when we have a win. So the reason why that's happened is actually for two reasons. One is a bug that I didn't intend to do in the winner calculator. I accidentally left in this when a matrix i 0, when I'm meant when he ranges, says the first thing I need to fix. Now hopefully I've addressed that bug in the actual video where I actually had it occur. When I wrote that The first time. Hopefully I've left you a message indicating that wrong. If I haven't, Well, you can fix it now. Alright, so that's the first part that I want to quickly address. The next bug is around the fact that this winning combinations variable here is not in state. And that's why whenever really updating it and therefore passing it to the board properly. So I'm going to quickly put this in state. So we go winning combination and then set winning combination is equal to U state. And by default it will be an empty array. Now, all we need to do here is come at the bottom of this and go set winning combination, calc result, winning combination. Because that's what's coming back from our calculate when a function is an object with a winning combination property set on it. If we take a quick look at when a calculator and calculate when a function. We can see it set here. Alright, so that's when I discovered it actually had the wrong value for the second parameter. Instead of a beam when he matrix, it needs to be winning ranges. So now that those two things are imply, we should be able to say the winning combination again highlighted. So if I get a win, there it is. Cool. Let's try. Oh, this time we'll go a different direction. There it is. Okay. And then if we go with the diagonal when his time there it is. Cool. So that is the last major bug that we have left in our game. So that leaves us with one more thing left to do. And that's wire up that started New Game button to start a brand new guy. We'll look at that in the next video. 25. Starting a new game: So I want to be able to play this game again and again and again. And I want to do it by just clicking on the Start New Game button. I don't want to have to come up and click refresh every time I want to start a new game. So to do that, I'm getting into y and event handler for this button. And then I'm going to create a function inside of this game that will reset all the state variables back to their defaults. So the first thing I'm gonna do is come over to result module.js and solid here, where I have the button down the bottom. I'm just going to add a new line. Add, add an onclick event handler like sun. And what I'm going to make it equal to is props dot on new game clicked. Okay? So that's what I'm going to call it. So that's what I'm going to pass to this result modal. So I'm going to come up to my main.js and I'm going to come down to where my result modal is. And here I'm going to add on the game clicked. And I'm going to set it to, well, I'm going to set it to my restart game. So I haven't grade dysfunction yet. I'm gonna come up and create this function. So let's do that. So just above the ansel click function, I'm going to create a new function here by using a variable set to an error function. Like sorry. And then inside this function, all I have to do is just set all of these values that we said in our click event handler back to the default values. So what they are here at the top. So if you want to, at this point, say, you want to set this as a variable, like a static variable at the top of the compartment, that's up to you. But for now, I'm just going to paste them in like sun. So is next will be set to true. I'm going to say, is gamma over, obviously to false as the game should not be over. I'm going to set the number of turns back to nine. I'm gonna set winner to undefined because we don't have a winner. And that's because it's a new game. And then lastly, the winning combination will be an empty array because we don't have a winning combination as of yet. Now if I do all this and apply it again, so let's just play it for a winner. Now I can come down to the Start New Game button, click on it, and it looks like we're starting all over again. I can then replay this game any number of times, get another win. So we've got a winning combination. Start a new game. Then maybe this time I make o when, then we started another game and then will finally go for a draw, right? So let's go for a draw. Or tires should say. It says it is a tight. So we can just start a new game again. And we can just do this over and over and over. So that is it. That is how you can make your own two-player local play, tic-tac-toe. So congratulations, this is now I knew React app that you can add to your React portfolio, alter your web development portfolio overall, whatever you would like to do. Happy for anyone to use it. And I'm glad that you're able to learn through me. And I hope to see you all in the future.