We are now at the second video of this section.
State design pattern in the previous video we looked at visitor design pattern in this video we are
going to develop a very simple game that uses F S M St. patterns are directly related to FSM as an FSM
in very simple terms is something that has one or more states and travels between them to execute some
behaviors.
Let's see how the states pattern helps us to define F S M a light switch as a common example of an FSM.
It has two states on and off one state can transit to the other and vice versa.
The way that the state pattern works is similar.
We have a state interface and an implementation of each state.
We want to achieve.
There is also usually a context that holds cross information between the states with FSM.
We can achieve very complex behaviors by splitting their scope between states.
This way we can model pipelines of execution based on any kind of inputs or create event driven software
that responds to particular events in specified ways.
The main objective of the state's pattern is to develop FSM as listed here.
First of all to have a type that alters its own behavior when some internal things have changed and
modeled complex graphs and pipelines can be upgraded easily by adding more states and rerouting their
output states.
We are going to develop a very simple game that uses FSM.
This game is a no guessing game.
The idea is simple.
We will have to get some number between 0 and 10 and we have just a few attempts or we'll lose.
We will give the player to choose the level of difficulty by asking how many tries the user has before
losing.
Then we will ask the player for the correct number and keep asking if they don't get it or if the number
of tries reaches zero.
For this simple game we have 5 acceptance criteria that basically describes the mechanics of the game
first the game will ask the player how many tries they will have before losing the game.
Next the number to guess must be between zero and 10.
Then every time a player enters a number to guess the number of retried drops by 1 and if the number
of retry is reached 0 and the number is still incorrect.
The game finishes and the player has lost.
Lastly if the player guesses the number the player wins.
Now we move on to the implementation of state pattern.
The idea of unit tests is quite straightforward in state pattern so we will spend more time explaining
in detail the mechanism to use it which is a bit more complex than usual.
First of all we need the interface to represent the different states and the game context to store the
information between states for this game.
The context needs to store the number of retrials if the user has one or not the secret number to guess
and the current state.
The state will have an execute state method that accepts one of these contexts and returns true if the
game is finished or false if not I've already written the code.
We are going to use in state DOT go file.
I will explain it step by step.
So as I mentioned previously I have defined the interface game states and the integers secret number
and retrials and the boolean one.
Next we defined the type start state struct as described and acceptance criteria 1.
The player must be able to introduce the number of retrials they want.
This will be achieved by a state called Start state also the start state struct must prepare the game.
Setting the context to its initial value before the player.
So here's the piece of code for this task.
First of all the start state struct implements the game state structure because it has the execute state
context method of boolean type on its structure.
At the beginning of this state it sets the only state possible after executing this one the ask state
state the ask state struct is not declared yet but it will be the state where we ask the player for
a number to guess in the next two lines.
We use the rand package of go to generate a random number in the first line.
We feed the random generator with in 64 type number returned by the current moment so we ensure a random
feed in each execution.
So if you put a constant number here the randomize it will also generate the same number to the rand
dot in the end method returns an integer number between 0 and the specified number.
So here we cover acceptance criteria to next a message asking for a number of re tries to set precedes
the F empty dot f scan f method a powerful function where you can posit an IO dot reader which is the
standard input of the console a format that is number and an interface to store the contents of the
reader.
In this case the re tries field of the context.
Finally we return true to tell the engine that the game must continue.
Let us see the ask state struct which we have used at the beginning of the function.
So here's the ask state struct they ask state struct also implements the game state as you have probably
guessed already.
This state starts with a message for the player asking them to insert a new number in the next three
lines.
We create a local variable to store the contents of the number that the player will introduce.
We use the F empty dot f scan f method again as we did in start state struct to capture the player's
input and store it in the variable and then we have 1 retry less in our counter.
So we have to subtract 1 to the number of is represented in the retry field.
Then there are two checks one that checks if the user has entered the correct number.
In which case the context field 1 is set to true and the next state is set to the finished state struct.
The second check is controlling the number of retrials has not reached 0 in which case it won't let
the player ask again for a number and it will send the player to the Finnish state struct directly.
After all we have to tell the game engine again that the game must continue by returning true in the
execute state method.
Finally we have defined the finish date struct.
It controls the exit status of the game.
Checking the contents of the one field in the context object the finished state struct also implements
the game state by having execute state method in its structure.
The idea here is very simple if the player has won the Finnish state structure will print the message.
Congrats you won.
If the player has not won the Finnish state prints the message you lose.
Remember that the zero value of the boolean variable is false.
In this case the game can be considered finished so we return false to say that the game must not continue.
We just need the main method to play our game.
So we have our main method over here.
Well yes it can't be simpler.
The game must begin with the start method although it could be abstracted more outside in case the game
needs more initialization in the future.
But in our case it is fine.
Then we create a context where we set the next state as pointer to the start variable.
So the first state that will be executed in the game will be the start state.
The last line of the main function has a lot of things just there.
We create a loop without any statement inside it.
As with any loop it keeps looping after the condition is not satisfied.
The condition we are using is the return value of the game state structure.
True.
As soon as the game is not finished.
So the idea is simple we execute the state in the context passing a pointer to the context to it.
Each state returns true until the game has finished and the finished state struct will return false.
So our for loop will keep looping waiting for a false condition sent by the finished state struct to
end the application.
Now save the file and navigate to the terminal.
Now let's play once it asks to introduce a number say 5.
Now let's introduce 8.
Now the third one say 2.
Are we 1.
Let's do it again.
So let's introduce first for next 3 7 9 and the last one say 2 we lost.
We set the number of retrials to 4.
Then we kept inserting numbers trying to guess the secret number.
We entered 3 7 9 and 2.
But it wasn't any of them.
I don't even know what the correct number was.
Let's fix this go to the definition of the finished state struct and change the line where it says you
lose and replace it in the way I do.
Fine.
Now it will show the correct number.
Let's play again before you move to the terminal save the file go run state DOT go.
Let's give 3 6 2 and one.
We again lose.
And the correct number was 8.
This time we make it a little harder by setting only three tries and we lost again.
I entered 6 2 and one the correct number was 8.
Let's play it again.
5 3 4 5 6 8 we lose again.
Let's give it a last try 9 6 14 3 6 and 1.
Great.
This time we lowered the difficulty allowing up to 9 tries and we won.
We even had four more tries left but we guessed the number on the fifth try.
After entering 6 14 3 and 6 the correct number was 1 which was my fifth try.
Have you realized that we could have a winning and a lose state instead of printing the messages directly
in the finished state struct.
This way we could for example check some hypothetical scoreboard in the wind section to see if we have
set a record.
Let's refactor our game.
First we need a win state and they lose state struct.
So let's open the states dots go file which I've created in the same folder above.
The main method I have added the wind state and the loop state.
These two new states have nothing new.
They contain the same messages that were previously in the finished state that by the way must be modified
to use these new states.
Let us modify the Finnish state now the Finnish state doesn't print anything.
And instead delegates this to the next state in the chain the wind state structure.
If the user has won and lose state struct if not remember that the game does not finish on the Finnish
state struct.
Now we must return true instead of false to notified to the engine that it must keep executing states
in the chain.
You must be thinking now that you can extend this game forever with new states.
And it's true.
The power of the state pattern is not only the capacity to create complex FSM but also the flexibility
to improve it as much as you want.
By adding new states and modifying some old states to point to the new ones without affecting the rest
of the FSM in this video we have learned about the state design pattern in the next video.
We will dive into mediator design pattern.