#include #include #include #include #include #include #include #include #include typedef enum { Empty = 0, Floor = 1, Wall = 2 } TileType; typedef enum { Forward = 0, TurnRight = 1, TurnLeft = 2 } Command; typedef enum { FacingUp = 0, FacingRight = 1, FacingDown = 2, FacingLeft = 3, MAX_FACING = 4 } Facing; class Tile { public: Tile(int x, int y, TileType t) { m_x = x; m_y = y; m_type = t; } Tile() { m_x = -1; m_y = -1; m_type = TileType::Empty; } void print(); int m_x; int m_y; TileType m_type; }; class Player { public: Tile* m_loc; Facing m_facing; void turn(Command c); }; void Player::turn(Command c) { switch (c) { case TurnLeft: case TurnRight: default: throw "Invalid turn direction"; } MAX_FACING } void Tile::print() { switch (m_type) { case TileType::Empty: std::cout << " "; return; case TileType::Wall: std::cout << "#"; return; case TileType::Floor: std::cout << "."; return; default: std::cout << "!"; return; } } std::vector split(std::string s, std::string delimiter) { size_t pos_start = 0, pos_end, delim_len = delimiter.length(); std::string token; std::vector res; while ((pos_end = s.find (delimiter, pos_start)) != std::string::npos) { token = s.substr (pos_start, pos_end - pos_start); pos_start = pos_end + delim_len; res.push_back (token); } res.push_back (s.substr (pos_start)); return res; } /** * Print the map, optionally showing the palyer on it */ void printMap(Tile* map, int w, int h, Player* p) { for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { if (p != NULL && p->m_loc->m_x == x && p->m_loc->m_y == y) { std::cout << "@"; } else { map[y * w + x].print(); } } std::cout << std::endl; } } void printCommands(std::vector& commands) { int moves = 0; for (int i = 0; i < commands.size(); ++i) { Command& c = commands[i]; switch (c) { case Forward: moves++; if (i == commands.size()-1) { std::cout << "move forward: " << moves << std::endl; } break; case TurnLeft: std::cout << "move forward: " << moves << std::endl; std::cout << "turn left" << std::endl; moves = 0; break; case TurnRight: std::cout << "move forward: " << moves << std::endl; std::cout << "turn right" << std::endl; moves = 0; break; } } } /** * Go through the map from top to bottom, left to right, and find first * tile that is open floor */ Tile* findFirst(Tile* map, int w, int h) { for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { Tile* t = &map[y * w + x]; if (t->m_type == TileType::Floor) { return t; } } } return NULL; } int main(int argc, char** argv) { if (argc < 2) { std::cout << "invalid input" << std::endl; return 1; } const std::string fpath = argv[1]; struct stat st; int ret = stat(fpath.c_str(), &st); if (ret != 0) { std::cout << "failed statting: " << fpath << ", " << strerror(errno) << std::endl; return 1; } FILE* fin = fopen(fpath.c_str(), "r"); if (!fin) { std::cout << "Failed opening: " << argv[1] << std::endl; return 1; } char* buf = new char[st.st_size]; memset(buf, 0, st.st_size); size_t r = fread(buf, 1, st.st_size, fin); fclose(fin); if (r != st.st_size) { std::cout << "read: " << r << "/" << st.st_size << " bytes" << std::endl; delete[] buf; return 1; } std::vector lines; std::string l; for (size_t t = 0; t < st.st_size; ++t) { if (buf[t] == '\n') { lines.push_back(l); l = std::string(); continue; } l += buf[t]; } std::cout << "there are: " << lines.size() << " lines" << std::endl; delete[] buf; std::vector maplines; std::vector walklines; for (auto& line : lines) { line.erase(std::remove(line.begin(), line.end(), '\n'), line.cend()); if (line.size() == 0) { continue; } if (line[0] == '.' || line[0] == '#' || line[0] == ' ') { maplines.push_back(line); } else { walklines.push_back(line); } } if (walklines.size() > 1) { std::cout << "walk lines size: " << walklines.size() << std::endl; return 1; } std::string directions = walklines[0]; int map_width = 0; int map_height = maplines.size(); for (auto& w : maplines) { if (w.size() > map_width) { map_width = w.size(); } } // construct w*h map Tile* map = new Tile[map_width * map_height]; for (int y = 0; y < map_height; ++y) { for (int x = 0; x < map_width; ++x) { map[y * map_width + x] = Tile(x, y, TileType::Empty); } } // Assign each tile a type int row = 0; for (auto& l : maplines) { int column = 0; for (auto& c : l) { Tile* t = &map[row * map_width + column]; if (c == ' ') { t->m_type = TileType::Empty; } else if (c == '#') { t->m_type = TileType::Wall; } else { t->m_type = TileType::Floor; } column++; } row++; } // construct command list from input std::vector commands; std::stringstream ss; for (int i = 0; i < directions.size(); ++i) { char c = directions[i]; if (std::isdigit(c)) { ss << c; // handle last instruction being a move without turning if (i == directions.size()-1) { int count = 0; ss >> count; for (int j = 0; j < count; ++j) { commands.push_back(Forward); } } } else { bool isleft = false; if (c == 'L') { isleft = true; } else if (c == 'R') { isleft = false; } else { std::cout << "invalid direction: " << c << std::endl; return 1; } int count = 0; ss >> count; for (int j = 0; j < count; ++j) { commands.push_back(Forward); } commands.push_back(isleft ? TurnLeft : TurnRight); ss = std::stringstream(); } } printMap(map, map_width, map_height, NULL); printCommands(commands); Tile* start = findFirst(map, map_width, map_height); if (start == NULL || start->m_type != TileType::Floor) { std::cout << "invalid start tile" << std::endl; return 1; } Player p; p.m_loc = start; p.m_facing = 'R'; printMap(map, map_width, map_height, &p); std::cout << "starting tile x: " << start->m_x << ", y: " << start->m_y << std::endl; for (auto& c : commands) { switch (c) { case Forward: break; case TurnLeft: break; case TurnRight: break; } } delete[] map; return 0; }