Snakes and Ladders random world generator second implementation
Here's an attempt:

class World
  attr_reader :board

  def initialize(size, snakes_count = 10, ladders_count = 10)
    @board = Array.new(size * size)

    place snakes_count,  :snake
    place ladders_count, :ladder
  end

private

  def free_point
    point = rand(@board.size) until point &amp;&amp; @board[point].nil?
    point
  end

  def place(count, entity)
    count.times do
      start_point = free_point
      end_point   = free_point until end_point &amp;&amp; end_point != start_point &amp;&amp; (entity == :ladder || end_point != @board.size - 1)
      pair = [start_point, end_point].sort
      pair.reverse! if entity == :snake
      @board[pair.first] = @board[pair.last] = pair
    end
  end
end


The idea here is that:


A snake or ladder consists of a point pair. A snake is a desending pair (ie, go back from a higher point to a lower point), while a ladder is an ascending pair (go forward from a lower point to a higher point)
A snake cannot have either of its points be the final point on the board.


The board is represented as a size x size array, so a world of size 12 would produce a board that is 12x12, or 144 squares. Checking for occupation is then as easy as just checking if @board[point].nil?. It also gives you an easy way to iterate the board for rendering or rules checking; as you're playing, if the player lands on square 63, you can check square 63. If it has a value, then check if v[0] > v[1] (snake) or otherwise (ladder).

If desired, you could have #place keep a separate list of snakes and ladders, but it's not strictly necessary, since you can think of them as the same construct (a movement from one point to another), differentiated only by the direction of movement.