Lecture thumbnail 0:00 / 0:00 All right.
So what we’re going to take a look at now is a much simpler way of defining state machines that doesn’t
involve a centralized location where you define the transitions between different states.
So we looked at a way of defining transitions in a single dictionary, which kind of defines all the
starting states, the triggers as well as where you end up with.
But you can avoid that completely.
So we’re going to look at a simpler scenario.
We’re going to model a combination lock, and that combination lock is going to be in one of three different
states.
So we’re going to have a state locked.
That’s when the combination lock is actually locked.
We’re going to have the state fail.
That’s when you enter an incorrect code.
And so we should print fail on the screen.
And then the unlocked state, that’s where you enter the correct code and the combination lock is actually
open.
So what I’m going to do here is I’m going to define, first of all, the code that opens the lock.
I’m also going to define the initial state.
So let’s call this state locked, and then I’m going to define the entry.
Now, the entry is going to be a sequence of digits that the user has tried to enter as they are actually
opening the lock.
So I’m going to have a string builder modeling this particular thing.
So we’re going to have a string builder like so.
And then what I’m going to do is I’m going to build a state machine, but I’m going to do it differently.
I’m going to make an infinite loop.
So it’s going to be a while True.
And inside that loop, I’ll have a switch on the state.
So we’re going to handle each one of the states right inside this loop.
So I’ll generate the different labels here.
Now, we don’t really need the argument out of range exception because we know we are limited by the
three possible states defined here.
And so let’s actually implement them.
I’m going to begin by implementing the failed state.
That’s when you enter an incorrect code.
And so the lock tells you that you have failed, but maybe the lock allows you to type in stuff once
again.
So let’s actually first of all, write line.
The word failed.
I’m going to make the word erase whatever the user has actually entered.
So I’m going to say console dot cursor left equals zero here.
So I’m going to go back to the start of the line and then I’m going to overwrite the word failed over
the actual digits that the user tried to enter.
I’ll clear the entry.
So that’s the entry that the user has been accumulating the digits that were meant to open the code.
And then I will set the state to state dot locked.
Okay.
So after this, what happens is if you fail to enter the correct code, what happens is that we print
failed, but then we clear the entry and set the state back to locked so you can try entering the code
again.
And this is the place where you would, for example, count the number of failed attempts and then correct
them somehow.
So in addition to this, let’s implement the unlocked state.
That’s the good one.
That’s when you finally manage to unlock the whole thing.
So once again, I’ll say console dot cursor left equals zero console dot write line equals well console
dot write line unlocked in this case, and I’m going to return from the program because, well, there’s
nothing else to demonstrate, is there?
Now the lock state is the one that’s interesting because that’s where we actually get the user’s input.
So we have this stringbuilder called entry, which actually keeps every single digit.
So we append to that entry the user’s input.
So we say console dot read key.
So with a single key without waiting for the line break for the carriage return to be entered and we
get the key char from that to actually put into the stringbuilder.
And then of course we can compare the stringbuilder with the code.
So if entry dot two string is in fact equal to the, then what we can do is we can say that the state
is unlocked in this particular case and just break from here.
Now another case is we need to make sure that the user keeps entering the right digits.
So if the code does not start with the stringbuilder entry, that means the user has entered an incorrect
digit.
And so we set the state to failed.
So we say state equals state dot failed and that’s pretty much it.
All right.
So as you can see, we are in an infinite loop, which means that as the state switch from one to another,
you keep coming back to checking every single state inside the switch statement and performing the appropriate
calculation.
So the program is actually done.
And this is something that we can actually run right now and see what the output is.
All right.
So here we are.
We have this input panel.
Now, if I type one, two, three, one, notice it overwrites failed.
If I type A six that writes failed once again, if I say one, two, one that says failed.
But if I say one, two, three, four, it says unlocked, which is what we wanted in the first place.
So the takeaway from this demonstration is that it’s not always necessary to define the transitions
in terms of some sort of dictionary or some sort of formalized structure, because in the case of a
switch that you keep going through again and again and again, you can actually get.
The transitions as simple assignments here.
Now another thing that you can do in addition to having an infinite loop like this is you can actually
jump from one case of the switch to another case of the switch.
And this is also very interesting because essentially what you can do at any location, like, for example,
here, the state is failed.
And let’s imagine there is no infinite loop.
What you can do now is you can say something like the following.
So instead of doing this, for example, you could say go to case state dot failed because guess what?
C-sharp allows you to jump from one switch case to another and thereby you can orchestrate the entire
state machine as a set of transitions from one switch case to another switch case, which is also very
possible.
Of course, it involves the use of the eval goto keyword, but I don’t mind.
I think that in this particular case it might be warranted and the up side of this implementation,
as opposed to having a dictionary full of transitions, is you can do other things besides and everything
is kind of human readable.
You have your case, the case is indented by two spaces, as you can see here.
And in the case you can actually read what’s going on and you can sort of follow the code along instead
of, you know, having to jump to some formalized structure that exists somewhere else.
So it’s certainly well and good to use formalized structures or indeed external frameworks.
But if you have a very simple state machine like the one here, then perhaps having a switch is a more
palatable, more understandable approach.
Play Play Play Stop Play Play Start Play information alert