Теодор обнови решението на 01.12.2015 22:30 (преди около 9 години)
+module TurtleGraphics
+ module Canvas
+ end
+end
+
+class TurtleGraphics::Turtle
+ DIRECTIONS = [:right, :down, :left, :up]
+ DIRECTION_VECTORS = [[0, 1], [1, 0], [0, -1], [-1, 0]]
+
+ def initialize(rows, columns)
+ @rows = rows
+ @columns = columns
+ @direction = 0
+ @position = [0, 0]
+ @is_spawn = false
+ end
+
+ def draw(canvas = nil, &block)
+ @canvas = canvas || TurtleGraphics::Canvas::Matrix.new
+ @canvas.init(@rows, @columns)
+ @canvas.mark_cell @position
+
+ self.instance_eval(&block)
+ @canvas.render
+ end
+
+ def move
+ y, x = DIRECTION_VECTORS[@direction]
+ @position = [(@position[0] + y) % @rows, (@position[1] + x) % @columns]
+ @canvas.mark_cell @position
+ end
+
+ def turn_left
+ @direction = @direction.pred % DIRECTIONS.size
+ end
+
+ def turn_right
+ @direction = @direction.next % DIRECTIONS.size
+ end
+
+ def look(orientation)
+ @direction = DIRECTIONS.index orientation
+ end
+
+ def spawn_at(row, column)
+ unless @is_spawn
+ @canvas.reset_cell @position
+ @position = [row, column]
+ @canvas.mark_cell @position
+ @is_spawn = true
+ end
+ end
+end
+
+
+class TurtleGraphics::Canvas::Matrix
+ def init(rows, columns)
+ @matrix = (0...rows).map { [0] * columns }
+ end
+
+ def mark_cell((row, column))
+ @matrix[row][column] += 1
+ end
+
+ def reset_cell((row, column))
+ @matrix[row][column] = 0
+ end
+
+ def render
+ @matrix
+ end
+end
+
+class TurtleGraphics::Canvas::PercentMatrix < TurtleGraphics::Canvas::Matrix
+ def render
+ max = @matrix.flatten.max.to_r
+ @matrix.map do |row|
+ row.map { |x| x / max }
+ end
+ end
+end
+
+class TurtleGraphics::Canvas::ASCII < TurtleGraphics::Canvas::PercentMatrix
+ def initialize(palette)
+ @palette = palette
+ @size = @palette.size - 1
+ end
+
+ def render
+ rows = super.map do |row|
+ row.map { |x| @palette[(@size * x).ceil] }.join
+ end
+ rows.join "\n"
+ end
+end
+
+class TurtleGraphics::Canvas::HTML < TurtleGraphics::Canvas::PercentMatrix
+ def initialize(size)
+ @size = size
+ end
+
+ def render
+ [
+ '<!DOCTYPE html>',
+ '<html>',
+ render_head,
+ render_body(super),
+ '</html>'
+ ].join "\n"
+ end
+
+ private
+
+ def render_head
+ [
+ '<head>',
+ ' <title>Turtle graphics</title>',
+ ' <style>',
+ render_css,
+ ' </style>',
+ '</head>'
+ ].join "\n"
+ end
+
+ def render_css
+ [
+ 'table { border-spacing: 0; }',
+ 'tr { padding: 0; }',
+ 'td {',
+ " width: #{@size}px;",
+ " height: #{@size}px;",
+ ' background-color: black;',
+ ' padding: 0;',
+ '}'
+ ].join "\n"
+ end
+
+ def render_body(matrix)
+ [
+ '<body>',
+ render_table(matrix),
+ '</body>'
+ ].join "\n"
+ end
+
+ def render_table(matrix)
+ [
+ '<table>',
+ matrix.map { |row| render_row row }.join,
+ '</table>'
+ ].join "\n"
+ end
+
+ def render_row(row)
+ [
+ '<tr>',
+ row.map { |x| '<td style="opacity: %.2f"></td>' % x }.join,
+ '</tr>'
+ ].join "\n"
+ end
+end