Thursday 7 July 2011

The abstractions ....

The Direction and types...

namespace MarsRover
{
abstract class Direction
{
public abstract Direction GetLeft();
public abstract Direction GetRight();
public abstract Position GetNext(Position pos);
}

class East : Direction
{
public override Direction GetLeft()
{
return new North();
}

public override Direction GetRight()
{
return new South();
}

public override Position GetNext(Position pos)
{
pos.X++;
return pos;
}

public override string ToString()
{
return "East";
}
}

}


The step and steps....

namespace MarsRover
{
abstract class Step
{
public abstract Position GetPosition(Position position);
}

class LeftRotation : Step
{
public override Position GetPosition(Position position)
{
position.Direction = position.Direction.GetLeft();
return position;
}
}

class Move : Step
{
public override Position GetPosition(Position position)
{
return position.Direction.GetNext(position);
}
}
}

namespace MarsRover
{
abstract class Plateau
{
public abstract bool IsPositionOutOfRange(Position pos);
}

class RectPlateau : Plateau
{
readonly int x;
readonly int y;

public RectPlateau(int x, int y)
{
this.x = x;
this.y = y;
}

public override bool IsPositionOutOfRange(Position pos)
{
return ((x < pos.X) || (y < pos.Y))
? true
: false;
}
}
}

Check the class diagram


Few classes:

Controller - The main class: with all the I/O

using System;

namespace MarsRover
{
class Controller
{
public static void Main(String[] args)
{
try
{
Plateau plateau = Factory.CreatePlateau("5 5");
Rover rover = Factory.CreateRover("1 2 N");
String instruction = "LMLMLMLMM";
Position pos = Process(plateau, rover, instruction);
Console.WriteLine("Rover position is " + pos.X + " " + pos.Y + " " + pos.Direction);

rover = Factory.CreateRover("3 3 E");
instruction = "MMRMMRMRRM";
pos = Process(plateau, rover, instruction);
Console.WriteLine("Rover position is " + pos.X + " " + pos.Y + " " + pos.Direction);
}
catch (Exception ex)
{
Console.WriteLine("Exception occurred" + ex.Message);
}
Console.ReadKey();
}

public static Position Process(Plateau plateau, Rover rover, String instructions)
{
foreach (char instruction in instructions)
{
rover.ProcessStep(Factory.CreateStep(instruction));
if (plateau.IsPositionOutOfRange(rover.Position))
{
throw new PositionOutOfRangeException("The Rover is out of Plateau.");
}
}
return rover.Position;
}
}
}



The Factory: All the creations happen here.


using System;

namespace MarsRover
{
class Factory
{
public static Plateau CreatePlateau(String dimensions)
{
try
{
String[] split = dimensions.Split(new[] {' '});
int side1 = Int32.Parse(split[0]);
int side2 = Int32.Parse(split[1]);
return new RectPlateau(side1, side2);
}
catch (Exception ex)
{
throw new InvalidInputException(string.Format("Failed to create Plateau from give dimensions:{0}. Exception is {1}", dimensions, ex.Message));
}
}

public static Rover CreateRover(String coordinates)
{
try
{
String[] split = coordinates.Split(new[] {' '});

int side1 = Int32.Parse(split[0]);
int side2 = Int32.Parse(split[1]);
string hint = split[2].Trim();

Direction direction;
switch (hint[0])
{
case 'N':
direction = new North();
break;
case 'E':
direction = new East();
break;
case 'S':
direction = new South();
break;
case 'W':
direction = new West();
break;
default:
throw new InvalidInputException("Invalid direction specified.");
}

Position pos = new Position(side1, side2, direction);
return new Rover(pos);
}
catch (Exception ex)
{
throw new InvalidInputException(string.Format("Failed to create Rover from give coordinates:{0}. Exception is {1}", coordinates, ex.Message));
}
}

public static Step CreateStep(char instr)
{
switch (instr)
{
case 'L': return new LeftRotation();
case 'R': return new RightRotation();
case 'M': return new Move();
default:
throw new InvalidInputException(string.Format("Failed to create step from given instruction: {0}" + instr));
}

}
}
}