title: How do I structure a validation loop to ensure that random placed ships fall within bounds?
body: <p>Here is a stripped-down class for Board, and one for Ship.</p>
  
  <p>What I can't get to work is, when I make a new instance of Ship, I want the values to be checked with <code>Board.new.within_board_bounds(ship)?</code> before it creates my new object.</p>
  
  <p>If the return value is false, I want the <code>initialize</code> method to run again until the test returns true. Only then will the ship object be instantiated.</p>
  
  <p>I tried recursively calling <code>Ship.new</code> every time the test value is false, and tried a <code>while</code> loop calling <code>Ship.new</code>, all with unfortunate results.
  What's the right way to do this?</p>
  
  <pre><code>class Board
  
    def initialize
      @grid = {
          1 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          2 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          3 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          4 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          5 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          6 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          7 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          8 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          9 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."},
          10 =&gt; {"A"=&gt;".", "B"=&gt;".", "C"=&gt;".", "D"=&gt;".", "E"=&gt;".", "F"=&gt;".", "G"=&gt;".", "H"=&gt;".", "I"=&gt;".", "J"=&gt;"."}
      }
    end
  
    def within_board_bounds?(ship)
      return false if ship.row + (ship.shipspan) &gt; 10 &amp;&amp; ship.direction == "down"
      return false if ship.row - (ship.shipspan) &lt; 0  &amp;&amp; ship.direction == "up"
      return false if ship.col + (ship.shipspan) &gt; 10 &amp;&amp; ship.direction == "right"
      return false if ship.col - (ship.shipspan) &lt; 0  &amp;&amp; ship.direction == "left"
      true
    end
  end
  
  class Ship
    attr_reader :shipspan, :size, :row, :col, :ship_type, :direction
    def initialize(ship_type)
        @row = rand(10) + 1                                    # 1-10
        @col = rand(10) + 1                                    # 1-10
        @colAlpha = [0, 'A', 'B', 'C', 'D', 'E',
                    'F', 'G', 'H', 'I', 'J'][col]              # A-J
        @direction = ['up', 'down', 'right', 'left'].sample    # up, down, right, or left
        case ship_type
          when 'Aircraft Carrier'
            @size = 5
            @shipcode = 'A'
          when 'Battleship'
            @size = 4
            @shipcode = 'B'
          when 'Cruiser'
            @size = 3
            @shipcode = 'C'
          when 'Destroyer'
            @size = 2
            @shipcode = 'D'
          when 'Submarine'
            @size = 1
            @shipcode = 'S'
          else
            @size = 0
            @shipcode = '?'
        end
        @shipspan = size - 1
  
      puts "success #{@colAlpha} #{@row} #{@direction} #{@size}"
    end
  end
  
  #-----------------------------------------------------------------------------------------
  
  ac = Ship.new("Aircraft Carrier")
  p ac
  
  p Board.new.within_board_bounds?(ac)
  </code></pre>