تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Detecting Game Over0:03

I think the next big thing that we need to address, at least as far as the game is concerned, is knowing when the game is over, either by guessing the correct secret number or running out of attempts. And we can approach this in a variety of different ways, but to start, I want to do something like this to where we will have an onEnd property and then we would assign a callback function that will execute when the game is over.

and then we would assign a callback function that will execute when the game is over. And let's do this to start. We will show the feedback saying that the game is over, or let's just say game over. I think that's gonna be fine. Now there is a possibility that this would interfere with showing the feedback down here or, or rather that's, that's vice versa. Showing the feedback down here will interfere

or rather that's, that's vice versa. Showing the feedback down here will interfere with our game over message. And I think it really doesn't make sense to show feedback for every guest because we get that feedback for the history. So we can leave the feedback for important things like the game being over. So now we just need to implement this, which means we need to scroll up to the Game class.

Implementing onEnd Callback1:00

So now we just need to implement this, which means we need to scroll up to the Game class and right here inside of the constructor, we are going to create this $onEnd. Now we can do a couple of things here. We can initialize it as a function, which that would be fine. We can also initialize it as null. The thing is, this is gonna be a property and we are going to have to be aware.

The thing is, this is gonna be a property and we are going to have to be aware that we can assign anything to this property. So when it comes time to executing this, we need to check if it is a function. And I think the checkGuess method is the perfect place to do this. So the first thing I want to do is check if the maxAttempts is equal to the history length, then we don't wanna do anything.

to do is check if the $maxAttempts is equal to the $historyLength, then we don't wanna do anything because that means the game is over. And really we might want to throw an error, but I'm not sure about that because you know, if we try to make a guess for a game that's over, that could be considered an error. I don't know. We'll, we'll see how I feel about that later. But for right now, we're just going to return. But also note, since I'm using the === sign,

But for right now, we're just going to return. But also note, since I'm using the === operator, the identity operator, that means that maxAttempts has to be the same type and value of historyLink, which means it needs to be an integer. So let's go ahead and let's make sure that maxAttempts will be an integer. We'll call parse in passing the input of maxAttempts and assigning that to our private field so

We'll call parse in passing the input of maxAttempts and assigning that to our private field so that now all we have to do is decide when we want to determine that the game is over. I think that we need to make it past here and make it past the actual guess here. But right here we could check. So we have two states that determines if the game is over, if the guess is equal to the secretNumber, or if the maxAttempts is the same.

if the guess is equal to the secretNumber, or if the maxAttempts is the same as the history length in either one of those cases, the game is over, in which case we will call the onEnd callback function. But as I mentioned, we can assign any value to the onEnd property. So what we need to do is check if type of this onEnd is a function, then we want to execute this onEnd.

this on end is a function, then we want to execute this on end. And if it's not a function, then we don't want to do anything with it at all. But then we'll go ahead and check the guess return, the appropriate response. And that should work. I, I do notice that we have the play method here. We don't need that anymore. So let's get rid of that.

We don't need that anymore. So let's get rid of that and let's see what this is going to do inside of the browser. So let's go with the hard game because I think the max attempts is five. So whenever we make five attempts, the game should be over and sure enough it is. But there are other things that I want to do. Yes, we need to show that the game is over,

Disabling Game UI3:49

But there are other things that I want to do. Yes, we need to show that the game is over, but we need to reenable the game settings and really we should disable the guess ui. Now that first thing is going to be easy enough to do because we already have the code to do that. So back to our clawback function. We show the feedback that the game is over, we will re-enable the settings ui, but then we want to disable, what did we call it?

re-enable the settings ui, but then we want to disable, what did we call it? I think it was the gameArea. Yes it was. So we had gameArea and let's just do the same kind of thing that we did with the settings so that we will have disabled and then we would set that to true, which means that whenever the game starts, we're going to need to set that to false. Now I know that we directly interact with

Adding gameArea UI Methods4:34

that to false. Now I know that we directly interact with that gameArea element up here. In fact, I think the only thing that we do with that is show or hide it based upon changing the CSS classes. So why don't we do something like this to where we will have the ui, the gameArea, and we will have a method to hide it and then we will also have a method to show it. So let's go ahead and implement that as well.

and then we will also have a method to show it. So let's go ahead and implement that as well. I'm going to grab this gameAreaElement constant. We're gonna take it out of this event listener, and we're going to define that inside of our function that we use to create our UI object so that we have settings here. We're gonna add the gameArea property. And let's see, we will have our hide method, which is going to use our gameAreaElement to where we set the classList.

And let's see, we will have our hide method, which is going to use our gameArea element to where we set the classList and we add hidden. And if we hide it, that also means we need to be able to show it. So we will have the show method to where we simply remove the hidden CSS class. But then we also need to be able to enable and disable that. So we will have a setter called disabled to where we get the true or false value determining whether

So we will have a setter called disabled to where we get the true or false value determining whether or not we want to disable it. And then we just need to disable the elements inside of our game area. And, and really we just have three, we have an input element and then we have two button elements. Now we already have a reference to this input element because that is how we get the guess in order to check the guess.

