Николай обнови решението на 02.12.2015 15:22 (преди около 9 години)
+module TurtleGraphics
+ class Turtle
+ @@directions = {
+ up: [-1, 0],
+ right: [0, 1],
+ down: [1, 0],
+ left: [0, -1],
+ }.freeze
+
+ def initialize(canvas_rows, canvas_columns)
+ @canvas_rows , @canvas_columns = canvas_rows, canvas_columns
+ @current_row, @current_column = 0, 0
+ @current_direction = :left
+ end
+
+ def draw(canvas = Canvas::Matrix.new(), &block)
+ @canvas = canvas
+ @canvas.initialize_matrix(@canvas_rows, @canvas_columns)
+ self.instance_eval &block
+ mark(0,0) unless @spawn_at_was_invoked # not elegant, but working
+ @canvas.print
+ end
+
+ def move
+ @current_row = (@current_row + @@directions[@current_direction].first) %
+ @canvas_rows
+ @current_column = (@current_column + @@directions[@current_direction].last) %
+ @canvas_columns
+ mark
+ end
+
+ def spawn_at(row, column)
+ @current_row = row
+ @current_column = column
+ mark
+ @spawn_at_was_invoked = true
+ end
+
+ def look(direction)
+ @current_direction = direction
+ end
+
+ def turn_left
+ turn(-1)
+ end
+
+ def turn_right
+ turn(1)
+ end
+
+ private
+
+ def turn(direction)
+ current_direction_index = @@directions.keys.find_index(@current_direction)
+ @current_direction = @@directions.keys.at( (current_direction_index +
+ direction) % 4)
+ end
+
+ def mark(row = @current_row, column = @current_column)
+ @canvas.mark(row, column)
+ end
+
+ end
+
+ module Canvas
+ class CanvasClass
+ attr_accessor :matrix
+ def initialize
+ raise NotImplementedError, "#{self.class.name} is abstract method"
+ end
+
+ def mark(row, column)
+ @matrix[row][column] += 1
+ end
+
+ def [](index)
+ @matrix[index]
+ end
+
+ def initialize_matrix(rows, columns)
+ @matrix_rows, @matrix_columns = rows, columns
+ generate_matrix
+ end
+
+ def print
+ raise NotImplementedError,
+ "#{self.class.name} should have implemented this method"
+ end
+
+
+ private
+
+ def normalize_matrix
+ raise NotImplementedError,
+ "#{self.class.name} should have implemented this method"
+ end
+
+ def generate_matrix
+ @matrix = []
+ @matrix_rows.times { @matrix << Array.new(@matrix_columns, 0) }
+ end
+ end
+
+ class ASCII < CanvasClass
+ def initialize(intensity_scheme)
+ @intensity_scheme = intensity_scheme
+ end
+
+ def print
+ rows = normalize_matrix(@matrix)
+ rows.map(&:join).join("\n")
+ end
+
+ def normalize_matrix(matrix)
+ matrix.map do |row|
+ row.map { |intensity| @intensity_scheme[intensity] }
+ end
+ end
+ end
+
+ class Matrix < CanvasClass
+ def initialize
+ end
+
+ def print
+ @matrix
+ end
+ end
+
+ class HTML < CanvasClass
+ def initialize(pixel_size)
+ @pixel_size = pixel_size
+ end
+
+ def print
+ normalized_matrix = convert_matrix(@matrix)
+ table = generate_table(normalized_matrix)
+ generate_html(table)
+ end
+
+ private
+
+ def convert_matrix(matrix)
+ maximum_value = matrix.flatten.max
+ matrix.map do |row|
+ row.map{ |intensity| intensity / maximum_value.to_f }
+ end
+ end
+
+ def generate_table(matrix)
+ table = " <table>\n"
+ matrix.each do |row|
+ table_row = " <tr>\n"
+ row.each do |intensity|
+ table_row += " <td style=\"opacity: #{intensity}\"></td>\n"
+ end
+ table += table_row + " </tr>\n"
+ end
+ table += " </table>\n"
+ end
+
+ def generate_html(table)
+ @@view.gsub('<!-- PIXEL_SIZE -->', @pixel_size.to_s).
+ sub("<!-- TABLE -->", table)
+ end
+
+ @@view = <<-HTML
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Turtle graphics</title>
+
+ <style>
+ table {
+ border-spacing: 0;
+ }
+
+ tr {
+ padding: 0;
+ }
+
+ td {
+ width: <!-- PIXEL_SIZE -->px;
+ height: <!-- PIXEL_SIZE -->px;
+
+ background-color: black;
+ padding: 0;
+ }
+ </style>
+</head>
+<body>
+<!-- TABLE -->
+</body>
+</html>
+HTML
+ end
+ end
+end