Валентин обнови решението на 22.12.2013 08:02 (преди почти 11 години)
+# not ready
+module Graphics
+ class Canvas
+ attr_reader :width, :height
+
+ def initialize(width, height)
+ @width, @height = width, height
+ @container = Array.new(height) { Array.new width, false }
+ end
+
+ # задава пикселът, идентифициран от координатите x и y е "запълнен".
+ def set_pixel(x, y)
+ @container[y][x] = true
+ end
+
+ # проверява "запълнен" ли е пиксела идентифициран от координатите x и y
+ def pixel_at?(x, y)
+ @container[y][x]
+ end
+
+ def draw
+ end
+
+ #
+ # === Args
+ # +renderer+::
+ # sdsdfsf
+ #
+ # === Description
+ #
+ def render_as renderer
+ if renderer == Renderers::Ascii
+ map_lane('@', '-')
+ elsif renderer == Renderers::Html
+ output = <<HTML
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Rendered Canvas</title>
+ <style type="text/css">
+ .canvas {
+ font-size: 1px;
+ line-height: 1px;
+ }
+ .canvas * {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ border-radius: 5px;
+ }
+ .canvas i {
+ background-color: #eee;
+ }
+ .canvas b {
+ background-color: #333;
+ }
+ </style>
+</head>
+<body>
+ <div class="canvas">
+HTML
+ output += "#{map_lane('<b></b>', '<i></i>', '<br>')}</div></body></html>"
+ end
+ end
+
+ def map_lane(filled, empty, row_delimiter = "\n")
+ @container.map do |row|
+ map_lane_row(row, filled, empty)
+ end.join row_delimiter
+ end
+
+ private
+ def map_lane_row(row, filled, empty)
+ row.map { |s| s ? filled : empty }.join
+ end
+ end
+
+ module Renderers
+ class Ascii
+ end
+
+ class Html
+ end
+ end
+
+ class Point
+ attr_reader :x, :y
+
+ def initialize(x, y)
+ @x, @y = x, y
+ end
+
+ def ==(object)
+ if object.kind_of? Point
+ object.x == x && object.y == y
+ else
+ false
+ end
+ end
+ end
+
+ class Line
+ def initialize(one_point, another_point)
+ @one_point, @another_point = one_point, another_point
+ end
+
+ def from
+ if @one_point.x < @another_point.x
+ @one_point
+ elsif @one_point.x > @another_point.x
+ @another_point
+ else
+ y_from
+ end
+ end
+
+ def to
+ if @one_point.x > @another_point.x
+ @one_point
+ elsif @one_point.x < @another_point.x
+ @another_point
+ else
+ end
+ end
+
+ private
+ def y_from
+ if @one_point.y < @another_point.y
+ @one_point
+ else
+ @another_point
+ end
+ end
+
+ def y_to
+ if @one_point.y > @another_point.y
+ @one_point
+ else
+ @another_point
+ end
+ end
+ end
+
+ class Rectangle
+ attr_reader :left, :right
+
+ def initialize(one_point, another_point)
+ diagonal = Line.new(one_point, another_point)
+ @left = diagonal.from
+ @right = diagonal.to
+ end
+
+ def top_left
+ end
+
+ def top_right
+ end
+
+ def bottom_left
+ end
+
+ def bottom_right
+ end
+ end
+end
Бележки:
- Виждам коментара "not ready", но гледай да разкараш всички коментари в окончателния вариант :) Добрият и ясен код няма нужда от такива.
- Помисли дали няма друг по-оптимален начин в Ruby за реализация вътрешното представяне на пано, от масив от масиви. Ruby не е C и има по-удобни структури от данни, за които дори няма нужда да
require
-ваш нищо :) - Също така,
pixel_at?
може да връща нещо, което се оценява като истина или лъжа; не е задължително да еtrue
/false
. - Помисли кой трбява да носи отговорността за "рендериране" на пано. Самото пано или рендерера? Помисли кой обект каква отговорност носи. Една основна идея на ОО-програмирането е да разпределиш различните отговорности между различни обекти. Стреми се всеки обект да отговаря за едно конкретно нещо и само за него. Напълно нормално е да имаш голям брой малки обекти в системата, с тясно специализирани отговорности. В момента класовете ти
Html
иAscii
са два празни такива. -
map_lane
? Какво е "lane"? Платно, лента? Може биline
? Същото и заmap_lane_row
, което може би има нещо общо с "пиксел". - В случая е удачно HTML кодът на
Html
да се пази в константа/и вHtml
. - Няма нужда да проверяваш за типа на обекта при сравнение на фигури. Ще сравняваме в тестовете винаги фигури от един и същи тип. Също така, не виждам да си имплементирал
eql?
иhash
. -
one_point
иanother_point
не са достатъчно добри имена. Ако са просто две точки, кръсти ги first и second, или нещо такова. "One" и "another" не са подходящи в случая. - Оставяй по един празен ред след
private
. -
else
клонът вLine#to
е празен. Ако искаш да върнешnil
, просто го пропускаш.