Update

We have updated the content of our program. To access the current Software Engineering curriculum visit curriculum.turing.edu.

Iteration 1 - Ships and Cells

Back to Battleship Home Back to Requirements

Test Driven Development

In this iteration, you are required to use TDD to create your classes. Use the interaction pattern to determine what a method should do and write one or more tests to verify that expected behavior. Then you can implement the method. You should always write code with the purpose of making a test pass.

Ship

A Ship object will represent a single ship on the board. It will be able to keep track of how much health it has, take hits, and report if it is sunk or not. A ship should start off with health equal to it’s length.

The Ship class should follow this interaction pattern:

pry(main)> require './lib/ship'
#=> true

pry(main)> cruiser = Ship.new("Cruiser", 3)
#=> #<Ship:0x00007feb05112d10...>

pry(main)> cruiser.name
#=> "Cruiser"

pry(main)> cruiser.length
#=> 3

pry(main)> cruiser.health
#=> 3

pry(main)> cruiser.sunk?
#=> false

pry(main)> cruiser.hit

pry(main)> cruiser.health
#=> 2

pry(main)> cruiser.hit

pry(main)> cruiser.health
#=> 1

pry(main)> cruiser.sunk?
#=> false

pry(main)> cruiser.hit

pry(main)> cruiser.sunk?
#=> true

Cell

A Cell object is a single cell on our board. A Cell can either contain a Ship or nothing.

pry(main)> require './lib/ship'
# => true

pry(main)> require './lib/cell'
# => true

pry(main)> cell = Cell.new("B4")
# => #<Cell:0x00007f84f0ad4720...>

pry(main)> cell.coordinate
# => "B4"

pry(main)> cell.ship
# => nil

pry(main)> cell.empty?
# => true

pry(main)> cruiser = Ship.new("Cruiser", 3)
# => #<Ship:0x00007f84f0891238...>

pry(main)> cell.place_ship(cruiser)

pry(main)> cell.ship
# => #<Ship:0x00007f84f0891238...>

pry(main)> cell.empty?
# => false

Additionally, a cell knows when it has been fired upon. When it is fired upon, the cell’s ship should be damaged if it has one:

pry(main)> require './lib/ship'
# => true

pry(main)> require './lib/cell'
# => true

pry(main)> cell = Cell.new("B4")
# => #<Cell:0x00007f84f0ad4720...>

pry(main)> cruiser = Ship.new("Cruiser", 3)
# => #<Ship:0x00007f84f0891238...>

pry(main)> cell.place_ship(cruiser)

pry(main)> cell.fired_upon?
# => false

pry(main)> cell.fire_upon

pry(main)> cell.ship.health
# => 2

pry(main)> cell.fired_upon?
# => true

Finally, a Cell will have a method called render which returns a String representation of the Cell for when we need to print the board. A cell can potentially be rendered as:

  • ”.” if the cell has not been fired upon.
  • “M” if the cell has been fired upon and it does not contain a ship (the shot was a miss).
  • “H” if the cell has been fired upon and it contains a ship (the shot was a hit).
  • “X” if the cell has been fired upon and its ship has been sunk.

Additionally, we will include an optional boolean argument to indicate if we want to reveal a ship in the cell even if it has not been fired upon. This should render a cell that has not been fired upon and contains a ship as an “S”. This will be useful for showing the user where they placed their ships and for debugging.

pry(main)> cell_1 = Cell.new("B4")
# => #<Cell:0x00007f84f11df920...>

pry(main)> cell_1.render
# => "."

pry(main)> cell_1.fire_upon

pry(main)> cell_1.render
# => "M"

pry(main)> cell_2 = Cell.new("C3")
# => #<Cell:0x00007f84f0b29d10...>

pry(main)> cruiser = Ship.new("Cruiser", 3)
# => #<Ship:0x00007f84f0ad4fb8...>

pry(main)> cell_2.place_ship(cruiser)

pry(main)> cell_2.render
# => "."

# Indicate that we want to show a ship with the optional argument
pry(main)> cell_2.render(true)
# => "S"

pry(main)> cell_2.fire_upon

pry(main)> cell_2.render
# => "H"

pry(main)> cruiser.sunk?
# => false

pry(main)> cruiser.hit

pry(main)> cruiser.hit

pry(main)> cruiser.sunk?
# => true

pry(main)> cell_2.render
# => "X"

Lesson Search Results

Showing top 10 results