Стоян обнови решението на 29.11.2015 15:23 (преди около 9 години)
+module TurtleGraphics
+ class Turtle
+ def initialize(rows, columns)
+ @rows = rows
+ @columns = columns
+ @matrix = initialize_matrix(rows, columns)
+ @position = {:row => 0, :column => 0}
+ @orientation = :right
+ end
+
+ def spawn_at(row, column)
+ @position[:row] = row
+ @position[:column] = column
+ @matrix[@position[:row]][@position[:column]] += 1
+ end
+
+ def look(orientation)
+ @orientation = orientation
+ end
+
+ def turn_left
+ @orientation = case @orientation
+ when :left
+ :down
+ when :down
+ :right
+ when :right
+ :up
+ when :up
+ :left
+ end
+ end
+
+ def turn_right
+ @orientation = case @orientation
+ when :left
+ :up
+ when :up
+ :right
+ when :right
+ :down
+ when :down
+ :left
+ end
+ end
+
+ def move
+ factors = get_move_factors
+ new_position = {
+ :row => @position[:row] + factors.first,
+ :column => @position[:column] + factors.last}
+ set_position(new_position)
+ end
+
+ def draw(canvas, &methods)
+ spawn_at(0, 0)
+ instance_eval &methods
+ canvas.apply_matrix(@matrix.clone)
+ canvas.get_canvas
+ end
+
+ private def get_move_factors
+ case @orientation
+ when :left
+ return [0, -1]
+ when :right
+ return [0, 1]
+ when :up
+ return [-1, 0]
+ when :down
+ return [1, 0]
+ end
+ end
+
+ private def set_position(position)
+ if position[:row] > @rows
+ @position[:row] = 0
+ else
+ @position[:row] = position[:row]
+ end
+
+ if position[:column] > @columns
+ @position[:column] = 0
+ else
+ @position[:column] = position[:column]
+ end
+
+ @matrix[@position[:row]][@position[:column]] += 1
+ end
+
+ private def initialize_matrix(rows, columns)
+ matrix = []
+ rows.times do
+ row = []
+ columns.times do
+ row.push 0
+ end
+ matrix.push row
+ end
+ matrix
+ end
+ end
+
+ module Canvas
+ class ASCII
+ def initialize(palette)
+ @palette = palette
+ @canvas = ""
+ end
+
+ def apply_matrix(matrix)
+ map = create_intensity_map(matrix)
+ maximum = get_maximum_value(matrix)
+ matrix.each do
+ |row|
+ row.each do
+ |pixel|
+ @canvas << get_pixel_palette_value(pixel, maximum, map)
+ end
+ @canvas << "\n"
+ end
+ @canvas.chomp("\n")
+ end
+
+ def get_canvas
+ @canvas.clone
+ end
+
+ private def get_pixel_palette_value(pixel, highest_pixel, intensity_map)
+ intensity = get_pixel_intensity(pixel, highest_pixel)
+ value = ' '
+ intensity_map.keys.each do
+ |range_maximum|
+ if intensity <= range_maximum
+ return intensity_map[range_maximum]
+ end
+ end
+ value
+ end
+
+ private def get_pixel_intensity(pixel, maximum)
+ pixel / maximum.to_f
+ end
+
+ private def create_intensity_map(matrix)
+ map = Hash.new
+ maximum = get_maximum_value(matrix)
+ step = 1.0 / (@palette.length - 1)
+ current = 0
+ @palette.each do
+ |item|
+ map[current] = item
+ current += step
+ end
+ map
+ end
+
+ private def get_maximum_value(matrix)
+ maximum = 0
+ matrix.each do
+ |row|
+ highest_in_row = row.max
+ if highest_in_row > maximum
+ maximum = highest_in_row
+ end
+ end
+ maximum
+ end
+ end
+ end
+end
Здравей :) Малко коментари:
- Имаш стилови проблеми. Например, по конвенция,
private
не се използва така. Също, аргументите на блока не се слагат на нов ред. -
initialize_matrix
изглежда прекалено като на C/Java. Опитай да го направиш без да мутираш масив. Има методи, различни отeach
в езика. :) -
get_maximum_value
може да стане много по-ясно на един ред. Виж какво има в стандартната библиотека. -
turn_left
иturn_right
са доста подобни. Можеш ли да измислиш как да не ти се налага да правишcase
? -
get_move_factors
плаче да бъде изнесен като константа :)