Rush Hour is one of my favorite puzzle games of all time. It's applications in computer science are great, but the game is just really fun to play and very addictive.
The basic premise of the game is that there is a 6 x 6 square board. On that board can be placed various cars (which take up 2 spaces) and trucks (which take up 3 spaces). There is one exit on the right side of the board on the third row from the top. Also on this row is the red car. Your objective is to get the red car out of the board. Simple, right?
While the online version is fun, if you can get your hands on the real version, it's awesome.
This first challenge is pretty straight forward: Given some kind of input, can you do the following:
- Create a representation of the board with the cars on it (this will be your model)
- Represent that board in a view on the page (it does not need to be interactive)
- Move vehicles around at random (your controller)
The input is pretty simple. It will be a string that is exactly 36 characters long. Each car will have a designation and an empty space will have a 0. So, for the above starting position, the input would be as follows:
Or, written a different way:
111000 203444 203RR5 677805 60089A BBB89A
As in all things computer science, the eminent Sean Byrnes (founder of Flurry and one badass engineer in his own right) has weighed in and thinks that a better representation of the input is necessary (see the bottom, where I mention that your reviewer is there to make you better and is not necessarily your friend).
Sean's recommendation is that the input should be in JSON format, should be an array of arrays and should use * instead of 0 for the blank spaces.
Sean goes on to further say that this allows several advantages over the simple string input:
1. Immediate validation of board size
2. It is easy to do a check that an empty space is not a valid alpha-numeric character
Sean is absolutely correct. Your first action should be to take Sean's advice and convert the string into the format he recommends.
The reason that JSON has become so popular is that it can be read in as a "string" and directly manipulated as an object. Here is an example of what our input might look like if it was represented as JSON:
So, if you wanted to get the 1st element of the 0th row, you could do this:
var square01 = myboard.board;
This is a great way to represent your board internally and allows you a lot of flexibility.
So, how do you go from the input string to the JSON? Is it better to deal with the JSON or the string?
While it may be tempting to let the string represent your model, don't do this. Instead, you should create a Board object which will take a set of Vehicles. The input to initialize the Board object will be this string. A Board should also be able to output it's current configuration in the exact same string format.
A Vehicle should know its orientation and be able to tell the Board to move it in one of the two directions. It should also know its identification on the Board. If a Vehicle asks to move, the Board will respond if it is a legal move, at which point the Vehicle will or will not update its location on the board.
A Vehicle is easily broken into two classes, a Car and a Truck. Make of this what you will, but remember, a single vehicle can only move in two directions. If it is facing north/south, it can only move up/down. If it is facing east/west, it can only move left/right.
Object Oriented programming
There are several tenets of OOP that you should keep in mind for this project (depending on where you Google, you will find others):
- Inheritance: Given a class, another class can be a sub-class of the parent class. That sub-class will inherit all of the properties of the parent class. In our sample, inheritance comes into play with the Vehicles class. It might make sense to have two sub-classes of Vehicle, that of Car and Truck. The primary difference is that each is a Vehicle but the Car is aware that it takes up two squares while the Truck is aware that it takes up three squares. In either case, a Car or a Truck can be interacted with as simply a Vehicle.
- Message Passing: When interacting with objects, you ask the object to do the work for you. If, for instance, you want to move a particular Vehicle, you may ask the Board to move that Vehicle for you. It will return true if it moved, or false if it was not a valid move. If the board moves the Vehicle, it will update its representation itself to account for this.
Whenever a Vehicle makes a valid move, you should update your view. Your view can be any representation you choose. If you want to get fancy, you can mimic the Thinkfun UI. It could be a set of colored squares, or you could even choose to represent it as the output of the Board configuration.
Sitting between the two is your controller. It will tell the model to update, then ferry that update to the view.
For this assignment, have your controller issue random moves to the Board and see how things move around.
We are going to use a professional model in our development. You should set up a git repo to house your code and have a master branch. You will never make updates on your master branch, but will instead do all of your development on a feature branch. The only time this is not true is during your first initialization.
It is often advantages to make your feature branches as small as possible, containing a single feature change. Once a new feature is complete, you will push it to your origin and then issue a Pull Request to your reviewer.
Your reviewer is here to make you better. They are not necessarily here to be your friend. They will strongly critique your code and you will often make multiple changes before your reviewer accepts your PR.
When your PR is accepted, it will be merged back to master. At that point, you may pull the latest to your local master and then set off on your next feature.
Here are a few git commands to make your life easier, but I expect that Stack Overflow will answer the bulk of them better.
Create a new branch: git checkout -b mynewbranch Switch to an existing branch: git checkout master Add a file to the existing branch: git add filename Commit a series of files: git commit -m "commit message" Push a commit to the origin: git push origin mynewbranch Pull a branch down to your local: git pull origin master
Look into Dijkstra's algorithm and consider how we're going to make this part of our solver.