because that is how we get the guess in order to check the guess. However, we don't have a reference to the button elements. We could easily create those, but I'm gonna be a little lazy at least for right now, and just fetch them dynamically whenever we need to. So the code to do that is going to look like this. We will get the elements that we want to disable by using our gameArea element and we will call querySelector.

by using our gameArea element and we will call querySelector. All this is going to of course, select all of the elements based upon the CSS query that we provide that is contained inside of the gameArea element. So it's not going to look anywhere else within the document. It is strictly looking inside of the gameArea element. That's really what we want. And we want the input elements and the button elements so

And we want the input elements and the button elements so that then we can just iterate over them. I'm gonna use a for loop, but the type of collection that is returned from querySelectorAll actually has a forEach method. So I could use that if I wanted, but I'm gonna go with the for loop so that then we will simply set the disabled property.

but I'm gonna go with the for loop so that then we will simply set the disabled property to the provided value. So that's going to allow us to enable and disable that. So back inside of the browser, let's pick another hard game and suddenly nothing works. So let's pull up the developer tools. Game area element is not defined. That is line 300. And that makes sense because I took out

That is line 300. And that makes sense because I took out that element object from the submit event listener, and I'm using that I right here, gameArea element. And we do that somewhere else right here. So instead we will say UI.gameArea.show, and then we have UI.gameArea.hide. So now we should be able to play our game. Let's make the game end by guessing five times. And sure enough, we can see

Let's make the game end by guessing five times. And sure enough, we can see that our game settings enabled the input element for the guess UI is disabled, but it doesn't look like the buttons are disabled. So we need to add some CSS classes to those elements. Essentially the same thing that we did in the previous episode. So that when it's disabled bg-blue-500 and we'll also set the opacity to 50.

So that when it's disabled bg-blue-500 and we'll also set the opacity to 50. Let's essentially take those same classes and apply them to the quit. But of course the background color is going to be a little bit different. Instead it's going to be bg-red. But that should do it for us so that if we play the game, let's go through five attempts and there we go. So now the only option that we have is

let's go through five attempts and there we go. So now the only option that we have is to either clear the board or to start playing another game. And that's exactly what we want. Now the drawback with this approach is that we can only do one thing when the game is over because we have just a single property, we can only assign one thing to this property and that's a function. Now, there are ways around that,

Supporting Multiple End Callbacks9:02

and that's a function. Now, there are ways around that, but I would prefer to have an API that just takes that into account. So what I want to do is essentially replicate the same idea that we'd use when we set up an event listener. And that's we will call a method that says addOnEnd, and then we would pass in a function for our callback function. So that then if we wanted

for our callback function. So that then if we wanted to call something else when the game is over, then we would just simply pass in another callback, which in this case it would say not Hello World game over. And you know, it would give us the same kind of end result, except that it's going to be much more flexible. So we just need to implement that. And it's relatively simple to do. It is just a few changes. I say it's a few changes, it's lengthy kind of,

And it's relatively simple to do. It is just a few changes. I say it's a few changes, it's lengthy kind of, because the first thing that we need to do is keep track of all of the callback functions, which means that we need an array, or at least an array is the easiest thing to use. So we could have on end callbacks. I'm already not liking my naming scheme, but it's clear what this is. This is an array of our callback functions so that

but it's clear what this is. This is an array of our callback functions so that then we don't have this onEnd property. Instead we have a method called addOnEnd. I'm gonna do that before checkGuess. And this is going to accept a function that we will then push to our onEnd callbacks array. I'm really wishing I picked another name, but that's going to be fine.

I'm really wishing I picked another name, but that's going to be fine. So every time we call add on end, we pass a function that we push to our array so that inside of checkGuess whenever we need to execute those callback functions, we can do this. We will iterate over our callbacks. I'm gonna use the foreach method here. And for each function, you know, it's still a good idea to check to make sure

And for each function, you know, it's still a good idea to check to make sure that the function is an actual function. So we'll do that, and if it is, then we will simply execute it. Otherwise, we'll just ignore it and leave it alone. But now our code is much more flexible, giving us the ability to execute multiple callback functions whenever the game is over. So let's play a hard game.

to execute multiple callback functions whenever the game is over. So let's play a hard game and let's go through five guesses really quick. We see the alert box come up, we also see our message in the feedback areas and that the game is over. The game settings enables the makeAGuess section is disabled. So we can play another game. Uh, let's do an easy game to

So we can play another game. Uh, let's do an easy game to where we can start guessing again. Uh, let's start with six. That's too low, so we'll try eight. We guessed it. So the game is over, but we also see that the game is over and the UI does exactly what it is supposed to do. Callback functions are extremely common in JavaScript. We use them all of the time with events, but we can also use and incorporate them inside of our own code.

Introducing Custom Events12:15

We use them all of the time with events, but we can also use and incorporate them inside of our own code. But sometimes it's just not good enough to have a callback. Sometimes you need an actual event and we can create our own custom events, which we will look at in the next episode.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