In this video, learn how to create the maze game using the Builder Design pattern. Explore this pattern by creating a counting maze.
- [Instructor] In this video, we will be creating our maze in Python using the Builder Design pattern. The beginning of our code is still the same, not much has changed yet. We still have our MapSite, we have the direction enumeration we have the room and the wall and the door and we have the maze. The first difference in our code using the Builder Design pattern starts by declaring an interface called MazeBuilder.
We created a new method that is like a C, C++ constructor method and then we create different methods. Build maze, build room, build door and get maze, which will return the constructed maze. Now what's interest is that each of those methods are basically empty, they do not return anything. There's a reason for this. In the Builder Design pattern, we allow subclauses to only override the methods they are interested in.
We are not raising any exceptions here, we just say this is the interface. You can override it, implement it if you wish. If you don't then just leave it alone. Now in order to build a maze, we use the same maze scheme class and we create our maze, but this time we are passing in an builder object and it can be a different builder. What the builder does is it builds a maze. This case, it builds room number one, room number two and after having created two rooms, it builds a wall in between these two rooms.
In the end, the builder object will return the maze we have created. We can define in Python an interface as we would do in C or C++ which usually would be a dot h header file, just to show what it would look like in Python. Here, our init method would be the constructor, build maze is a method, build room takes a number, the room number and build door takes two rooms to build a door from room one to room two and get maze then will return the constructed maze.
There is also another method and see it will be private, C++ so the common wall is between room one and room two and we would need to know the direction of the two rooms, where the wall is, east, west, south, north. Here our private member holds the maze that's being constructed. Implementation of standard maze builder can look like this. We inherit from maze builder in our constructor initializer, we create a member variable to hold the maze we are going to build.
In the build maze method, we are calling the maze class and create an instance of it and assign it to our member and build room, which we are overriding from the abstract maze builder interface, we are trying to retrieve the room number N and if it doesn't exist, then we fall into the exception handler and we will build our room. Create a room, edit to the maze, and then what's interesting here is that all sides of the room are walls, no door yet.
The next method, build door, then we'll look for the room number one and two and it will set a door between room one and room two in the direction that meets them and between room two and room one in that adjoining direction. Another method is the common wall method, which finds the wall that's common between a room and another room.
Now here we have to define a rule and what design patterns are about is basically to explain the creation process, not so much to play around with different implementations, so in order to keep things simple, what we've done here is we are seeing if the number of a room is less than the other room, then direction is east and the other way around, the direction is west, so this way we are building rooms from the left, west, to the right, east and if the number one, two, three, four is less than, then our direction of the door is on the east, if it's greater than, it's on the west.
We are now in a position to build a maze using the standard maze builder. What we do is we assign our maze a maze variable and we create a maze game, save it in this game variable, and then we create an instance of the standard maze builder call it builder and now we use the game, or the create maze function on it and pass in our builder. After the builder has finished creating the maze, we call the get maze method on the builder and that will retrieve the maze, so let's run it.
What we can see here, first we are looking for room one and room one does not exist, so we are building this room. Then room two, same thing, it didn't exist yet so we are building it and we can see, after we put a door in between room one and room two, the door object is the same object here and for room one because the number is less than room two, the door direction is on the east, while for room two the same door its direction, its wall is on the west.
The maze game clause, first create a maze which is a regular maze and we pass in the builder which builds the maze, creates two rooms and then builds a door between those two rooms and in the end returns the maze that the builder built. You can also create a complex maze and what that means is we can build one room all the way to 1000. We're building a maze consisting of 1000 rooms and then we return the maze.
Now we didn't put any doors in between those rooms because we didn't have to, so that's up to us. We did not have to override the build door method or calling. We can also create and build other maze builders using the same base class interface, maze builder. In this case we are creating a Counting Maze builder. It has some private members, of course in Python nothing is private, so we're using a leading underscore to just indicate and so we treat it like a private member.
Here we have the build maze method, the build room, the build door and we're adding an add wall method which does not exist in the interface of maze builder and now what we are returning here is the counts because what we are doing in the implementation is we're not building a maze at all, we are just incrementing some counters and we are seeing when we call build room, when we call build door, and when we call get counts instead of get maze, we are just returning the numbers of rooms and doors that would have been built, but we didn't build a maze at all.
Now we can build our two mazes. First the standard maze, as we've done before, and then the Counting Maze which is new. What's interesting here is that the code game.CreateMaze passing in the builder and then we get back builder, get maze and down here we do the same thing, game, create, passing in the builder or in this case we're passing in the Counting Maze builder, which is part of the Builder Design pattern and instead of getting back the maze, we're getting the counts and it's a two pull so we're assigning that to rooms and doors and we can run it and we get the result, first part is the same, second part says the maze has two rooms and one doors.
Note: This course was created by Packt Publishing. We are pleased to host this training in our library.
- Running Python programs within Eclipse
- Setting breakpoints
- Using the PyDev debugger
- Using design patterns
- Creating a GUI application with Tkinter
- Writing a Windows scheduling service