#include <iostream>
#include <map>
#include <vector>
using namespace std;
enum Direction{
UP, DOWN,
LEFT, RIGHT
};
class Map{
public:
typedef char field_type;
Map(size_t width, size_t height): _width(width), _height(height){
field_type defaultValue = ' ';
for(size_t x = 0; x < width; ++x){
row_type defaultRow;
for(size_t y = 0; y < height; ++y)
defaultRow.push_back(defaultValue);
_fields.push_back(defaultRow);
}
}
field_type &at(size_t x, size_t y){
return _fields[x][y];
}
size_t width(){
return _width;
}
size_t height(){
return _height;
}
private:
typedef vector<field_type> row_type;
size_t _width, _height;
vector<row_type> _fields;
};
class Snake{
friend class Drawer;
public:
struct BodyElement{
char sign;
int x, y;
};
Snake(Direction dir, BodyElement el): _dir(dir){
_bodyElements.push_back(el);
}
Direction direction(){
return _dir;
}
void setDirection(Direction val){
_dir = val;
}
BodyElement &head(){
return _bodyElements.back();
}
const BodyElement &head() const{
return _bodyElements.back();
}
void addBodyElement(char sign){
BodyElement newElement = head();
newElement.sign = sign;
_moveFuncs[_dir](newElement);
_bodyElements.push_back(newElement);
}
private:
Direction _dir;
vector<BodyElement> _bodyElements;
static map<Direction, void(*)(BodyElement &)> _moveFuncs;
};
map<Direction, void(*)(Snake::BodyElement &)> Snake::_moveFuncs = {
{{UP}, {[](BodyElement &be){ --be.y; }}},
{{DOWN}, {[](BodyElement &be){ ++be.y; }}},
{{LEFT}, {[](BodyElement &be){ --be.x; }}},
{{RIGHT}, {[](BodyElement &be){ ++be.x; }}}
};
class Drawer{
public:
Drawer(Map &map): _map(map){}
void snake(const Snake &snake){
for(auto &el : snake._bodyElements)
_map.at(el.x, el.y) = el.sign;
}
void operator()(){
for(size_t y = 0; y < _map.height(); ++y){
for(size_t x = 0; x < _map.width(); ++x)
cout << _map.at(x, y);
cout << endl;
}
}
private:
Map &_map;
};
int main() {
Map myMap(5, 5);
Snake snake(DOWN, Snake::BodyElement{'x', 0, 0});
Drawer draw(myMap);
snake.addBodyElement('a');
snake.addBodyElement('b');
snake.setDirection(RIGHT);
snake.addBodyElement('c');
snake.addBodyElement('d');
snake.setDirection(UP);
snake.addBodyElement('e');
snake.addBodyElement('f');
draw.snake(snake);
draw();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8dmVjdG9yPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKZW51bSBEaXJlY3Rpb257CglVUCwgRE9XTiwKCUxFRlQsIFJJR0hUCn07CgpjbGFzcyBNYXB7CnB1YmxpYzoKCXR5cGVkZWYgY2hhciBmaWVsZF90eXBlOwoJTWFwKHNpemVfdCB3aWR0aCwgc2l6ZV90IGhlaWdodCk6IF93aWR0aCh3aWR0aCksIF9oZWlnaHQoaGVpZ2h0KXsKCQlmaWVsZF90eXBlIGRlZmF1bHRWYWx1ZSA9ICcgJzsKCQlmb3Ioc2l6ZV90IHggPSAwOyB4IDwgd2lkdGg7ICsreCl7CgkJCXJvd190eXBlIGRlZmF1bHRSb3c7CgkJCWZvcihzaXplX3QgeSA9IDA7IHkgPCBoZWlnaHQ7ICsreSkKCQkJCWRlZmF1bHRSb3cucHVzaF9iYWNrKGRlZmF1bHRWYWx1ZSk7CgkJCV9maWVsZHMucHVzaF9iYWNrKGRlZmF1bHRSb3cpOwoJCX0KCX0KCQoJZmllbGRfdHlwZSAmYXQoc2l6ZV90IHgsIHNpemVfdCB5KXsKCQlyZXR1cm4gX2ZpZWxkc1t4XVt5XTsKCX0KCQoJc2l6ZV90IHdpZHRoKCl7CgkJcmV0dXJuIF93aWR0aDsKCX0KCQoJc2l6ZV90IGhlaWdodCgpewoJCXJldHVybiBfaGVpZ2h0OwoJfQpwcml2YXRlOgoJdHlwZWRlZiB2ZWN0b3I8ZmllbGRfdHlwZT4gcm93X3R5cGU7CglzaXplX3QgX3dpZHRoLCBfaGVpZ2h0OwoJdmVjdG9yPHJvd190eXBlPiBfZmllbGRzOwp9OwoKY2xhc3MgU25ha2V7CglmcmllbmQgY2xhc3MgRHJhd2VyOwpwdWJsaWM6CglzdHJ1Y3QgQm9keUVsZW1lbnR7CgkJY2hhciBzaWduOwoJCWludCB4LCB5OwoJfTsKCQoJU25ha2UoRGlyZWN0aW9uIGRpciwgQm9keUVsZW1lbnQgZWwpOiBfZGlyKGRpcil7CgkJX2JvZHlFbGVtZW50cy5wdXNoX2JhY2soZWwpOwoJfQoJCglEaXJlY3Rpb24gZGlyZWN0aW9uKCl7CgkJcmV0dXJuIF9kaXI7Cgl9CgkKCXZvaWQgc2V0RGlyZWN0aW9uKERpcmVjdGlvbiB2YWwpewoJCV9kaXIgPSB2YWw7Cgl9CgkKCUJvZHlFbGVtZW50ICZoZWFkKCl7CgkJcmV0dXJuIF9ib2R5RWxlbWVudHMuYmFjaygpOwoJfQoJCgljb25zdCBCb2R5RWxlbWVudCAmaGVhZCgpIGNvbnN0ewoJCXJldHVybiBfYm9keUVsZW1lbnRzLmJhY2soKTsKCX0KCQoJdm9pZCBhZGRCb2R5RWxlbWVudChjaGFyIHNpZ24pewoJCUJvZHlFbGVtZW50IG5ld0VsZW1lbnQgPSBoZWFkKCk7CgkJbmV3RWxlbWVudC5zaWduID0gc2lnbjsKCQlfbW92ZUZ1bmNzW19kaXJdKG5ld0VsZW1lbnQpOwoJCV9ib2R5RWxlbWVudHMucHVzaF9iYWNrKG5ld0VsZW1lbnQpOwoJfQpwcml2YXRlOgoJRGlyZWN0aW9uIF9kaXI7Cgl2ZWN0b3I8Qm9keUVsZW1lbnQ+IF9ib2R5RWxlbWVudHM7CglzdGF0aWMgbWFwPERpcmVjdGlvbiwgdm9pZCgqKShCb2R5RWxlbWVudCAmKT4gX21vdmVGdW5jczsKfTsKCm1hcDxEaXJlY3Rpb24sIHZvaWQoKikoU25ha2U6OkJvZHlFbGVtZW50ICYpPiBTbmFrZTo6X21vdmVGdW5jcyA9IHsKCXt7VVB9LCB7W10oQm9keUVsZW1lbnQgJmJlKXsgLS1iZS55OyB9fX0sCgl7e0RPV059LCB7W10oQm9keUVsZW1lbnQgJmJlKXsgKytiZS55OyB9fX0sCgl7e0xFRlR9LCB7W10oQm9keUVsZW1lbnQgJmJlKXsgLS1iZS54OyB9fX0sCgl7e1JJR0hUfSwge1tdKEJvZHlFbGVtZW50ICZiZSl7ICsrYmUueDsgfX19Cn07CgpjbGFzcyBEcmF3ZXJ7CnB1YmxpYzoKCURyYXdlcihNYXAgJm1hcCk6IF9tYXAobWFwKXt9Cgl2b2lkIHNuYWtlKGNvbnN0IFNuYWtlICZzbmFrZSl7CgkJZm9yKGF1dG8gJmVsIDogc25ha2UuX2JvZHlFbGVtZW50cykKCQkJX21hcC5hdChlbC54LCBlbC55KSA9IGVsLnNpZ247Cgl9Cgl2b2lkIG9wZXJhdG9yKCkoKXsKCQlmb3Ioc2l6ZV90IHkgPSAwOyB5IDwgX21hcC5oZWlnaHQoKTsgKyt5KXsKCQkJZm9yKHNpemVfdCB4ID0gMDsgeCA8IF9tYXAud2lkdGgoKTsgKyt4KQoJCQkJY291dCA8PCBfbWFwLmF0KHgsIHkpOwoJCQljb3V0IDw8IGVuZGw7CgkJfQoJfQpwcml2YXRlOgogCU1hcCAmX21hcDsKfTsKCmludCBtYWluKCkgewoJTWFwIG15TWFwKDUsIDUpOwoJU25ha2Ugc25ha2UoRE9XTiwgU25ha2U6OkJvZHlFbGVtZW50eyd4JywgMCwgMH0pOwoJRHJhd2VyIGRyYXcobXlNYXApOwoJc25ha2UuYWRkQm9keUVsZW1lbnQoJ2EnKTsKCXNuYWtlLmFkZEJvZHlFbGVtZW50KCdiJyk7CglzbmFrZS5zZXREaXJlY3Rpb24oUklHSFQpOwoJc25ha2UuYWRkQm9keUVsZW1lbnQoJ2MnKTsKCXNuYWtlLmFkZEJvZHlFbGVtZW50KCdkJyk7CglzbmFrZS5zZXREaXJlY3Rpb24oVVApOwoJc25ha2UuYWRkQm9keUVsZW1lbnQoJ2UnKTsKCXNuYWtlLmFkZEJvZHlFbGVtZW50KCdmJyk7CglkcmF3LnNuYWtlKHNuYWtlKTsKCWRyYXcoKTsKCXJldHVybiAwOwp9