patternrubyMinor
Snakes and Ladders random world generator second implementation
Viewed 0 times
randomladdersgeneratorworldsecondandimplementationsnakes
Problem
The following is an implementation of a random world generator for the classic Snakes and Ladders game. This is a follow up to this question, where I reviewed my own original implementation. I am asking for a review of my review.
The world rules are:
The world rules are:
- The head of a snake can not be on the last square (you'll never win)
- The base of a ladder can not be on the last square (you'll have no where to go)
- A square can only have one thing, either the head or base of a ladder or a snake
class World
attr_reader :size, :snakes, :ladders
def initialize(size, snakes = 10, ladders = 10)
@size = size
@snakes, @ladders = {}, {}
place_snakes(snakes)
place_ladders(ladders)
end
def place_snakes(count)
count.times do
start_point = place_point
end_point_range = habitable_range.begin..(start_point - 1)
snakes[start_point] = place_point(end_point_range)
end
end
def place_ladders(count)
count.times do
start_point = place_point
end_point_range = (start_point + 1)..habitable_range.end
ladders[start_point] = place_point(end_point_range)
end
end
private
def place_point(range = habitable_range)
begin
point = rand(range)
end while occupied?(point)
point
end
def occupied?(number)
[snakes.keys, snakes.values, ladders.keys, ladders.values].flatten.include?(number)
end
def habitable_range
1..(size - 1)
end
endSolution
Here's an attempt:
The idea here is that:
The board is represented as a
If desired, you could have
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 && @board[point].nil?
point
end
def place(count, entity)
count.times do
start_point = free_point
end_point = free_point until end_point && end_point != start_point && (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
endThe 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.Code Snippets
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 && @board[point].nil?
point
end
def place(count, entity)
count.times do
start_point = free_point
end_point = free_point until end_point && end_point != start_point && (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
endContext
StackExchange Code Review Q#70448, answer score: 3
Revisions (0)
No revisions yet.