3
\$\begingroup\$

I have written a simplified version of the Mars Rover challenge in Ruby. Please review it for best coding practices.

A rover’s position and location is represented by a combination of x and y co-ordinates and a letter representing one of the four cardinal compass points. The plateau is divided up into a grid to simplify navigation. An example position might be 0, 0, N, which means the rover is in the bottom left corner and facing North.

In order to control a rover , NASA sends a simple string of letters. The possible letters are ‘L’, ‘R’ and ‘M’. ‘L’ and ‘R’ makes the rover spin 90 degrees left or right respectively, without moving from its current spot. ‘M’ means move forward one grid point, and maintain the same heading.

class Rover
 def initialize(x, y, direction)
 @x = x
 @y = y
 @direction = direction
 end
 def instruction(position)
 position.each do |input|
 if input == 'L'
 left
 elsif input == 'R'
 right
 else
 move
 end
 end
 puts "this is where the rover should be: x= #{@x} y= #{@y} facing= #{@direction}"
 end
 def right
 if @direction == 'S'
 puts "the rover is facing West."
 @direction = 'W'
 elsif @direction == 'N'
 puts "the rover is facting East"
 @direction = 'E'
 elsif @direction == 'W'
 puts "the rover is facting North"
 @direction = 'N'
 else
 puts "the rover is facing South"
 @direction = 'S'
 end
 end
 def left
 if @direction == 'N'
 puts "the rover is facing North."
 @direction = 'W'
 elsif @direction == 'W'
 puts "the rover is facting West"
 @direction = 'S'
 elsif @direction == 'E'
 puts "the rover is facting East"
 @direction = 'N'
 else
 puts "the rover is facing South"
 @direction = 'E'
 end
 end
 def move
 if @direction == 'N'
 @y += 1
 elsif @direction == 'E'
 @x += 1
 elsif @direction == 'S'
 @y -= 1
 else
 @x -= 1
 end
 end
end
#instance of our rovers with direction x, y, direction facing N, E, S, or W
mars_rover_a = Rover.new(0,0,'N')
# mars_rover_a.move()
mars_rover_b = Rover.new(1,1,'E')
#call the instruction for each instance of the object rover
mars_rover_a.instruction(['L','M','R','M','L','M','R','R','M'])
mars_rover_b.instruction(['R','M','M','L','M','L','L','M'])
asked Mar 31, 2019 at 20:12
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

I'd suggest that the position, and maybe orientation also, ought to be its own object ... "Location"?

I'd also prefer to use symbols rather than strings where possible, and rely on data rather than logic (see use of hashes below).

You might be interested in implementing a builder method, in which the methods called simply return the original object, which allows commands to be daisy-chained ...

class Location
 LEFT = {
 n: :w,
 e: :n,
 s: :e,
 w: :s
 }
 RIGHT = {
 n: :e,
 e: :s,
 s: :w,
 w: :n
 }
 def initialize(x:, y:, direction:)
 @x = x
 @y = y
 @direction = direction
 end
 def left
 @direction = LEFT.fetch(@direction)
 self
 end
 def right
 @direction = RIGHT.fetch(@direction)
 self
 end
 def move
 case direction
 when :n
 self.y += 1
 when :e
 self.x += 1
 when :s
 self.y -= 1
 when :w
 self.x -= 1
 end
 self
 end
 attr_reader :x, :y, :direction
 private
 attr_writer :x, :y, :direction
end

Hence:

2.4.5 :125 > l = Location.new(x: 0, y: 0, direction: :n)
 => #<Location:0x00007f9f5329e858 @x=0, @y=0, @direction=:n> 
2.4.5 :126 > l.left.move.right.move.left.move.right.right.move
 => #<Location:0x00007f9f5329e858 @x=-1, @y=1, @direction=:e> 
answered Apr 3, 2019 at 12:21
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.