Build a Real-Time App with Blazor & SignalR in .NET 8 🔥

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey friends Patrick here and this video that you're going to see here is actually part of the dot and Web Academy it is a challenge in there meaning I wanted the students to build a tic tac toe game with Blazer and Signal R and this here is the result this is already the end result of a version of the game that I made so as you can see here I have two windows open and we can enter a name here and uh name of the room that you're going to to create and then as you can see here the uh clients are connected to one Hub of signal R I know busws already you will learn what all that is in a couple of minutes and then here we can enter another name like Spider-Man for instance and we can see that there's a new room that we can join and now the creator of the room can start the game I know you don't see the second board here but when I enter or click on this cell here you see that it changes here as well and same thing here it's Spider-Man's turn and now we see what is actually happening and when we are done we can see that the game is over winner is x in that case Batman so this is the end result that we going to build in the next couple of well hours so I hope you like it if so don't forget to hit the like button maybe subscribe to my channel and don't forget to check out theet Web Academy link is in the video description and now enjoy the challenge and building a tic tac toe game with blazer web assambly and a and Signal R hey friends Patrick here and welcome to my solution of the very first challenge the tic tac toe game with blazer web assembly in my case and also signal R so let's already create the project I already told you I want to use Blazer web assembly so for that we choose the Blazer web app template here let me give this a creative name like Blazer tick Tech toe and we have hit next Target framework. net8 no authentication but again interactive random mode then in this case would be web assembly we could also choose Auto but uh I really want to use web assembly here because regarding a signal R it does make sense actually to use web assembly because then we will install the client package of signal R and you will see how you can communicate with the server so with a signal R Hub to be more precise but again you will see that in the next couple of lectures Now interactivity location per page component I just leave it at that because I really like it like that and uh include sample Pages why not and while this thing is creating on my other screen there it is I want to tell you short disclaimer this thing this application that we're going to build of course does not claim to be complete so you can do a lot more with that of course but I think it really gives you a great Foundation regarding signal R and communicating then with the server from a web assembly client application in this case because it's not only about an example chat application for instance where you have like two events for instance you see it's all about events or it's a lot about events with signal R you will or we will together build or make use of groups because we want to build or create rooms my idea here is that when a user connects or accesses our page our application then the user will be directly connected to the signal R hop and then the user has the option to either create a new room or the user will see uh a list of rooms and then join one of these rooms and these rooms then will be groups in Signal R jargon let's say all right so again one step after another this is a little introduction and the very first thing already I want to create is the Hub this is a game so let's create a Game Hub and for that we uh create a new folder here on our server application or project rather and uh again we call this hubs and here now we add uh a new item and this is then the Game Hub all right there it is and this thing now inherits from Hub and with control and period yet you will see the suggestion Microsoft ASP core signal are so this is the uh uh using directive we have to add the reference we need and as you can see you don't have to insall something right in the past there well it's some time ago but you had to install something but not here signal R is there out of the box when you create this kind of application choosing this project template the Blazer web app template and regarding the client we will have to install a client new get package but that's everything we have to install regarding signal R so you see there's a lot uh built in Signal R stuff already now what's next signal R is all about events in essence so what we will have is we will have an unconnected event for instance so when the user connects to our application something should happen then we can add custom events of course meaning when a user creates a room something should happen when a user joins the room something should happen and then of course later then the uh moves that the users will be able to make adding an X or an O to the uh to the board in a sense and the very first thing that I want to implement is the onconnected event this method there I want to do something and when this is done I will already I want to already show you what happens to the application with a little console right line of course so you see kind of how this works all right so first again our on connected async method for that we write public overwrite and then already we get the suggestion here onconnected async you already see the oncon on disconnected async and again I told you this application is not complete this thing we will not Implement all right of course I think you will know what to do when you implemented all the other stuff and followed this course but uh in my case I didn't so this is not complete but again I'm sure on disconnect it's up to you what you want to do you can remove a room for instance you can write a message in the application on the client whatever you want to do there you can do it here on disconnected async but now first on connected async that's the one and the only thing I want to do here first is console right line and then I want to call these uh guys here and girls that connect these are players so I would say player with ID and then this is already some of the Magic in Signal R each user in our case player has a unique ID and we can get to that ID like that so first string interpolation here and then it's context because we have the Hub so you can see there gets or sets The Hub caller context so the caller is the user that was just connected here and then connection ID all right and then connected so player with ID context connection ID connected this also means we will make use of that when a user still has his or her session then the connection ID will also still be the same this means with the help of the connection ID we can differentiate the users and see whose users turn it is for instance when playing the game all right hope this makes already sense so connection ID very very important and to see the connection ID you can actually do uh one thing we have to already add the client at a page for instance or we just uh remove the home page and so on and only use one single page here on the client and then connect to the signal our Hub and then make sure that we see this little message here so I'd say let's already move on with the client implementations in the next lecture all right now for the client I told you already we need another package so here in the dependencies we will see this one and we go to manage new get packages in the client project we go to browse and then for instance enter signal our client that's the one and it's not signal our common it is Microsoft asut core signal our clients currently version 8.0.2 44 million downloads this definitely is the one and with that we will be able to make use of the so-called Hub connection Builder and with that then we will again be able to connect to our signal rhub so let's close that and then I want to well clean up a little bit because we have the uh example stuff here regarding the components for instance you see the layout main layout the NV menu and also then the homepage and what I like to do is create only one page for now which will be the lobby so we add a new razor component that is our lobby here and I was thinking about using the uh page route lobby as well but actually this is the only page that I want the user to go so what I decided then was to Simply steal this route here put it there like that all right so here we have our lobby now and then we can actually remove the homepage we can remove the counter page as well and then also weather nothing we need nav menu we don't need that and then regarding the main layout you only thing I want to do is actually I remove the sidebar here and only use the body here so nothing will be there actually apart from here the lobby text so let's try that real quick we start the application and see if cleaning up actually worked yep there we are great right so here we only have the lobby now let's also already open the console because we will definitely make use of that and this is our result you probably already noticed that we don't see anything regarding web assembly so no console output that web assembly is used well that's because we did not make use of the web assembly render mode for now but that's what we will definitely do next and also we have to again add some signal our boiler plate stuff before we can actually communicate to our Game Hub so let's first start with the rendom mods all right so here now again we have ADD random modes maybe you already know that by now and also maybe you already know about this little Pitfall or trap with net a because but if I would now say random mode interactive web assembly then this thing would be rendered Twice first on the server and then also on the client the problem with that is that when we write our uninitialized async method here and we will connect to our gam Hub then we will see an output that is not nice because we will actually see two times that the player with a certain ID has been connected or has connected to the uh Game Hub and this is not what we want so we actually have to disable pre-rendering to only connect once and render this only on the client but I will first show you how or what the behavior is that we don't want and after that then the actual behavior that we want so for now this is already web assembly when we now restart this and there it is it's rebuilding this is what I was talking about now we see net loaded 5 megabytes this is only in development bear with me here all right I know this is big but when you build this actually and deploy to Azure for instance and this is way smaller but as you can see now this is the web assembly stuff that you typically see in the console and now regarding the uh connection to our gamehub first little bit of boilerplate code here in the program Cs on the server so for instance if you're uh if you don't want to use Blazer here the Blazer web app template you can also just build a web API for instance or use the web API template it's pretty much the same stuff so now in the uh program Cs and by the way I of course I prepared this a little so I'm uh looking at the other screen and here now first thing is to use uh the uh signal services so let's add this one here Builder Services add signal r as you can see add signal R services to the specified I service collection great stuff and then there's only one additional uh thing and this is this is is new haven't seen that before actually because before we saw the uh uh counter here the counter page that I now deleted but now they decided to use the Imports which does make sense because you typically won't delete the Imports file so it's a bit more safer because for instance we we need the uh assembly and for instance if you delete the counter page now then we wouldn't be able to use Blazer web assembly I think you learned this already in the Blazer jumpstart course in the Web Academy but now they changed it haven't really checked that out but still interesting stuff anyways uh what we have to add here no not really well it doesn't really matter where you add it but you can add it here uh is let's call it the end point for the uh for the game hub for our signal R Hub so here we have to make sure that this thing is registered with map Hub and this is not the game hub this is our beautiful class and and here now we also have to specify the route for that let's just call that gamehub and with that we are done and of course this is not known in the dictionary here of visual studio so this is the boiler plate code we need to be able to connect the client to the server and now in the server again I already told you about our on list async so protected override and then uninitialized async that's the one and now don't forget the async keyword we actually don't need the base method here but what we want to do is now again start a connection to our hub for that we add a little member here or a little variable The Hub connection could be null so now Hub connection is the name we use this using directive and move that to our import razor file that's the one perfect and now here first we say Hub connection is new Hub connection Builder actually that's the one and here now we can specify the URL which is the gamehub just enter that on the server right so with URL and then here we can just say navigation manager which is not injected actually so we have to inject that one and then to Absolute URL and then Dash not Dash slash and then Game Hub and then here we call build so with that we have our Hub connection and here real quick at inject navigation manager navigation manager and then this method should be known hopefully nope give me a sec that's the one all right so not URL URI it is and then we just call a wait that's why we need the ASN keyboard and the task return type Hub connection and then start async and that's everything with that this is the complete boiler plate to connect to your signal R Hub and then you're free to do whatever you want to do with that so here now we restart the application you won't see a big change here that's what you can see but you know see that this is in the console so player with ID so so connected player with ID so so connected Let me refresh this and again two connections maybe you can you see it two connections so every time it is first rendered on the server and then on the client so to change that because I really only want to use the client here we can can just or we have to it's the way. net8 we have to create a new instance of the random mode so new interactive web assembly random mode and then here as you can actually see there's a second way to uh to create a new instance of the interactive web assembly render mode and here we can set pre-rendering to true or to false by default this is true as you can see here default value is true and we say now nope don't want that that's it now let's restart this one more time and also open the console there it is and you see now only one line player with ID zone so connected let's try that one more time and here it is all right so now we have our connection ready and with that we can actually already start with some events for instance so let's play around with that next all right now what I want to do when a player connects to our game I first want to send the current available rooms to that new player and for that we need some more entities now we won't store anything in the database in this course but still let's create a separate a project for that so that the server and the client project both can make use of them and well maybe we can have the is a tiny bit cleaner of course this is no clean architecture not the best architecture at all I already told you this is not complete and maybe not always the best practice but my goal with this course and with this challenge is for you to understand signal R more together with web assembly Blazer web assembly and also to be able to do a bit more with signal R regarding the groups for instance so that you understand what's the connection ID what can I do with the groups how can I put a user into a group and only send messages to a specific group stuff like that so anyways we have our server project here we have our client project now let's create another one so we add a new project which is only a class Library we next we call this now Blazer T tag toe shared actually of course don8 it is don't need that class here all right but now again I told you I want to create rooms so then send these rooms to the player but additionally we will have two more entities in which or models let's say the uh Game Room the player and also the actual tic tac toe game with the board and the the current uh the uh different states like whose turn it is and who the winner is or maybe it's currently draw and so on so this is what we're going to do so let's create these new items real quick first the game room let's make this public then we will also have the uh player all right also public of course and then we will also have new item which is the tick Tech toe game all right so this as well these are the ones and now we will add more to them of course later but for now the these are the basics and now back to the server and the uh the game hop down where is it here and what I want to do again first we have a list of rooms so here now private static read only list of game rooms need another reference here come on that's the one and we call this rooms and this is now first simply a new list of rooms so this would be an mty room list and now what I want to do I actually want to send these rooms to the player that was just connecting so how would I do that again an asynchronous method and here now I can call clients and these are you don't see it here now you see it gets or sets an object that can be used to invoke methods on the clients connected to this Hub so all clients you can do something with all all the clients here but you can also say I just want the caller and this gets a proxy as you can see there that can be used to invoke on the calling client and receive results so this means that only the user that just connected will receive the following with the send async method and in Signal R maybe you already saw my uh signal R chat tutorials on on YouTube as you can see here the very first thing that you put here where in in the send Asing method is a string and this is the way to know what actually happened there so when our Hub is sending something to a client then the client can listen to a certain method as it says here string method and our method here is now simp rooms and then we can add whatever we want to add here a cancellation token or some objects for instance right and as many as you want actually and here again what I want to do is I want to send the rooms there and actually I want to order them already so maybe we can add something already to the game room that would be the following first thing is an ID but this will be a string because I want to use a guid for that so here now the room ID all right and then the string room name all right let's leave it at that by the way why a string well we uh will use Goods again because with a good I can make sure that these room IDs are really unique probability is really high that they are unique and for instance if you would use an integer here and increment it manually maybe this wouldn't work when a room will be removed because no user is there anymore could just be the case or the probability is higher that we will have the same ID for a room so that's why a good will make more sense here but this is done when we actually create a new room anyways these are already some properties of the game room and when we now go back I can order them so order buy and then for the room room name all right that way we can make sure that they are ordered all the time all right and I think actually we don't need that so let's remove it okay so let's save that now and with that we are able to go back to the client and then react to this method here to that call so let's do that next real quick so here now in the lobby we already have our up connection but here now I already told you it's all about events so now here we can add handlers or listeners you name it that will do something when uh the event in the end is fired so let's add a Handler here so that would be with uh it's done with Hub connection and then on and here's the function you can now see it actually says register a Handler that will be invoked when the Hub method with the specified method name name see bit confusing maybe at first is invoked and it Returns the value returned by Handler to server if the server requests a result so in the end you know it we here have our method name this is rooms in the send async method we have the method name here only called string method all right and here now it's the same thing so when we get this event here rooms and we actually already can Define the type here so we want to get a list of game rooms and with that I noticed that I forgot one thing we have to add a dependency actually because here now this won't not work I try to press control and period but here now in the uh dependencies we just add another pro project reference and that would be shared we hit okay okay and actually we can then this was done automatically we could remove the shared one here because it's already here then in the client but anyways I leave this up to you it's not bad to have it there so now we have our game room class and now we can do something with that so here we see we have a room list and with the room list now we can do some stuff and the only thing that I want to do here and I think then it's enough with console right lining everything but here now still what I want to do is again string interpolation please so here we got rooms let's just display the count so here this would be count and then room list and then the count like that I hope all right let's test that all right so here now we restart the application and there it is is it restarting yep now it is and we got rooms isn't that nice count zero unfortunately but uh now we are going to create some rooms and here in the console again uh in the terminal we see the user that has been connected all right and with that I'd say the next step would be to finally create actual rooms so that we can see a count of one or two there maybe so let's do exactly that in the next lecture all right now my idea here is that we're currently in the lobby and actually we will never leave the lobby even when we create or join a room because when we create or join a room I only want to well display another component here that represents this room with the TIC TCT toe board the whole game logic there in essence so I don't want to navigate the user back from the lobby I only want to show display use another component for the actual room so the uh logic then for creating and joining a room will be in the lobby but as soon as we got a room then we will show another component and there we will have all the other game logic stuff I hope you get the idea I think you will when you see how we Implement all that so let's go back to there it is visual studio and again here the lobby and here now we will be able to create a room and later then also join a room and the actual method to create a room is simple so what we will do is simply private async and then task create room like that and here we will make a call so first if the Hub connection is null then we simply return again not complete so we could do bunch of stuff here we could display an error message we could throw an exception stuff like that but I don't and here now what I want to do is I call await hop connection invoke async now because with that we actually let's say we make a call to the hub or as it states here invokes a hub method on the server using the specified method name because when you compare this to a typical web API for instance you always make an HTTP web service call right a post call a get call put whatever it is and here we already have this connection to the server it's there all the time hopefully this means we can actually already call the method that is available there because we already have this connection established and that's why we call an invoke async method and not something like an uh HTTP post Jason get whatever it is right no fetch something like that so here this is why we call invoke async with that when I scroll a bit further up then you see again that we can make use of the method name here that you want to call and we can also actually already write here our result then you want to get back and this will be a game room then in the end now the method name not available yet in the game hub we will do that of course in a minute here now what I want to put there is create room so again you see kind of an identifier similar to the send async with rooms now it's the other way around you want to invoke something and this method then is or the name of the method is create room and this is really the actual name of the method that that we will Implement on the server in our gamehub it's not like that which is really just an identifier but here now this will be the actual method name and of course also we can add some uh some more parameters here some objects and what I want to do is I want to send a room name and a player name actually so the name of the room and the name of the player that creates that room but for that we have to add some something here to our component so first the player name and this will be private string then the player name and by default let's just say it's an empty string then the current room name so private string again current room name which is string empty and then the actual current room so private game room room could be null in the beginning at least and this is then the current room like that and what we will also uh want what we also want to display actually is a list of rooms so private list Game Room rooms and again this is a new empty list and we will make use of that here now actually it's not that much so but we can do well let's do that in a minute all right so here now uh create a room again we added now the current room name like that maybe and also we add the player name like that and we get something back so what we can do now is we can set actually the current room to the result of that call all right so far the code block of the client but now here I want to set the player name and the current room name so first thing and input field input fields for the player name and the current room name because when you want to create a room we want to give this thing a name so we need two inputs and then also a button for actually creating then a room and with the list of rooms what we also want to have is an unordered list with list items and each list item then would be again the name of the room that currently is open and also a button then again to join this room so let's do that here first one again an input we bind this to the player name and of course we can add a placeholder like your name all right and then let me just copy and paste that because I'm lazy so here now another input for the current room name placeholder here would then be the room name like that and then here we have a button and on clicking that button we call a function called create room right and you now also create room as a text so here now we will then use this function here to create this room all right with that now we are covering the list of the rooms later with that now let's jump to our Game Hub because so far as you can see here we only have uh the unconnected async method Here and Now what I want to add is the create a room method so already maybe a quick recap here on the or in the onconnected async method we have this call we use the send async method with a method name rooms and the um Lobby here subscribes in the end to this rooms method name and as soon as we get this thing then we just uh write this into the console now it is the other way around we call this invoke async method with the method name create room so there has to be a create room method on the server in the gamehub and also this thing should take two string arguments the current room name and the player name so let's do that back to the gamehub here and now here we can create our method for that so public async task and we return the game room the new one right name has to be create room now and regarding the arguments we have string name and string player name like that and now regarding the body here first thing the room ID already told you I want to use a guid here so this thing is new guid and then to string and then our room so bar room and and here now in the game room we can actually add a Constructor where we set the room ID and the room name so public game room room ID and room name that's correct inell code wow this is great so room ID is the room ID and room name is the room name so back here now we call this Constructor with again the name and the room ID but actually the other way around right so room ID and now here the name all right when we have this room now what we can do is we add this to our rooms list like that and then the next thing that I want to do is send now the new list or it's not the new list but the updated list of rooms to all the clients and then return the room there's more to do in this method actually like adding the player to the room stuff like that but we will do this later of course but now here what I want to do again is await actually similar to this thing here but let me let me really type this in so you see the difference we've got clients so far it's the same but now we say all and then send async and again rooms and then well this is the same name so let me just copy that the rooms ordered by their names all right like that and then here we can return the room all right that's it for creating the room for now now let's test that real quick because what I now expect is that we get an updated uh list of the rooms because now when we again have a look at the lobby here we should see this uh this line in the console right so let's test that real quick we restart the application there we are it is restarting we see the new beautiful UI and here we see we got rooms so now when I enter a name like my name my new room and I hit create room we see we got rooms count one and my new room two we get rooms count two but now what's really interesting actually is what happens if we open a second tab or window and the third one and so on so when another user joins our party here in the lobby and creates a room what happens then so here now I have a second window open maybe I can put them next to each other like that we see the console here let me make this a bit bigger so count is two again now I can create here the third room for instance and now here name is actually not that important for now and here now this should be uh room four maybe so create and you can see other window right but we get also we get the uh the call the the event if you want that another room has been created same thing here when we open the console now with F12 we see the locks already you can see them here as well that this this already happened here right I hope you can still see that yep you're good so now what about room five create and we see count five and same thing here isn't that great so now this already happens and of course this also works with every instance you now open of chrome your browser another tab whatever it is all right so now back to visual studio this generally works but what I now want to do is already add a little bit more UI to getting the rooms and then also add the players to our game rooms so a lot more we have to implement here so this thing is actually getting a game one step after another so again I would say creating a room in general works but now let's also add some UI and maybe also already the players and maybe a bit more logic so let's do that next all right so creating rooms in general the foundation works but now I think there's more to it so when we have a look for instance here in our lobby there should be a list of the available rooms there should be a button to be able to join that room and maybe on server side when we create a new room we can already add a player to this room so I would say we now move into that direction adding more UI and then also adding more Logic for joining a room then so meaning players and then maybe also already doing a bit more with this thing here the TIC tactoe game the actual game that you want to play here but one step after another so we've got I know I'm repeating myself but we've got creating rooms covered in general but now let's do more here we display a list and also a button to be able to join these rooms so here now what we can do simply HR uh not HR H3 to add this seter for the rooms and then already told you they had an unordered list and here now with a for each we just go over all the rooms so room in our rooms list it shall be and here relatively simple really we just add the room room name typo here so now room name it is and then we add a button again where we say on click this function is not there yet we want to join this room we need an argument here so we do it with a Lambda expression so join room and then here the room room idid this shell will be it and then here we say join room now let's add the method real quick so also down here we write private async task join room with the room ID and here now again we check for the Hub connection so again we can actually copy that one and here now what you want to do is we want to invoke again another method so bar joint room this is the one that we get back then await Hub connection invoke async again we get the room back the game room like that the name of the method then will be join room and let me put this in a new line other arguments will be the room ID and again the player name like that and then we also check if we actually able to join the room so is it null or not because could be the case that the room is already full meaning two players are there already so in that case well you can do whatever you want to do but I just write something into the console like the room is already full something like that so here now again we check if join room is not null all right if this is the casee we set our current room to the join room and otherwise again we just say something like console right line and then room is full or does not exist and here now you can already see that there are a lot more ways to play around with that for instance you could really add a toast notification you could change the logic in a way where you just don't display the room if it's full or you add a little lock icon something like that so this can really develop into something really beautiful in the end right with the with great graphics although it's just a tic TCT toe game but still you know buttons can look really really nice so there's a lot you can use to improve that kind of game but now I already implemented The Joint room method what I actually wanted to uh start here is show you the representation of our rooms so maybe we can try that real quick when we open our or rebuild our application here we are we set room one create room nothing is happening now why is that let's have a look on rooms of course we don't set our list here so we have a beautiful rooms list but here now this is the rooms list let's try that one more time maybe all right room one create room there it is this is room one room two create room three create double click the room two and so on now we can join but we get an arrow here and what does this say it says when I am able to scroll F invoke join room due to an error on the server Hub exception method does not exist now this is nice right we get exactly what's Happening Here the the terminal is not telling us what is happening but here in the console we see this method is missing and we know that so we have to add this thing first but since we're now going on the server to the server anyways let's also complete the create room method here meaning I want to add players for instance to that room and then also implementing the join room method so again creating a room and joining a room in one lecture let's do that next all right so what do we have here in the create room method again we have the room ID we have the room we add the room to the list now we need players all right we already have the player name here but you can see that this thing is not used yet so let's do that next for that I want to do a little bit more here in the player class currently it looks really empty so what we can add is simply the ID and the name of the player and to be more exact this is the connection ID so again a string and here connection ID why a string well maybe you can have a look here again player ID with right so this is no integer or something like that this is a crazy interesting idea so string should work here and the other one is also a string and this shall be the name of the player and again we can create a Constructor with exactly the same parameters actually so string connection ID and string name and here now we set the connection ID to connection ID and the name to the name and that's it and since we have the latest version of C actually this is the first time I see the suggestion here it or Visual Studio suggests to suggests to use the new primary Constructor so when I go to show potential fixes which is not really a fix but here you can see that we uh or it suggests to do exactly that use a primary Constructor so here you see we would then have or it would remove the uh Constructor here and then add this to the class so one more thing we can learn here is that well we can combine the properties and the Constructor with the class definition now why not let's see if it works all right anyways in the game room there we can also we can let actually also use the primary Constructor here so let's do that real quick use primary Constructor nice but what we also have here now or what I want to add is a list of players so prop list player and then players and this is actually uh a new list of players and I also want to add a game here so public and then tick TCT to game this is a game like that get set of course and this then again is a new tic tactoe game all right now this means when we go back to our gamehub what I can do here is I can create a new player so VAR new player is a new player with not the room ID here this is actually the context connection ID but the player name this is correct and we can add this player now to the room for that we need another method so let's go back to the game room and here now we add a new method and this method now should be called try to add a player try add player so public bu notebook bu try add player Why Try well there are cases where it's simply not possible so so player new player and here now we first check the player's count of the current room and if you already have a player with that connection ID all right so here now if players count count that's the one is or actually is below two and the uh any play player not like that but almost if there's any player where the player connection ID equals the new player connection idid so again let's put this in a new line here so again if we have less than two players and there's no player with the given connection ID then we add this player to to the room so what we say here is now players add the new player what I also want to do is yes we can actually already return true and otherwise we return false but what I also want to do is I already want to set the players or the IDS of the players in the actual tic tac toe game because in the tic tac toe game the logic there is that we have a player X and a player o right with these two symbols the X symbol and the O symbol and for each symbol we set a corresponding player and I just note T this little arrow here all right so we check if the player count now after adding the player is uh is one so players count is one and in that case we uh we set the player X and else if Jesus I have a new keyboard by the way so sometimes it's still a bit hard to find the right Keys players count is two then we set the ID for player o so let's add that real quick to the teato to game here so we also have bit more in the actual class so here now public string could be null at the beginning so player X ID it's a property so get set of course and here now again player o ID like that and we have that ready we can now say that our game player X ID is the new player connection ID correct and same thing here in that case the game player o ID is the connection ID sorry for mixing already the game logic with only creating and joining new rooms but since we're already added here I think makes sense to to already set that so now we have the game room with the ID the name the players list and the actual game where we then can also add a player or up to two players actually so now let's go back to the game hop there it is and here now so again we have the new player but now we can call room tryad player new player all right so with that the player is in the room and the next thing for now would be to finally uh create our join room method so I think that's enough for this lecture so let's create or let's join another room in the next lecture all right so joining a room first public async task game room it is and this can actually be null as you might remember here in our lobby we invoke or we call this method here invoke this thing then join room and this thing could be null so here maybe we get a game room or maybe we get nothing so here now join room very important the name again with the room ID and also the player name like that and now regarding the logic first thing we check is this room actually available so V room is rooms and then first or default where the room ID shall be the given room ID and now we check if the room is not null in that case we do something and otherwise we return null all right and here now first thing again the new player so Bor new player is a new player with again the context con connection ID and also the player name great and now we try to add this player so if room try add player new player then what we do is we return the room all right the thing now is that when you have a look at both these the create room method and the join room method then you you would see that apart maybe from this dead line here where we send all the rooms to all clients we do not make anything signal r related meaning the gamehub has no idea where the players currently are so when we create a room or join a room then it's fine that we add them to the game room but we do do not know or signal uh our server our gamehub in the end does not really know where these players belong to if we want them to communicate with each other all right so we have no idea when for instance a player makes a move that who should we send this move to and to fix that or to make our lives a lot easier there are groups in signal are so as you can already see we have clients and then all we also have something like clients and then caller but there's also something like groups and to make the join room and actually also the create room method complete we make use of these kind of groups so let's do that next all right so first real quick let's jump back to the create room method here and there we will also already make a use of the groups and then this method really is complete so quick recap we have a room ID with then a new room and we add this new room with that room ID to our list of rooms so far so good and then what we also do is we add a new player to that room now again uh we not only want to send the new list of rooms to all connected clients we also want to make sure that we have a group and that group gets an ID and we also add a player to that group which is then the same thing in essence as a game room for that again let's make use of groups so here now what we do is await groups and let me scroll a bit further down so groups again and maybe yep there it is gets or sets the group manager groups is not n here yes that's true so we have to do a bit more but the important thing is here the IG group manager Hub Group sketer sets the group manager and now here as you can see adds a connection to the specified group with add to group async so let's use that method and now as you can see we have a connection ID so context connection ID this is the player in that case and then we can also give this thing a name easiest thing to do is to use the room ID which is again a gooey so we can make sure that there's a high probability that this is really unique so if someone calls a room my room and then another player also uh creates a room called my room then this would not really work so here now let's use the room ID all right so with that now we have this new group with the room ID as the name and we already add the player with this connection ID to that group and the great thing is now whenever someone makes a move or anything is happening in that game room then in the game hub reg grab the group with that room ID and then we can inform only the players that are connected to that group of course we will do that in the next lectures and the very first step here is what happens if a user joins the room so here we cre creating the room and now when joining we pretty much do exactly the same thing first so here now we say groups add to group async now we already have this group but it doesn't really matter anyways here now we see that the uh new user and the new player with this connection ID will also be added to the room with that room ID and then we do something else so that we really see that someone joined this room we now send a new method to all the uh the clients that are connected to that group and how's that done well we've already seen the uh clients and then all and Calla but we also have the following group all right and the group now you can see here maybe again scroll a bit further down you see it here uh the group wants the group name again in our case it's the room ID and as you can see here gets a that can be used to invoke methods on our connections in the specified group all right and the group name well it's the group name so here now we uh enter the room ID again like that and then we call send async you know that by now I think and now player joined is the new method with the new player that then will be serialized on the client and when the new player joined we want to do something all right so now we addit groups and we implemented this call here player joined or this new method named player joined now what should we do with that because in the lobby there's not really a place for that we here create a room and if someone created a room maybe the user then already should jump into the room same thing with join room right when the user joins the room then he or she wants to see that room and not stay in the lobby so we this information that someone joined the room here isn't really interesting in the lobby so I think it's time to add one more component to our little application here and that would be then the room razor component so let's add another folder here in the client project and call this component and here now we add a razor component and we call this now the room all right with that we have our room razor file and as I already told you in the beginning of this course or more or less initially that uh here now I don't want to navigate the user to another page when joining I just want to display this room here actually so what we can do is we check if we have room for instance if so we show it if not we don't so here now in the lobby maybe we can change the text here actually so welcome to Blazer tick tag toe like that and now here we check if current room is null then we have all the UI to create or join a room like that and if not then here we display our new room component and actually let's grab that and add it to our Imports raser file so here like that and then this thing should hopefully be available yep now it is great quickly lines are gone so now we have to focus on this new room component and then also find a place where we can show that someone joined a room so let's jump to that room component now right here and add some logic into the code block now we need some stuff the first thing is this room component also needs a game room so let's add this parameter here parameter and then prop and this shall be again room which could be null and we call this then current room like that and we again add this now to our Imports raise a file like almost like that all right so now we have the game room available here as well and since we also in that game room want to be able to communicate with our Game Hub we need a hub connection now this is a great opportunity to use a cascading parameter so here again uh property this is a hub connection which which can be null Hub connection the name and then here instead of using another parameter let me just use a cascading parameter because maybe now when you would like to add more child components we can still make use of this skating parameter meaning we already have this thing available in our lobby component and now here we can add the current room which is the current room and here now we can add the cascading value and set the value to our Hub connection so this thing as soon as it is initialized is also available in our room component here great stuff here in Blazer in my opinion now to make use of the new Hub connection here again we will use the uninitialized async method and then add a couple of handlers actually to react to certain events in our game and the first one here then would be the player join event so let's do that with the uninitialized async so protected overrides and then on initialized async again it is and here now first I check if we actually have a current room if this thing is null and actually if the uh Hub connection is null and one more thing if our connection ID is also null so H connection connection ID is null then we return because something is not set up properly here we add the async keyword and now let's listen to the player joint event so similar to the lobby we say Hub connection please note it is already established everything is running because we have our cascading parameter The Hub connection there so now Hub connection on and there we actually get the player returned right let's double check and we go back to the Game Hub join room create room and here now when the player joins we get player joined and it sends the new player so let's go back get the player here and uh the method name here is player joint all right and again we have the player here available and what do we want to do do with that well what we can do is we can say current room players and then add this new player for instance all right but now maybe we can add some kind of representation of that and not use the console again so instead of writing something into the console we can actually check if the current count of the players in that room is below two then we can add a text for the current user saying like waiting for another player to join and when we have account of two then this message disappears and we could display a start game button for instance something like that so now up to the markup first thing is we check if we have a current room so if current room is not null like that only then we do something maybe even display again hrh3 the current room name so current room and then the room name like that and now here as I said if the uh Cur room players count is below two so if current room players count is below two then we display H4 maybe waiting for another player to join all right so now again we go to the lobby we see or should see welcome to Blazer Tic Tac Toe Blazer is still not in the dictionary of Visual Studio this is really interesting we have a current room I have no current room rather then we display our input fields in the button and also a list of the rooms but when we create a new room we should see this room current room and here we also see with create room that the game room create the the create room method so many rooms uh method is invoked and with that we get the current room here and with join room we are able to join the current room or the room that was that we clicked on with the button up here all right and then when we see the room so here now our room component we should see the current room name also this text waiting for another player to join and then as soon as the other player joins this message here should disappear Let's test that we restart our application it is rebuilding all right so my name is Batman bad cave is this the correct name not sure so we see welcome to Blazer tic TCT toe we see bad cave the name of the room and waiting for another player to join so let's open this in a new tab I opened a new tab I ordered them next to each other and I see a little mistake here that we did not pay attention to earlier and when we have a look at the code here we see when we're connecting we set the room list here but we have to redraw our component so here now for that we call status changed and this notifies the component that its state has changed and when applicable this will cause the component to be rendered so let's call that here and unfortunately we have to restart the application again so now we open this again Batman bad cave we create the room now it's here but now when we also reload that we also see the room and now again we want to join and this message here waiting for another player to join should disappear and it didn't work because again state has changed wasn't called so pay attention there so here let me just copy that and we go to the room Razer player joint we add this state has changed and now let's try this one last time Batman bed cave create now here Spider-Man will join the bed cave and you see the message is gone all right so you see this kind of communication worked and regarding redrawing or rendering the components you have to add state has changed this is really important and it's somehow fortunate that this happened now because I of course wanted to show you how important it is to call this method so again player joint this worked in general we can create rooms we can join a room we now see if another player or when another player joined our room but now the next step actually is to add logic to our game so as you can see here we have the room the lobby the game room here the players here but the tic tac toe game here well there's not a lot in there right so we have to fill this now add way more to this class and then with that we will also add more events here more UI of course in the room razor component and then also in the game hub we will add more more methods in the end to well make this thing a real game so let's do that next now to move on with the actual game what we might do next or maybe should do next is actually implementing more here into the OR implementing more in the tic tac toe game itself so for that we need a couple more properties and maybe already the first one or two methods for the game because the next step would be in my opinion too well start the game somehow and when the game is started then we should maybe see the TIC TCT toe board there all right so let's do that so we already have the IDS for player X and o the next thing now shall be the current player ID so whose turn it is currently so again a property with a nullable string and this is then the current player ID and then the next thing is the current player symbol so whoever is the current player this player then has the symbol X or o and when the player makes a move then we want to set the field in that board with X or o so this is why we need that information so again a string and this is not nullable actually so next would be this thing here the current player symbol and this now actually is not a property because here now we set this directly player ID if the player ID is the player X ID then in that case we set X otherwise we set this to O all right so current player symbol we just check if the current player is a player X ID in that case we know that X is the current symbol if not it's O then the next part should be well maybe let's add the board at the last because I already see the board here as a list of list of strings but I have to explain this a bit more easier are some Flags so we have game started so game started in the beginning is false pretty similar is not game p in teley code not game p it is bull and then game over which is also false in the beginning then is draw is another flag so we will check if we have a draw and if you know the game then you know that this might happen quite often then I have a string for the winner so I just want to decide if x or o is the winner and yes I know you can definitely improve all that with States and an enum maybe so there's definitely way or there are more ways to improve this but again this is a simple version and I wanted to show you all the signal R stuff I think this is really nice now the board I already told you about the board so first I had a two-dimensional array there but the problem with the two-dimensional array is that you cannot serialize it with signal R via web sockets so what you can do instead is you have a list of a list of strings and this then will be our board so nine fields in the end right 3 * three so again this is our board and we can ini initialize this thing as a new list of lists list of lists of strings and the size is three all right okay so this is then our board then we have a Constructor c r nope CTO R like that and here we call a method called initialize board all right so private void actually initialize board and we call this method here in the Constructor so initialize board it is and here now we clear our board all right so removes all elements from the lists and after that in a for Loop we set every value to string empty all right so here now for in I yep that's it in code this is nice and here we say V row is the new list of strings with again the size three and then for J is zero J smaller than three j++ and then here here we say row at string mty forgot the integer like that and board at row all right so again we have this list of lists of strings and each row is this part here so each row a list of strings size three and we add the string empty to every row so to every column in the end so that in the end we have a list of three lists of strings I hope you get the idea and with that the whole field is empty okay and then the well the last method for now is start the game so this now is a public void start game method all right and and here we set the current player ID to the player X ID so meaning the player with the X symbol starts remember the player X ID and the player o ID should already be set when creating uh the room so here in the game room we see the list of players we see the t t to game and here then we say when we add a player that the player X ID is disc connection ID and play o ID is this connection ID and all that is still held in the gamehub here so we have the list of rooms a room has a game and the game then has this set so this is not stateless at all we all always have this state available otherwise this would not work so here now in the TIC TCT toe game the only thing I want to set is the current player ID because I also want to to uh use the start game method to reset a game so if a game is over then we reset some Flags here and for instance this is the game started flag this is true but resetting is game over which is then again false winner is again string empty and his draw is also false and also we have to initialize the board again so current player is set to X game started is true game over is false winnner is empty is draw is fals and initialize the board okay so far the logic for now I'd say and the next step then would be to really start the game and see a result on the clients and use the uh Game Hub again to start the game finally so let's do that next all right first is in our room let's add another method to start the game so async task it is we just call this start game and in here first let's check if we have a hub connection so Hub connection if this thing is null or the current room is null then we return but if we have this available then we say Hub connection invoke async invoke async and then the method name is start game and here now we provide the current room room ID actually room there it is room ID like that so start Game Hub connection invoke async start game and now the counterpart on the uh Game Hub so here we add another method public async task start game again name is very important here has to be the same so start game again we check if the room is available so in our rooms first or default forgot the ID here with the string room ID and and then here when the room ID is or equals the given room ID we found our room and then if room is not null we say room game and then start game our new start game method in the TIC tactoe game and now here again we make use of the groups so await Plus clients group with the given room ID here now we send async and another thing is that I want to provide the complete room of course there are ways to improve this again maybe you just send a certain difference whatever it is but my idea here for this challenge was that again let's keep it as simple as possible and also here then this would mean that the game Hub always decides what's true in the end so the gamehub will send the room with every update meaning when the uh when one player makes a move we make a change on the server and the server then Returns the complete new room so we do have to think about what can be a difference how do we update all the clients and so on so not like uh I don't know multiplayer shooter game for instance where you really just uh sometimes just send and the coordinates of the players and if a player has shot something whatever it is so there it's really crucial to send as few information as possible to make the whole game still running very very fast but um you know I think you know it's uh in the end turn-based game right so here now we can send the complete room and I think the internet connection is not a problem nowadays so here we just sent the complete room and we're done with that and by the way again I really love here already that I said turn-based game so you can really build a much bigger thing out of that I I just love the idea of that you know I love video games so that's that's really my thing anyways what we could do here is we could send now a method called game started for instance right but you will see that we will have way more events here let's say where we will then send the complete room to the player making a move checking if we have a winner so we do not really need a Handler for each of these events of course you can do so if you want to provide specific messages something like that but let's again keep things simple and what we can do now is simply send async update game or game updated something like that and when the uh client then gets this then we just override our current room and then see the difference and the results all right so this is now my idea here so with the start game method we check if we have the room if the room is not null we start the game with the start game method we set certain flags and then we sent the method update game game to the method with the method name update game send this information to all connected clients of that room so now back to our room component we have to add the Handler for that so down here additionally to play a joint we say now hop connection like that on and then we get a game room here and here it is update game with the new let's call it server room because this is the room on the server and here now what we do is we simply say our current room now is the server room and we call state has changed all right so with that we should see all the changes on the screen when we add the corresponding mark up here and I think this is what we definitely should do next meaning adding more logic here asking or checking more cases and of course in the end also rendering or drawing the actual Board of the TIC tactoe game so let's do that next all right so now before we can start the game we need a button and maybe add an information for the player who has joined the room because here we now see waiting for another player to join but what is now with the play player who actually joined our room the first player who created the room would not see this message anymore this player should see the button to start this game now and the other player should see a message which says waiting for the other player to start the game maybe so let's Implement that it's not that magical actually so if first we check current room game game current room room game and then game started is false then we check if the current room game player X ID is actually my ID so we have to add another variable here actually and the last thing I want to check is if the current room players count count is two like that if this is the case then we display waiting for the other player to start the game all right now my player ID how do we set that well right at the beginning here we can actually say my player ID is H connection connection ID that's nice and of course we add it here so private string can weal in the end in the beginning and then my player ID all right so with that fix little typo here the next thing would be the start game button now we have the method down here right start game and for that button we check if again the current room game game started is false or now we can uh also make use of the game over state so or if current room game is game over like that and then the next thing we have to check is not like that like that actually current room game player X ID again is my player ID and next then is current room players count is two again and if all that is the case then we say button on click Start game and start game for the Tex next here all right this is the button now and now when the game is started we show something else and that would be actually the board right but maybe we can start with some text and then add the board afterwards so now here we ask if current room game game started so if this is the case first let's display something like it's current room and then game and then current player symbol turn so we would see that it is the turn of for X of X forx it's X's turn or O's turn currently and then I also want to display the the the player names I think this is this is fun to see who's currently playing so in a little ban here we just say currently playing and then here we see current room players zero come on zero name and this player then would be X and then pretty similar would then be or maybe a comma would be player one name which is then the O symbol so here we have o and here the capital x all right I think this is enough for now because the next part would be the board drawing the board and actually then already making moves so let's test the current state but first let me double check real quick what we actually changed because I think it was a lot so here we have the game hub that's not that much we have the start game method client group room ient I say update game in our room we have lots and lots of checks but this well of course could be the case that we have a typo here some tiny errors maybe tiny mistakes but nothing that should break the application but here here we have a loop and when I have loops I'm afraid and yeah see this is what I mean I I I and then here j i j so let's fix that real quick and uh hopefully now we shouldn't have an endless loop so let's start the game all right as you've seen I closed it earlier all right there we are so Batman bad cave create the room waiting for another player to join and now here we add Spider-Man We join the bad cave B cave Batcave waiting for the other player to start the game now we hit start game nice all right so we have the bad cave it's X's turn that's correct and current playing is Batman and Spider-Man Batman is X Spider-Man is O perfect so this works so far this is already amazing and now the next part part is drawing the board and then the whole logic regarding making moves and deciding who is the winner so let's do that next all right so now we are back in our room razor component and before we draw the board we need new methods so that we are we have them available already and these are actually um checking if it's currently our turn and making a move so let's add them real quick we have private asnc task make move method there we will provide the current row and the current column regarding the body we will deal with that later and then also private bull is my turn and here then of course we will check if it's currently our turn we can Implement that already because this is not that not a lot actually so if we have a current room if it is not null then we return true if my player ID equals current room game current player ID so yeah this well if we don't have a room then we also return false so this is the is my turn method regarding the uh make move method this is another call let's I I call it call but it's is it's invoking another method in the gamehub but now first let's draw the board because this is tiny bit more complicated so this will be a table all right and in this table now we also have to add some CSS but let's do that in a minute we again call a for Loop so four four and row is zero then again three maybe I should have used these variables as well in the initialized board method and then for each row Plus+ here we say a table row and in that table row then we say for in column don't forget the at in column Z column smaller than three column Plus+ we say the following and this is something where you really have to pay attention because we add a table cell here and we use the onclick event to call the now make move function so make move row and column right and here now now we add the following for the content this is the current room game and then from the board we choose a row and column now I could demonstrate this but I can already tell you that this would not work the problem is this expression here so why is that we have a loop here all right and row and column will be incremented until they're three both of them and in here we're using a lampda expression and the problem is that Lambda Expressions capture the uh variables here by reference and not by their value so again when you do it like that then in that Lambda expression we have a reference to the row and the column to the current value of these uh variables and since we're using a reference here then in the end we will always call make move with the same value which would be three in that case now to fix that we can create a local copy of them all right so to do that simply say VAR R for the row and C for the column and then here we also use R and c and so R and c and with that copy we will really use the value here otherwise we would still use the the reference and with that even though the values are incremented since we're using the reference then here we will still use the last value I hope you get the idea here if you want to see this in action just remove that use row and call then you will see that it does not have the effect that you might want it to have all right right so this is now the board and since we now already added let's add some more cases here we have the table but we can also check if it's currently our turn if not we uh also display a message please wait for the other player to make a turn so add if and then is not my turn and current room game is not game over then we display something like please wait for the other player to make a move all right and the last ones would be actually displaying Game Over States so maybe let's copy these and then yeah maybe add them here so here now we first check if actually only if the game is over so current G room game game over and current room game is not draw then we say game over winner is then current room game winner almost and the other case we have a draw so this draw we just display draw like that okay all right now let's test that so far we restart the application and then the last steps would actually be to make the moves so application is restarting we are here and here let's try that one more time Batman bad cave we create the room Spider-Man is joining the Batcave we start the game and we don't see the uh board now why is that I have a feeling that I am I forgot the CSS so real quick let's open that up now we add another file here new item room razor CSS and here I will just copy some CSS so that's what we need because otherwise it's a bit tedious sorry about that but we have a width and the height a border text the line the cursor font size and vertical align and now here we simply set the class there a board there is class is now take tag toe say save that and let's try that one more time all right restarting again Batman bad cave create room Spiderman join the room start the game and there's our board all right and now here you see we have the cursor icon and we could actually click right but we do not react to that click so make move the make move function is not doing anything so far so let's cover that in the next lecture all right so in essence only making a move is left as our last feature let's call it that way and then afterwards also we want to check if we have a winner or if it's a draw so these two things have to be implemented now for that we well have to make changes in the room razor here we have to implement the make move method then also we need the counterpart in our Game Hub and then also a bit more logic here in the tic tac toe game so I would say we start with the room eraser file and implement the make move method here because here we in essence only again invoke a method of our Hub so we call a weit and then again our Hub connection invoke async and here we will call this thing make move and here now we provide right the current room room ID and maybe put this into a new line here the room ID then also the row and the column and the last thing shall be my player ID but let's also check if we are actually allowed to do this so we check if is my turn then also if if the current room is not null Additionally you want to know if the current room game has actually been started similar we ask if it's not game over because we don't want to make any moves when the game has not been started yet or the game's over like that and the last thing the Hub connection so we also check if if the Hub connection is not null so only then we want to make our move all right now before we implement the counterpart here in our gamehub CS file we need more logic in the tic tac toe game as you can see here we have the start game method initialize board method but again not the make move method and additionally we also want to toggle the player after making a move so so let's Implement these two methods toggle the player and making the move first in the tic tac toe game and then afterwards we can use these methods in our Game Hub so you know first toggle player so void public word actually public void toggle player and here we say current player ID is now with the dinary operator we check if the current player ID is is the player X ID then the new current player ID is the player o ID and otherwise again player X that's toggling the player and now making the move public pool because we want to return if we able to make the move or not and then here we provide the row again the column and the player ID and before we allowed to actually make the move we again have to check a couple of things so first we check if the player ID is not the current player ID if this is not the case we return false but additionally again there are a couple more things so if now and this is about the board if the row provided is zero or the column nope or the row row is greater or equal three then we check if the column is below zero or exactly column greater or equal three and the last thing we check if the board row and column actually already has a value so it's not empty if this is the case then we return false all right so we have to make sure that we are actually the one that's turn it is currently that's done with the player ID then we want to check the borders of the board and you want to see if something is already set in the current cell of the board or in the current cell the user has clicked and if everything is fine then we just say board row column is now the current player symbol after that we toggle the player and we return true all right now we've got toggling the player and moving or making a move additionally after each move the Game Hub wants to check if we now have a winner or if we have draw now these methods are tedious so please bear with with me I just copy and paste them so let me just select them here in my on my other screen and paste them now here and let's just talk about them so first the check winner method which or the thing that will be returned is simply the player symbol all right so first we check the rows and the columns and as you can see here what we want to do is in a loop we go over each row row and check if the uh specific cells have the exact same value and same thing also for the columns so here we are in the same row right and with the 0o 1 and two we check the uh The Columns and then the other way around we check the rows 0o one and two and then the different columns so horizontally and vertically we're checking if the symbols are the same if they are we have a winner actually and return then the symbol same thing States here for the DI diagonals so board 0 0 and so if we have a value here in 0 0 then we compare 0 0 with 1 one and so on and same thing for the other diagonal so again 02 and I think you get the idea by now if we don't have a winner then we simply return an empty string and regarding the draw here what we do is we check if all cells in the ends of the board have a value if that's the case and we have not a winner well then it's a draw and this happens quite often in teoe all right so these are now the methods we need in our Tik Tac to game and now we can go to the game hub and here add our make move method so again a public async public async task make move and again we get the room ID the row the colum and the player ID and now here first again we want to get the room so our room is first our default where the room ID equals the given room ID and then we check is our room actually available and we already make the move and check if we were able to make the move so if true is returned so room game make move with the provided arguments if this is possible then we do the following first we check if we have a winner so room game winner is now room game chck winner most of the time this will be an empty string and then room game is draw and here we say room game check not winner check draw this time that's the one and now we check for the actual values so if string is null or empty or it's not null or empty regarding the the winner so room game and then winner or the room game is draw then we set the game over state to true not as draw game over actually and this is now true all right and after that in any case we send the update game method to the clients connected to our group so await clients group and then room ID send async update game with our new or updated room so again quick recap this is our make move method we get the room ID the row the column and the player ID you try to get this room format everything and then we check if the room is null or not and if we were able to make make the move if this is the case then we try to get the winner if there is a winner we also check if we have a draw state if this is the case either we have a winner or the game is draw then we set game over to true but in any case we send the update game method to the connected clients of that group or that room and again told you that earlier but with that update game method name we are able to only send one single update here I had another implementation where I had the method name uh game over or game started something like that but this is not really necessary when we just have update game and then send the complete room every single time again this is maybe not the ideal way but I think in this scenario this totally works it's not a real time action multiplayer game so with these turn-based games I think this is totally fine so I would say we test this run the application again let's try it with a Batman and the bad cave we create the room Spider-Man joins the bad cave we start the game and as you can see now it's exess turn so we see Batman and Spider-Man Batman is X so we hit X here now I can't C click anywhere but Spider-Man can for instance there Isn't it nice and that was just selected because I clicked there and now I said the X here maybe an O there another X and I I'm totally missing that Batman is about to win and there we have it game over winner is X still saying that it's O's turn so this is something that we can of course also add to our if statement maybe I'll do that before I'm uh pushing this repository to fix that but also we see that uh on both screens actually we see that the wins X and we can again start the game and it's again X's turn so I cannot click here as Spider-Man but Batman can and now let's try to let Spider-Man win and we see winner is again it's exess turn so I really have to remove that and uh I cannot click anywhere now let's try the draw this is the hottest one when you're doing this by yourself all right uh now here and we've got oh there see totally missed that so again we have no we have okay no this is wrong actually this is not correct it says that there's a draw but of course uh before we had a winner so I have to check this first if we uh actually have a winner so let's fix that real quick actually we can just check here if winner is null or empty so here now if string is null or empty regarding the room game winner so only if this thing is another or empty then whatever the check draw method says is true all right so now let's save that try this one more time all right we start the game and let's try to reproduce our last moves so we had this one this one there and then the X was here here and here yeah and now it's true we have game over winner is X try that one more time with o that maybe right winner is O and now let's try to get a draw here that's and then here here and here and now it's correctly saying we have have a draw all right that's it I hope you liked this challenge I hope you learned something tell me that in the community whatever you want to see here or if you have any questions please tell me them as well and it would be awesome to see your versions of tic tac toe maybe you changed the design I know that we can do a lot more here we can of course add more CSS maybe Tailwind for for a better look we can also add a leaderboard meaning with every game we can count the victories and the defeats of each user and display a little table below maybe would be nice but I think now with these foundations in Signal are with the groups now you can or you know how to do that so you see how to store the current state actually in the game hub and then you can uh yeah send the current wins and defeats again uh to to all the players for instance that are currently connected to the group or the room so again thank you very much for watching The Challenge if you have any questions please feel free to ask them in the community and I hope you also have fun with these challenges here see you next time hey there one little bonus here I changed the design a little bit so I added Tailwind CSS as you can see here and well added some more Style so it looks a tiny bit better in my opinion at least so let's just have another look with our example players here so Batman in his bed cave creating a room we see the room now here so we see we can either create a new room or We join a room below so now I enter Spiderman here enter the bad cave again we see waiting for the other player to start the game we see the room name then we can hit start game and let me remove my face here so you can see both boards as you can see please wait for the other player to make a move so Batman's turn then Spider-Man and so on now let's win this thing and we can see game over winner is X and the creator of the room can again start the game for another round all right so now let's have a look in uh V Studio there it is and just uh check out the changes and as you can see it's not really a lot so the main thing or the uh first thing you should do I haven't really installed Tailwind I just used the CDN here to uh use the uh minified CSS file of the latest tailin CSS version and then with that I changed the main layout a little bit as you can see here I removed the the outer diff right and then added some classes to the main main tag and then also another diff here for the body in essence it's background color text color and also some spacings padding margins and so on so this is the main layout and then we go to the lobby there I made also changes to the text so the headers are a bit different of course input and buttons s also down here instead of join room now you see the room name which is then the text of the button and I think that's it for the lobby and then last thing the room I made the b a little bit bigger as you can see here width and height of the cells is now 100 pixels font size is also bigger and also here regarding the room we see the header is a bit different and also the start game button and here to Center the table I added a diff around that table to center it with a flex GD in ESS sense and also added a break here so the button and the text are in two different lines and not next to each other so that's pretty much it I will check this in you can get the code I think here in this lecture because this is the last one of this Challenge and maybe I will also add it to the first lecture so you definitely see the code I think GitHub repository access is not necessary here it's only one branch only the master Branch so just grab the zip file so that you have the code and can build your own turn best game if you want so that's it just a little bonus here Tailwind CSS to get a little bit better looks for our tic tac toe game
Info
Channel: Patrick God
Views: 3,562
Rating: undefined out of 5
Keywords:
Id: RsnndxBBFok
Channel Id: undefined
Length: 124min 8sec (7448 seconds)
Published: Tue Apr 09 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.