XNA Game – Rotation – Mapping out the main game objects – Part 5

This will be the first blog post where I will upload the latest version of the source code.  Giving you the chance to look through what I’m doing.  Before we get to that I’m going to list out the main objects in the game and what their purpose is:

Letter – Represents a letter at it’s lowest level, it is essentially a character and it’s points value

Tile – A tile contains a letter, I picture a tile like a tile in the game of Scrabble

Square – A square is a position where a tile can be, in terms of Scrabble again there are many squares on the board each of which can contain a tile.

Board – A collection of squares (and their position relationships) with one another

The first objective is to work out how we can build a board.  At the moment we are only talking about building the board in the sense of the relationship of the objects in memory not how the board will be drawn graphically (we will handle graphics in a later post).  In case you have forgotten here is what the board looks like:

board

Before we dive in and just model out the board we need to think a little into the future as to how the game is going to work.  When finding which words have been made we will need to have a way of extracting all of the letters that are next to each other both horizontally and vertically.

To do this we need a way of modelling rows and columns.  A row is simply a list of a list of squares and a column is the same.  So we can define to properties on Board to be:

public List<Line> Rows { get; private set; }		
public List<Line> Columns { get; private set; }

Where Line is essentially a wrapper class that is a List<Square>.  Now looking at how the board needs to be we can write some tests to assert those facts.  Firstly we need a test to assert that we have the right number of squares in each row and column.  Row 1 should have 1 square, row 2 should have 3 squares etc.  And the same can be said for columns.

The second test for a successfully created board is that the instance of a square is shared between the row and column.  This is most important.  By using both rows and columns we are really storing redundant data.  Technically using only the information in the Rows collection we could ascertain everything we need to (and the same can be said for Columns).  The reason that we are using two collections is to make evaluation much easier for ourselves later due to the shape of the board.

So to test that the Rows and Columns collections point to the same set of tests we need to setup a board and then simply test each square in each row is the same as it’s corresponding square in the column.  E.g. the first square in the first row should be the same as the first square in the fifth column.  See the BoardCreation.cs file for the complete tests.

Now we have the tests we need to go about implementing them and making them pass.  To create a board we are going to use a BoardFactory.  The board factory will be responsible for setting up a board in a good state.  By using the factory pattern we can easily swap out this factory we are about to write for a different one in later levels of the game for example.

To implement the BoardFactory we are going to need two loops (there is probably a way to do it with one but that just melts my mind to think about).  The first loop is responsible for creating the rows.  This is relatively simple (view the source code to see the implementation of this).  The harder part is the second loop the one that’s looping around the rows and creating columns for the same squares.

We are going to create the columns from left to right.  What we are doing for each column is selecting out the square from the rows collection and adding it to the column collection.  The key thing here are the two sequences that we need to correctly iterate around the row collection to select them into the column collection.  The first sequence that we need it to iterate around the correct row.  If you look at the board the first column needs one square from the 5th row.  The second column needs three squares from rows 4, 5 and 6.  The third column needs 5 squares from columns 2, 3, 4, 5 and 6.  Hopefully a pattern is emerging by now.  Back to our tests we need to create RowIndexSequenceGenerator class that is responsible for creating this sequence.  You can see the class and full tests for it in the code.  The other sequence that we need is one to loop around the square index in the row.  The first column needs square index 0 (from row 5), the second column needs square index 0 (from row 4), 1 (from row 5) and 0 (from row 6).  The third column needs square index 0 (from row 3), 1 (from row 4), 2 (from row 5), 1 (from row 6) and 0 (from row 7).  You can check out the full implmentation for the class and specs in the LineIndexSequenceGenerator and LineIndexSequenceGeneratorSpecs respectively.

Once we have both of these sequence generator classes the second loop becomes much easier.  A problem like this highlights how much TDD can help you.  We had a relatively tough problem in getting the second loop right.  This was made so much simpler by breaking it down into smaller components and writing tests for them.  Then when we put them all together to function as a whole it works first time.  Simples.

Download the code so far from here. Feedback welcome on the code or if you have any questions let me know.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s