Skip to content

Instantly share code, notes, and snippets.

@jamesmoriarty
Created April 29, 2012 08:51
Show Gist options
  • Select an option

  • Save jamesmoriarty/2547748 to your computer and use it in GitHub Desktop.

Select an option

Save jamesmoriarty/2547748 to your computer and use it in GitHub Desktop.
map exercise
class Map
attr_accessor :tiles, :start, :finish
WATER_VALUE = 10_000
FLATLAND_VALUE = 1
FOREST_VALUE = 2
MOUNTAIN_VALUE = 3
START_KEY = "@"
FINISH_KEY = "x"
TRANSPOSITION = {
"~" => WATER_VALUE,
"." => FLATLAND_VALUE,
"@" => FLATLAND_VALUE,
"x" => FLATLAND_VALUE,
"*" => FOREST_VALUE,
"^" => MOUNTAIN_VALUE
}
# @example
# @tiles = <<-TILES
# @*^^^
# ~~*~
# **...
# ^..*~
# ~~*~x
# TILES
# @map = Map.new(@tiles)
# => #<Map:0x00000100851528 @tiles=[[1, 2, 3, 3, 3], [10000, 10000, 2, 10000], [2, 2, 1, 1, 1], [3, 1, 1, 2, 10000], [10000, 10000, 2, 10000, 1]], @start=[0, 0], @finish=[4, 4]>
def initialize(tiles_string)
# arrayify by new line and then character
@tiles = tiles_string.split("\n").map do |row|
row.split("")
end
# record points before substitution
@start = position(START_KEY) or raise "could not find start"
@finish = position(FINISH_KEY) or raise "could now find finish"
# substitute tiles for cost
@tiles = @tiles.map do |row|
row.map do |tile|
TRANSPOSITION[tile] or raise "invalid tile"
end
end
end
# @example
# map.position("@")
# => [0,0]
def position(value)
@tiles.each_with_index do |row, y|
row.each_with_index do |tile, x|
if value == tile
return x, y
end
end
end
nil
end
# @example
# @map.adjacent(*@map.start)
# => [[0,1]]
def adjacent(x, y)
valid_adjacent_coordinates = []
(-1..1).each do |x_offset|
(-1..1).each do |y_offset|
x_new = (x + x_offset)
y_new = (y + y_offset)
if !(x_new == x and y_new == y) and
x_new < width and x_new >= 0 and
y_new < height and y_new >= 0 and
cost(x_new, y_new) < 10_000
valid_adjacent_coordinates.push [x_new, y_new]
end
end
end
valid_adjacent_coordinates
end
# @example
# @map.cost(*@map.start)
# => 1
def cost(x, y)
@tiles[y][x]
end
# @example
# @map.width
# => 4
def width
@tiles[0].size
end
# @example
# @map.height
# => 4
def height
@tiles.size
end
# @example
# @map.path
# => [[0, 0],[1, 0],[2,1],[3,3],[3,4],[5,5]]
def path
end
end
require "test/unit"
class TestMap < Test::Unit::TestCase
def setup
@tiles = <<-TILES
@*^^^
~~*~
**...
^..*~
~~*~x
TILES
@map = Map.new(@tiles)
end
def test_map_intialize
assert_instance_of Map, @map
end
def test_position_start
assert_equal [0,0], @map.start
end
def test_position_end
assert_equal [4,4], @map.finish
end
def test_width
assert_equal 5, @map.width
end
def test_height
assert_equal 5, @map.height
end
def test_cost
assert_equal 1, @map.cost(*@map.start)
end
def test_adjacent
adjacent_coordinates = @map.adjacent(*@map.start)
assert adjacent_coordinates.include?([1, 0]), "should include forest #{adjacent_coordinates}"
assert !adjacent_coordinates.include?([-1, 0]), "should not include off map #{adjacent_coordinates}"
assert !adjacent_coordinates.include?([-1, -1]), "should not include off map #{adjacent_coordinates}"
assert !adjacent_coordinates.include?([0, -1]), "should not include off map #{adjacent_coordinates}"
assert !adjacent_coordinates.include?([0, 1]), "should not include water #{adjacent_coordinates}"
assert !adjacent_coordinates.include?([1, 1]), "should not include water #{adjacent_coordinates}"
assert !adjacent_coordinates.include?(@map.start), "should not include self #{adjacent_coordinates}"
end
def test_path
best_path = [[0, 0],[1, 0],[2,1],[3,3],[3,4],[5,5]]
assert_equal best_path, @map.path
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment