Toy Robot

August 2017 · 8 minute read

I have recently challenged my skills with the infamous toy robot simulator challenge and thought it would be great to document my thought process throughout the build. Not only can other see how I’ve gone about moving from A to B, but I can also gain a better insight into my own processes.

The completed project can be viewed at



The criteria for this program rings a bell, so the first thing I’m going to do is look back through some of own work to review two projects I’ve started working on in the past which can be directly useful to this challenge.


The first thing I’ve done is made some notes about what I’m trying to achieve. How the app might be structured and where methods might occur within that structure.

What methods belong where:


5x5 square

valid input coordinates x & y == 0..4


Input value

  Valid if == “PLACE X,Y,F” || “MOVE” || “LEFT” || RIGHT” || “REPORT”

  X & Y == INT (0..4)

  F == “NORTH” || “SOUTH” || “EAST” || “WEST”


Initialised at position == NULL*


  Place robot on table at position x,y,f

  Check: Is the position valid?


      Move forward 1 space in the direction I am facing

      Check: If I move forward, will the new position be valid?


      Turn 90 degress to left


      Turn 90 degrees to right


      output current coordinates

App Structure

- /lib
	- table.rb		(define table vars)
	- robot.rb		(define robot vars)
	- position.rb		(define robots position on the table)
	- place.rb		(place robot and validate the new position is valid)
	- handle_input.rb	(manage the place and move commands)
	- direction.rb		(manage the robots facing direction)
	- move.rb		(move robot to new coordinates if new position is valid)
	- report.rb		(print our report data)
- /spec
- .rspec
- .ruby-version
- toy_robot.rb
- Gemfile
- Gemfile.lock


Initialise Repo

First thing with any project, of course is to create a new repo on Github with a, clone it to your local and you’re good to go!

Directory Structure

I’ve already thought about how the app will structured, so I can start by generating the appropriate root files.

- Create a .ruby-version file
- Create Gemfile with rspec spec
- Generate your gemfile.lock $ gem install bundle && bundle install
- Initialise Rspec $ rspec --init
- Create the lib dir for the project files
- Create the project root file toy_robot.rb

Table class

First thing I think of is that I need a table to put the robot on. For this I simply need to specify an area that is 5x5. Now is also a good time add in a simple validation checking that any position on the table is within that 5x5 area.

User Input

For me, I like to have some sort of visuals so the next thing I’ll do is initialise the main loop to get user inputs. I’ve don’t this before both with the Elevator and Ordering programs I wrote when I was learning Ruby, so it should be a breeze.


Now that I have a table class and loop for reading user inputs that work successfully, it’s time to start testing!

The rest of the project will be test-driven, meaning I will try to write tests ahead of or at the same time as code. I will then ensure that all existing tests pass before committing anything else to my repo.

Robot class

I’ll now need to define a robot to be ‘placed’ on the table. The first thing I’ll need to know is what coordinates (x & y) is the robot being place at?

Position class

I need to define position coordinates x, y and update the robot’s position when a user inputs “PLACE x,y”

- Define position coordinates x and y
- Update robot.position
- Check that the robot’s position is now not nil

Validate position

The only way to be sure that the robot’s new position is valid within the table’s 5x5 area is to check it against the Table#is_valid method.

HandleInput class

I need to handle user inputs and ensure the commands being parsed are valid

- Array of valid command patterns
- Match input to one of those patterns

- If input matches, do the action
- else return

- if robot.not_in_place? 
- the only valid command is ‘place’

Place method

One of the criteria for ‘placing’ a robot is to also tell it what direction it needs to be facing. I’ll start by updating the test code to expect a direction - this will help me quickly pinpoint the locations that need to be updated through out my code base.

Direction class

I’m not sure yet how the #left and #right methods are going to fit in with the rest of the app, so I’ll start by defining an array of valid directions which I will iterate over to get the next or previous value, depending on which starting position was parsed.

- Define turn_right to check that the direction is valid and locate that direction in the directions_array
- Find the index of the current direction in the directions_array
- Iterate the directions_array to find the next direction’s value

Right turn method

The right method needs to check whether the current direction is the last item in the array, if it is I can instead simply return the first value in the directions_array.

- Check if the current direction is the last value in the array
    * If it is the next direction will be the first value in the array.

Once the turn right method is working, I can then integrate my direction class with user inputs to update the robot’s position when the right command is parsed.

Left turn method

Essentially the reverse of the right_turn method. I can also refactor here since two methods are almost identical.

- Define turn_left method ( essentially the reverse of turn_right )
- Refactor theses two methods to increase flexibility

Move method

To move the object, I’ll need to know: What is my current position, made up of x,y,f and what are the rules for moving in each direction?

- If direction == North
- x stays the same
- y increase by 1

- If direction == East
- x increases by 1
- y stays the same

- If direction == South
- x stays the same
- y decreases by 1

- If direction == West
- x decreases by 1
- y stays the same

Report method

The report method simply needs to display the current position of the robot at the time when when the method is called.

User Testing

Having implemented all of the spec features and ensured that the tests pass, I have reviewed the specs and tested the program manually to ensure everything is working as it should. I’ve found an issue where the MOVE action returns a false position validation but still updates the robot position.

To fix this, the best solution is to break down the problem and code to see where it’s going wrong. At this point, I have just commited a big chunck of unrefined code because you can’t refine code until you get it working in the first place!


Now that I have working code which meets all of the project specs, I have a valid MVP (minimum viable product). Now is the time to go through, tidy up refactor and optimise my code.


Now that my project is looking more complete, I will revise my top level documentation and update the README.


Review Code

Before passing code on for someone else to look at, it’s always good practice to review it yourself and see if there are any more improvements that you can make or if you have any specific areas that you think could be improved but your not sure how to implement. I will also review each method to ensure that any possible exceptions are being handled.

Review Tests

I have written tests throughout the build process and ensured that they pass before committing any new changes. To ensure the robustness of this product, I’m going to review all of the test code to see if there’s anything I’ve missed and to make sure that the tests are relevant. I’ll add any additional tests I can think of.

User Testing

Upon testing, I have found that I missed an exception - when user presses enter without inputting a command, the program exits. This empty command should be ignored.

Sample Data

The final criteria in the project spec is to produce some sample data output and show that the program works according to specs


Like with any project, this can undoubtedly be improved. At this stage, however, I am pleased with what I have produced. I feel that my code is clean and simple with smart methods that don’t try to take on too much.

In saying that, I am also eager to hear feedback which will hopefully open my eyes to something I hadn’t previously thought of.