shushus

Спринт 11. Умный указатель shared_ptr.

Mar 26th, 2023
653
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.81 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. main.cpp
  3. -----------------------------------------------------------------------
  4. #include "canvas.h"
  5. #include "shapes.h"
  6.  
  7. #include <cassert>
  8. #include <sstream>
  9.  
  10. std::unique_ptr<Texture> MakeTextureCow() {
  11.     Image image = {R"(^__^            )",  //
  12.                    R"((oo)\_______    )",  //
  13.                    R"((__)\       )\/\)",  //
  14.                    R"(    ||----w |   )",  //
  15.                    R"(    ||     ||   )"};
  16.     return std::make_unique<Texture>(move(image));
  17. }
  18.  
  19. std::unique_ptr<Texture> MakeTextureSolid(Size size, char pixel) {
  20.     Image image(size.height, std::string(size.width, pixel));
  21.     return std::make_unique<Texture>(move(image));
  22. }
  23.  
  24. std::unique_ptr<Texture> MakeTextureCheckers(Size size, char pixel1, char pixel2) {
  25.     Image image(size.height, std::string(size.width, pixel1));
  26.  
  27.     for (int i = 0; i < size.height; ++i) {
  28.         for (int j = 0; j < size.width; ++j) {
  29.             if ((i + j) % 2 != 0) {
  30.                 image[i][j] = pixel2;
  31.             }
  32.         }
  33.     }
  34.  
  35.     return std::make_unique<Texture>(move(image));
  36. }
  37.  
  38. void TestCpp() {
  39.     Canvas canvas(Size{77, 17});
  40.  
  41.     canvas.AddShape(ShapeType::ELLIPSE, {2, 1}, {30, 15},
  42.                     MakeTextureCheckers({100, 100}, 'c', 'C'));
  43.     canvas.AddShape(ShapeType::ELLIPSE, {8, 4}, {30, 9}, MakeTextureSolid({100, 100}, ' '));
  44.  
  45.     auto h1 = canvas.AddShape(ShapeType::RECTANGLE, {54, 7}, {22, 3},
  46.                               MakeTextureSolid({100, 100}, '+'));
  47.     canvas.DuplicateShape(h1, {30, 7});
  48.  
  49.     auto v1 = canvas.DuplicateShape(h1, {62, 3});
  50.     canvas.ResizeShape(v1, {6, 11});
  51.     canvas.DuplicateShape(v1, {38, 3});
  52.  
  53.     std::stringstream output;
  54.     canvas.Print(output);
  55.  
  56.     const auto answer
  57.         = "###############################################################################\n"
  58.           "#                                                                             #\n"
  59.           "#            cCcCcCcCcC                                                       #\n"
  60.           "#        CcCcCcCcCcCcCcCcCc                                                   #\n"
  61.           "#      cCcCcCcCcCcCcCcCcCcCcC          ++++++                  ++++++         #\n"
  62.           "#    CcCcCcCcCcCc                      ++++++                  ++++++         #\n"
  63.           "#   CcCcCcCcC                          ++++++                  ++++++         #\n"
  64.           "#   cCcCcCc                            ++++++                  ++++++         #\n"
  65.           "#  cCcCcC                      ++++++++++++++++++++++  ++++++++++++++++++++++ #\n"
  66.           "#  CcCcCc                      ++++++++++++++++++++++  ++++++++++++++++++++++ #\n"
  67.           "#  cCcCcC                      ++++++++++++++++++++++  ++++++++++++++++++++++ #\n"
  68.           "#   cCcCcCc                            ++++++                  ++++++         #\n"
  69.           "#   CcCcCcCcC                          ++++++                  ++++++         #\n"
  70.           "#    CcCcCcCcCcCc                      ++++++                  ++++++         #\n"
  71.           "#      cCcCcCcCcCcCcCcCcCcCcC          ++++++                  ++++++         #\n"
  72.           "#        CcCcCcCcCcCcCcCcCc                                                   #\n"
  73.           "#            cCcCcCcCcC                                                       #\n"
  74.           "#                                                                             #\n"
  75.           "###############################################################################\n";
  76.  
  77.     assert(answer == output.str());
  78. }
  79.  
  80. void TestCow() {
  81.     Canvas canvas{{18, 5}};
  82.  
  83.     canvas.AddShape(ShapeType::RECTANGLE, {1, 0}, {16, 5}, MakeTextureCow());
  84.  
  85.     std::stringstream output;
  86.     canvas.Print(output);
  87.  
  88.     const auto answer =
  89.         R"(####################)""\n"
  90.         R"(# ^__^             #)""\n"
  91.         R"(# (oo)\_______     #)""\n"
  92.         R"(# (__)\       )\/\ #)""\n"
  93.         R"(#     ||----w |    #)""\n"
  94.         R"(#     ||     ||    #)""\n"
  95.         R"(####################)""\n";
  96.  
  97.     assert(answer == output.str());
  98. }
  99.  
  100. int main() {
  101.     TestCow();
  102.     TestCpp();
  103. }
  104. -----------------------------------------------------------------------
  105. texture.h
  106. -----------------------------------------------------------------------
  107. #pragma once
  108. #include "common.h"
  109.  
  110. class Texture {
  111. public:
  112.     explicit Texture(Image image)
  113.         : image_(std::move(image)) {
  114.     }
  115.  
  116.     Size GetSize() const {
  117.         if (image_.empty()) {
  118.             return {0, 0};
  119.         }
  120.         return {int(image_[0].size()), int(image_.size())};
  121.     }
  122.  
  123.     char GetPixelColor(Point p) const {
  124.         if (int(image_.size()) <= p.y || int(image_[0].size()) <= p.x || p.x < 0 || p.y < 0) {
  125.             return '.';
  126.         }
  127.         return image_[p.y][p.x];
  128.     }
  129.  
  130. private:
  131.     Image image_;
  132. };
  133. -----------------------------------------------------------------------
  134. shapes.h
  135. -----------------------------------------------------------------------
  136. #pragma once
  137. #include "texture.h"
  138.  
  139. #include <memory>
  140.  
  141. enum class ShapeType {RECTANGLE, ELLIPSE};
  142.  
  143. class Shape {
  144. public:
  145.  
  146.     explicit Shape(ShapeType type) : type_(type) {}
  147.  
  148.     void SetPosition(Point pos) {
  149.         pos_ = pos;
  150.     }
  151.  
  152.     void SetSize(Size size) {
  153.         size_ = size;
  154.     }
  155.  
  156.     void SetTexture(std::shared_ptr<Texture> texture) {
  157.         texture_ = std::move(texture);
  158.     }
  159.    
  160.     void Draw(Image& image) const {
  161.        
  162.         const auto image_size = GetImageSize(image);
  163.  
  164.         int y_ = 0;
  165.         int x_ = 0;
  166.         char helper;
  167.  
  168.         for (int y = 0; y < size_.height; ++y) {
  169.             for (int x = 0; x < size_.width; ++x) {
  170.                
  171.                 y_ = pos_.y + y;
  172.                 x_ = pos_.x + x;
  173.  
  174.                 if (y_ < 0 ||
  175.                     x_ < 0 ||
  176.                     y_ >= image_size.height ||
  177.                     x_ >= image_size.width) {
  178.                    
  179.                     continue;
  180.                 }
  181.                
  182.                 if (!texture_) {
  183.                     helper = '.';
  184.                 } else {
  185.                     helper = texture_->GetPixelColor({x, y});
  186.                 }
  187.  
  188.                 if ((type_ == ShapeType::ELLIPSE
  189.                               && IsPointInEllipse({x, y}, size_))
  190.                      || (type_ == ShapeType::RECTANGLE)) {
  191.                    
  192.                     image[y_][x_] = helper;
  193.                 }
  194.             }
  195.         }
  196.     }
  197. private:
  198.     ShapeType type_;
  199.     Point pos_;
  200.     Size size_;
  201.     std::shared_ptr<Texture> texture_;
  202. };
  203. -----------------------------------------------------------------------
  204. common.h
  205. -----------------------------------------------------------------------
  206. #pragma once
  207.  
  208. #include <string>
  209. #include <vector>
  210.  
  211. struct Size {
  212.     int width = 0;
  213.     int height = 0;
  214. };
  215.  
  216. struct Point {
  217.     int x = 0;
  218.     int y = 0;
  219. };
  220.  
  221. using Image = std::vector<std::string>;
  222.  
  223. inline Size GetImageSize(const Image& image) {
  224.     const int width = image.empty() ? 0 : static_cast<int>(image[0].size());
  225.     const int height = static_cast<int>(image.size());
  226.     return {width, height};
  227. }
  228.  
  229. inline bool IsPointInEllipse(Point p, Size size) {
  230.     double x = (p.x + 0.5) / (size.width / 2.0) - 1;
  231.     double y = (p.y + 0.5) / (size.height / 2.0) - 1;
  232.     return x * x + y * y <= 1;
  233. }
  234. -----------------------------------------------------------------------
  235. canvas.h
  236. -----------------------------------------------------------------------
  237. #include "shapes.h"
  238.  
  239. #include <iostream>
  240. #include <map>
  241. #include <string_view>
  242.  
  243. class Canvas {
  244. public:
  245.     using ShapeId = size_t;
  246.  
  247.     explicit Canvas(Size size)
  248.         : size_(size) {
  249.     }
  250.  
  251.     void SetSize(Size size) {
  252.         size_ = size;
  253.     }
  254.  
  255.     ShapeId AddShape(ShapeType shape_type, Point position, Size size,
  256.                      std::shared_ptr<Texture> texture) {
  257.         auto shape = std::make_unique<Shape>(shape_type);
  258.         shape->SetPosition(position);
  259.         shape->SetSize(size);
  260.         shape->SetTexture(std::move(texture));
  261.         return InsertShape(std::move(shape));
  262.     }
  263.  
  264.     ShapeId DuplicateShape(ShapeId source_id, Point target_position) {
  265.         auto shape = std::make_unique<Shape>(*GetShapeNodeById(source_id)->second);
  266.         shape->SetPosition(target_position);
  267.         return InsertShape(std::move(shape));
  268.     }
  269.  
  270.     void RemoveShape(ShapeId id) {
  271.         shapes_.erase(GetShapeNodeById(id));
  272.     }
  273.  
  274.     void MoveShape(ShapeId id, Point position) {
  275.         GetShapeNodeById(id)->second->SetPosition(position);
  276.     }
  277.  
  278.     void ResizeShape(ShapeId id, Size size) {
  279.         GetShapeNodeById(id)->second->SetSize(size);
  280.     }
  281.  
  282.     int GetShapesCount() const {
  283.         return static_cast<int>(shapes_.size());
  284.     }
  285.  
  286.     void Print(std::ostream& output) const {
  287.         using namespace std::literals;
  288.  
  289.         Image image(size_.height, std::string(size_.width, ' '));
  290.  
  291.         for (const auto& [id, shape] : shapes_) {
  292.             shape->Draw(image);
  293.         }
  294.  
  295.         output << '#' << std::string(size_.width, '#') << "#\n"sv;
  296.         for (const auto& line : image) {
  297.             output << '#' << line << "#\n"sv;
  298.         }
  299.         output << '#' << std::string(size_.width, '#') << "#\n"sv;
  300.     }
  301.  
  302. private:
  303.     using Shapes = std::map<ShapeId, std::unique_ptr<Shape>>;
  304.  
  305.     Shapes::iterator GetShapeNodeById(ShapeId id) {
  306.         auto it = shapes_.find(id);
  307.         if (it == shapes_.end()) {
  308.             throw std::out_of_range("No shape with given ID");
  309.         }
  310.         return it;
  311.     }
  312.     ShapeId InsertShape(std::unique_ptr<Shape> shape) {
  313.         shapes_[current_id_] = std::move(shape);
  314.         return current_id_++;
  315.     }
  316.  
  317.     Size size_ = {};
  318.     ShapeId current_id_ = 0;
  319.     Shapes shapes_;
  320. };
Advertisement
Add Comment
Please, Sign In to add comment