Create a TicTacToe in Blazor
6K views
Mar 16, 2024
This step-by-step guide is just for you. (No Prior Blazor Experience Needed)
View Video Transcript
0:00
Good day people, today we have something interesting in the house
0:04
Today we are going to create a tic-tac-toe game in Blazor. Well I am using Visual Studio 2022, you can use Visual Studio code either is fine
0:16
Whichever applications or IDE you are using, select next, select new, then select Blazor WebAssembly app. Click on next, leave the settings to default
0:29
and click continue. This is where you give the name of the application
0:34
which is tic-tac-toe game in our scenario. Now leave the location to the default and
0:41
click on create. What this does, it will create a default Blazor WebAssembly application for you
0:49
And it has. Alright, now let's see if this application runs or not. Let me
0:54
run this application and it's compiling the code, loading the application and voila, you have the application running. Okay, now there is another way. So, usually what I do
1:12
I run the .NET watch. What it does, every time you make changes in HTML and CSS
1:18
it reruns the application in the browser rather than you manually doing it
1:23
So, and in order to do that, all you have to do, get the path of the root directory
1:30
cd to that root directory and run the command called .NET watch run. Watch what happens
1:39
Now it's taking control of the browser and it does the magic. We don't have to worry about
1:43
anything. Alright, what do we need? We need a component to have our application running on
1:51
or we need a new component where we are going to write our HTML code, HTML and C sharp and for that
1:59
just select a razor component, give it a name. Let's call it a board because this is a board
2:04
of the game, right? Click on create. It has created the component. Now, what do we need in
2:11
this component? Tic-tac-toe game. The game is divided into nine different sections, right
2:17
Nine different boxes, if you will, and each row has three boxes and each row, that means each
2:23
row has three columns and there are three different rows of that size. So for that, what we need? We
2:29
need one div. The first div is the outer container, right? Now this is where all the nine boxes are
2:36
going to reside. So let's create the first div and inside that div, we are now going to divide the
2:41
page into nine different sections and how do we do that? Have two for loops. First for loop
2:48
integer row is equal to zero, then row less than three, then row plus plus. Now that we have created
2:56
three rows, let's create three columns for each of those rows. So integer column is equal to zero
3:03
column less than three and column plus plus. Now inside both of this for loop, we are going to add
3:10
the div which will be created nine times. Okay, now let's give some CSS classes name. Since this
3:18
div represents itself, let's give the name cell and outer div, let's give the name
3:29
container. It sounds nice. Okay, now let me also align this code. Okay, now that we have code is
3:39
ready, we need to call this component at the beginning. So for that, remove all this code
3:46
go to index.razor, remove all the unnecessary code and call our newly added component. So what it does
3:52
every time application runs, rather than running that all code, it will now run our component
3:58
which you can see this is now running. Since we don't have anything, it's not showing anything
4:02
What do we need next? We need CSS, right? So click add new file, select CSS. While naming
4:11
you have to give the name of the razor file, followed by the razor syntax followed by the CSS
4:18
What it does, it creates a component specific CSS, which is isolated just for that component
4:25
So this will be this CSS will represent the board component. Okay, what do we need in our
4:31
board razor? First, we had container. Okay. So let's create a class for container dot container
4:41
So a container, let's first give height and width. So height, I'm giving let's call it 31rem
4:48
sound good. So what rem means each rem represent the font size of the root element. So whatever
4:55
the root element of HTML component is, or HTML tag is, that is, that is 31 times of that size
5:02
will be our container's height. So in this case, by default, I guess HTML has 16 pixels. So 16
5:10
into 31, that would be the size of our entire component, right? So that's height. Now let's
5:15
give width, let's keep the width same as height. So 31rem sound good. Once you have height and
5:23
width given now we are now now we want to divide the page into nine sections, which is a grid. So
5:28
for that, we need to use a property called grid. And since we're divide creating three rows
5:33
so that would be grid dot template, if I'm not wrong, and we are going to create rows
5:40
three rows, so three and each row will have let's take 10rem. So size of 10rem, right
5:48
then we need to create a column three columns for each row. So again, select grid template columns
5:55
and repeat that for three times and give size of 10rem. And now we need to also give the gap
6:04
between each of the column, right? So let's give the gap of five pixels should do it, I guess
6:12
Alright, that you have nothing on the screen because we are yet to create a cell
6:20
So create go ahead and create that the height and width for the cell would be the parent height and
6:24
width. So just say 100% that will take parent's height and width. Then let's give some color
6:37
So background. Or now let's give green because I want to see that color on the screen
6:47
Okay, still nothing is there. What are we missing here? Let me see
6:54
Let's increase the size of the REM because I have the feeling it might not fit inside
7:00
No, that's not it. Something else is playing around here. Okay, let me stop dotnet watch. And let me see if manually running will do something for us
7:20
Oh, I don't know what's the problem with dotnet watch, but it's technically running if I manually run it. Now if I stop this
7:28
manual running, and then the dotnet watch again, it might reflect the changes. So most probably I
7:34
have seen this in a blazer, there's a cache problem loading while loading the page. So you have to
7:38
clean the cache and then it again, it shows up. And technically dotnet watch is not reflecting
7:43
that. That's why I had to manually stop it and run it. But yeah, we have the board ready
7:47
Beautiful. Besides the board, what do we need? We need the click action every time you click on
7:52
every time you click on the cell something's supposed to happen, right? This takes us to the
7:57
part of part where the presentation logic or C sharp logic comes in. Let's go ahead and add the
8:04
class code behind if you will. Empty class like again, while naming it, give the name of the
8:12
component, then followed by razor followed by CS. So it will create the C sharp class
8:19
Beneath the component. So this is a class is nothing but the partial class of the component
8:25
Just go ahead and add the word partial. And there you go. Simple. Okay, so all of our C
8:31
shop logic are going to go inside this class. Okay, what do we need, we need to first represent
8:38
this board programmatically. So every time user clicks, start playing the game x and
8:43
x and O's supposed to h10 or supposed to be stored somewhere. So that variable we need
8:50
Let's add one region. Let's call it variables tools. Let's say game tools. Okay, to represent board programmatically, we need character array
9:07
So let's go ahead and carry it to the character array. So let's go ahead and carry it to the character array, because three rows with three columns. So
9:18
let's go ahead and do that. So this is first row. Same way, we are going to have second and third
9:32
Second row and third row. Okay, now that we have created the board, we need to, we need to every
9:45
time you click on cell something supposed to happen. So we need on click event here. So on click
9:52
on click, let's call it make move method. And inside this method, we are going to pass
10:03
the row and the column. Now let's go ahead and create the same method here in code behind private
10:12
Let's create this new task and make move. So this would be a sink integer row, because we were passing two parameters, right integer row
10:28
and integer column. So what is the logic behind the parameters, you can click on any cell, right
10:33
So that's how when we pass a row and column number as a parameter, that's how method knows which
10:40
cell on the UI has been clicked. We need to also need a character or symbol to represent x and o's
10:46
right. So let's go ahead and do that. Here, let me add h5. And this will represent the character
11:00
So here, let's keep it simple for now. Say character player, whichever player is, and let's give it x
11:19
So every time user clicks on the board, we are going to replace with this character. So row
11:26
comma column is equal to player. And just show this player in here inside h5. So go ahead and say
11:38
player. Okay, let's if something happens, or we get some exception. Oh, now you can see x xx on x xx on every single cell. But what we want when you click on the cell
11:54
you're supposed to show the x. So rather than showing player, we are now going to show when
12:01
you click on a method, we are updating the board. So what we are going to do, we are just going to
12:06
show that board here. So that cell here, every time you click on the cell, the cell is going to
12:14
get update and we are just showing referencing same cell to show it on the UI. Now let's see how
12:19
that looks. Getting exception, let's see what exception says. Index out of bounds. So
12:34
that may be because of this, let me do something here. Integer i will hold the value of row
12:42
integer j will hold the value of column. And then we are here going to show i and j
12:52
rather than showing row and column. Let's see if this solves the issue
13:05
Hmm, it did not. So let me also pass same i and j from here as well
13:13
Build it again, run that again. Okay, now it works. As you can see now every time I'm clicking somewhere, it's updating the value
13:25
of x. Okay, now let's give some CSS to this character so it would look better than whatever
13:31
it is looking, however it is looking now. Okay, so for that we need to add a CSS class
13:39
Let's call it symbol since it is a symbol. Okay. Sorry. Okay, we need to align the symbol in the center. So that would be text align
13:58
center. We also need to align content in the center. So this will align horizontal vertically
14:07
since we are using the grid. And let's give some font family, font size
14:15
Font size. Roboto will do it or even Arial will do it. Then give some font size
14:35
Let's call it 700. Oh, sorry, font size. Let's say or do we want to assign to the media. Let's see how that looks
14:53
Okay, now the font size has not updated. I need to give the font weight as well
14:59
Let's give the font weight. 700 will do it and full color. So let's give color to be white
15:09
Okay, now it is white. So let's give the size to the three times or two times of REM
15:17
Then that will look better. Okay, now it's looking better. So let's give it five times of REM
15:26
Okay, now we are talking. 7 REM. Okay, now we are talking. Okay, this is look good
15:35
One time it will be the turn of X and the next time it will return of O. So let's bring the
15:40
character O into the picture. This will be fairly easy to do. Once we update the board with the
15:45
symbol, let's say symbol was X. Okay, now the next term will be O. So the next time the player would
15:52
be, if current player was let's say X, then the next turn would be O's. Else it will be X's
16:10
I hope this works. X, O, there you go. X, O, X, O, X, O. All right, next what we need to see
16:21
who won the game. We need to see if person won the game or not. And I guess there are only nine
16:26
combination. So let's just code that out. For that, we need to create a variable to store winning
16:33
combination. So that would be let's create a list of list of integers. I'll explain you that in a
16:41
minute. What does this entire data structure mean? Winning combos equal to let's call it new
16:52
Okay, now how many winning combination do we have? In order to win Tic-Tac-Toe, there are only eight
16:57
possible winning combination. So 0, 0, that means first cell, 0, 1, second cell and 0, 2, the third
17:06
cell. That's winning one, that's one winning combination. Same way, let's have all three
17:12
rows first, and then we will take care of the columns and the diagonals. Okay, so that now
17:18
second row would be 1, 0, 1, 0, 1, 1 and 1, 2. The third row would be 2, 0, 2, 1 and 2, 2
17:30
Let's first add these values. So that would be new list of integer and new integer
17:40
That would be 0 and 1. Okay, so that is why this data structure because each cell represents by
17:51
row and column. That's why integer array and which is then there are three different cells
17:57
That's why those are in the list and that list is part of all the winning combination. So list of
18:02
list of cell numbers. That's how. Okay, now again new integer. Then second value is 0, 0 and 1 and last one would be new integer
18:22
0 and 2. So I'm just going to copy this and paste it two more times
18:29
The second is 1 and 0. Second row, so 1 and 0, 1 and 1 and 1 and 2. The third row
18:41
2, 1, sorry, 2, 0. So this would be also 0, 0. My bad. 2, 0, 2, 1 and 2, 2. So that's rows
18:52
Then we have three columns as well, right? So column you can see here only. This is the first
18:57
column, second column, third column. So just copy this. Paste it. The first column is 0, 0
19:04
then 1, 0, then 1, 0 and then last one is 2, 0. Okay, then 0, 1
19:16
then 1, 1. This is correct. And 2, 1. Then last is 0, 2
19:34
1, 2. And last one is 2, 2. Okay. And the diagonals as well, right? So 0, 0, 1, 1, 2, 2. That's how
19:46
And 0, 2, 1, 1 and 2, 0. That's how. So let's add those two as well
19:56
So that would be 0, 0 and 1, 1 and 2, 2. Okay. And 0, 2 and 1, 1 and 2, 0. All right
20:07
So we have our winning combination in the house. Let's use this to compare and see at the end if
20:14
someone has won the game or the game has ended in a tie. Okay, so we are back to make move method
20:22
Here we are going to loop through each value of the winning combination. Okay. Now, so winning
20:31
combination holds these three values, right? Okay. Now fetch value from each of the cell
20:37
So for that, that we are storing the value of the each of the cell in integer array
20:44
So let's call it first cell and say item from the first, item from the first row. Okay. Or item from
20:54
the first, first item technically. Okay. Same way we need to have the value of each of the cell
21:03
So let's call it second. Let's call it third. So what we are doing here is
21:13
item of 1 and item of 2. So what we are doing here is this will store 0 and 1, sorry, 0 and 0
21:22
This will store 0 and 1. And at the end, this will simply store 0 and 2. So we are storing
21:30
the value of each of the cell while iterating through each of the item in this list. Okay
21:37
Once we have the value of the cells, what we need to check, we need to first validate
21:42
that each cell at least has the value should not be empty. If it is empty, then simply return
21:47
right? So if first, first, so inside a board, the first, or yeah, the first cell
22:01
since we're updating the board, so first 0th item, so that means the 0th cell, comma first
22:10
first cell, so 0 and 1. So if this, if board of this cell, that means first cell is double equal
22:19
to empty, or same way we are going to follow this, or second cell, or third cell. So we want
22:39
to make sure each cell has the value. If any of this is empty, then continue. Okay. Else, that
22:48
means it has a symbol either X or O. So I'm just going to copy this. If board of first is double
23:00
equal to, is double equal to second, and the second, and the second, so what I'm checking
23:13
here, if the first cell value, if first cell has X is equal to the second X. So this is comparing
23:20
to the second X. And the second X, the second X is double equal to the third one. So let me
23:29
hold on. Do something like this, like this below, so it will make more sense
23:42
Okay. So the first cell is equal to second cell, and the second cell equal to third cell. If that
23:48
is met, that means at least O or X has won the game. Now if any of the player has won the game
23:55
we are going to show the message on the pop-up that player has won the game. And for that
24:00
we can use simple JavaScript. And in order to use the JavaScript, just inject ijs runtime
24:08
let's call it js, and use that. Let me stop the application from running
24:14
Let's store our result into Boolean variable. So js dot, js dot async, since you are expecting a Boolean, and this is a confirm box, so confirm
24:31
and we are saying the player has won. This should do it. Also say await
24:45
since it is JavaScript explicitly being called. Moment of truth, guys, moment of truth
24:50
Oh, exception, not bad. That means we at least got into the condition, we just broke something
25:03
Confirm was undefined, okay. Maybe the C was small. Let me, ah, there you go. Okay, so, oh my god. So we are interchanging the variable, and then we are
25:27
updating the value. So we need to come back and show the actual winner vote. Okay, so rather than
25:32
showing player, so that happened because we are interchanging player symbol here. So let's just
25:37
show whatever the value of the board is, and maybe that will work. So let's run this
25:50
x, x, x won. Beautiful. Let's refresh this. Oh, again, I made sure that x is winning. Let me make sure the o is winning
26:06
and o won. All right, nice. Now what we need to do, once any of the player has been won
26:11
we need to clear out the game or board so that next game could start, right? So let's do that
26:18
Simple. Let me come back here. Now some final touches. So technically, we don't even need this
26:25
boolean variable, but we are going to leave as it is. What we want to do here, we want to reset the
26:30
game, right? So let's create a method for that first to reset the board. So we'll call it private
26:37
void. Let's call it reset game. So all we have to do is go through each board, each cell of the board and replace that with empty
26:54
replace that with empty characters. So integer i is equal to zero
26:58
i is less than equal to three, and i plus plus. That is rows, that are your rows
27:06
Sorry, I made some mistake. Okay. Now for integer j is equal to zero, j is less than three, and j plus plus. Now just say board of i
27:25
and j is equal to empty character. This will reset the board
27:30
Okay. And once the game has been finished, winner has been declared, reset the board
27:37
Let's see how, if this works or not. Let me run this
27:43
Okay. X, X and X, X has won. I say, okay. And board has reset. Okay. Now only one condition
27:51
is left. The game could be resulting to winning either O wins or X wins, but it could also be tie
27:57
right? So let's write the logic for that as well. So in order to write the logic for tie
28:04
I'm going to copy the same method, paste it here and is game is board empty
28:16
So what I'm going to do, I'm going to check if there's a cell that is still empty, even after
28:23
game has been finished. Okay. So if there are no cells empty and game has been finished
28:27
that means no one won. Right. So I'm just going to create one Boolean variable here
28:34
Say result is equal to true, meaning the game was empty, but I'm going to go through each of
28:42
this cell and I'm going to say, check if my board value is double equal to empty
28:49
If it is empty, then return. So if there is an empty, that means board is not empty. So return
28:58
false. Else return result. I don't even need to store the result here. Simply say return
29:08
true. I don't even need this. I don't know why I created this. And that means we don't need to
29:16
store this one as well. We need to store it in the Boolean as well. Okay. Now, if the game has
29:22
finished, that means once you come out of each loop, game has been finished. We're going to
29:27
check if what we are saying is board is empty, is board is empty. Then the game is ended up in
29:39
the tie. Then let's just simply show the game that game has been ended up into a tie. Confirm
29:48
message and just say game tied. You can use beautiful CSS and everything. I will link the
29:59
blog in the description where you can read how to have, you know, beautiful CSS, which will give
30:05
you a nice pop up to show rather than this inbuilt pop-ups or confirm boxes. Okay. Let's tie this
30:11
game. Post turn. Okay. Game tied. Beautiful. And oh, after the game has been tied, we again has
30:22
to reset the game for next. Oh, new and new thing just coming up. So if game was tied, then again
30:29
reset the game. Now, this is the final thing which was left here. X
30:43
Oh, X won't because I just added X there. Okay. Let's make sure O wins this time
30:49
Okay. O wins. Now let's tie the game. We actually saw the game being tied
30:54
So we don't have to, but anyway. And game tied. Beautiful. Now let me just add a couple of more
31:01
CSS, change some CSS here and there, and I'll show you the final version of the game. I made
31:06
some modification into CSS and final version is looking like this. Let me show you how it works
31:12
So first turn is X. So let's let X win. Beautiful. You can see the cat in the background
31:19
Now, now this is second turn. This is O's turn. Let the O win. And this time let's tie the game
31:30
Oh, my bad. Let me tie the game. Okay. Once the game has been tied, I will link down this code down in the description. You can
31:42
start playing around and you know, do whatever you want. It's free. What I will do, I will also
31:49
in next video, we will create the AI version of this. Here, if you go to my website, down to the
31:54
portfolio and here under tic-tac-toe, you will find the version which is played by the AI. So
32:04
here the AI plays the game. So we will try to generate the AI for the same game. As you can see
32:11
I'm doing nothing. It's the AI who is playing the game. Either AI wins the game or AI ties the
32:17
game, but it never loses. Next time, we'll see that how to design that with MinMax algorithm
32:22
Thank you so much for joining me and I'll see you next time. Bye-bye
#Educational Games
#Miniatures & Wargaming
#Software
#Video Game Development