// @Time : 2023-10-23 21:37:53 // @FileName: view.h // @Author : 423A35C7 // @Software: VSCode #ifndef _VIEW #define _VIEW #include "constants.h" #include "model.hpp" #include #define move_and_output(x, y, str) printf("\033[s\033[%d;%dH%s\033u", x, y, str) #define moveto(x, y) printf("\033[s\033[%d;%dH", x, y) // 下移光标 #define movedown(x) printf("\033[%dB", (x)) #define save_cursor() printf("\033[s") #define restore_cursor() printf("\033[u") #define clear_char(num) \ for (int i = 0; i < num; i++) \ printf(" ") class View { public: virtual void refresh() = 0; }; class BackgroundView : View { private: int gate_x; int gate_y; public: void refresh() { printf("\033[2J\033[?25l"); move_and_output(this->gate_x + 1, this->gate_y, "大门"); } BackgroundView(int gate_x, int gate_y) : gate_x(gate_x), gate_y(gate_y) { this->refresh(); } ~BackgroundView() { printf("\033[2J\033[0m\033[?25h"); } }; template class QueueView : View { protected: virtual void init() {} QueueModel &queue_model; public: QueueView() {} QueueView(QueueModel &_queue_model) : queue_model(_queue_model) {} // 这里如果不使用引用会在调用时报错: // 无法引用 函数 "SingleQueueModel::SingleQueueModel(const SingleQueueModel &) [其中 T=Customer]" (已隐式声明) -- 它是已删除的函数C/C++(1776) virtual void refresh() {} // 此方法不一定合理,因为View直接更改了Model void push_to_model(T &data) { this->queue_model.push(data); } virtual std::pair get_last_pos() { return std::make_pair(-1, -1); } }; // MVC中的View不应该依赖Model,这里的模板中只是使用了Model的名称,实际上并不依赖model实现的代码,只要这个模板类型有迭代器的实现就行 template class SimpleQueueView : public QueueView { friend View; private: int_ base_x; // x是向下增加 int_ base_y; // y是向右增加 int_ tail_y; protected: QueueModel &queue_model; public: SimpleQueueView(QueueModel &_queue_model) : queue_model(_queue_model), QueueView(_queue_model) { this->base_x = 0; this->base_y = 0; } SimpleQueueView(QueueModel &_queue_model, int_ base_x, int_ base_y) : queue_model(_queue_model), QueueView(_queue_model) { this->base_x = base_x; this->base_y = base_y; } std::pair get_last_pos() { return std::make_pair(this->base_x + 1 + this->queue_model.get_length(), this->base_y); } void refresh() { move_and_output(base_x, base_y, "柜台"); // this->base_x++; moveto(base_x + 1, base_y); for (auto node = this->queue_model.begin(); node != this->queue_model.end(); node++) { save_cursor(); std::cout << *node; restore_cursor(); movedown(1); } restore_cursor(); } }; class MultiQueueView : View { virtual Status init(int_ queue_num) = 0; virtual Status move(int_ start, int_ destination) = 0; }; // 还没法转成动态多态,不然还是需要一个T的模板,所以还不如直接用Model作为模板 // 这个类可能只能弄成有状态的,也就是说每次刷新的行为不仅与当前时刻的model有关,还与之前时刻的model有关 // 还是直接用T作为模板吧,虽然增加了模块之间互相依赖,即controller需要直接向view传节点,但减少了代码量 template class DriftingView : View { public: struct Node { T data; // ../include/view.hpp:152:58: error: passing 'const QueueView >' as 'this' argument discards qualifiers [-fpermissive] // 152 | coordinate target = node.target->get_last_pos(); // | ~~~~~~~~~~~~~~~~~~~~~~~~~^~ QueueView> & target; int_ remained_time; coordinate current; }; private: std::list state; public: void push(Node node) { this->state.push_back(node); } Status main() { // 如果用auto遍历,node就应该不是迭代器类型 for (auto node = this->state.begin(); node != this->state.end();) { coordinate target = node->target.get_last_pos(); node->current.first += (target.first - node->current.first) / node->remained_time; node->current.second += (target.second - node->current.second) / node->remained_time; node->remained_time--; if (node->remained_time <= 0) { node->target.push_to_model(node->data); // View应该直接调用Model吗? this->state.erase(node++); // 遍历时需要先自增再删除 } else { node++; } } return OK; } void refresh() { for (auto &node : this->state) { moveto(node.current.first, node.current.second); std::cout << node.data; restore_cursor(); } } }; #endif