Convert array to nodes - c++
Let me start off with saying that I have very basic knowledge of nodes and graphs.
My goal is to make a solver for a maze which is stored as an array. I know exactly how to implement the algorithm for solving (I'm actually implementing a couple of them) but what my problem is, is that I am very confused on how to implement the nodes that the solver will use in each empty cell.
Here is an example array:
char maze[5][9] =
"#########",
"# # #",
"# ## ## #",
"# # #",
"#########"
My solver starts at the top left and the solution (exit) is at the bottom right.
I've read up on how nodes work and how graphs are implemented, so here is how I think I need to make this:
Starting point will become a node
Each node will have as property the column and the row number
Each node will also have as property the visited state
Visited state can be visited, visited and leads to dead end, not visited
Every time a node gets visited, every directly adjacent, empty and not visited cell becomes the visited node's child
Every visited node gets put on top of the solutionPath stack (and marked on the map as '*')
Every node that led to a dead end is removed from the stack (and marked on the map as '~')
Example of finished maze:
"#########",
"#*~#****#",
"#*##*##*#",
"#****~#*#",
"#########"
Basically my question is, am I doing something really stupid here with my way of thinking (since I am really inexperienced with nodes) and if it is could you please explain to me why? Also if possible provide me other websites to check which implement examples of graphs on real world applications so I can get a better grasp of it.
The answer really depends on what you find most important in the problem. If you're searching for efficiency and speed - you're adding way too many nodes. There's no need for so many.
The efficient method
Your solver only needs nodes at the start and end of the path, and at every possible corner on the map. Like this:
"#########",
"#oo#o o#",
"# ## ## #",
"#o oo#o#",
"#########"
There's no real need to test the other places on the map - you'll either HAVE TO walk thru them, or won't have need to even bother testing.
If it helps you - I got a template digraph class that I designed for simple graph representation. It's not very well written, but it's perfect for showing the possible solution.
#include <set>
#include <map>
template <class _nodeType, class _edgeType>
class digraph
{
public:
set<_nodeType> _nodes;
map<pair<unsigned int,unsigned int>,_edgeType> _edges;
};
I use this class to find a path in a tower defence game using the Dijkstra's algorithm. The representation should be sufficient for any other algorithm tho.
Nodes can be of any given type - you'll probably end up using pair<unsigned int, unsigned int>. The _edges connect two _nodes by their position in the set.
The easy to code method
On the other hand - if you're looking for an easy to implement method - you just need to treat every free space in the array as a possible node. And if that's what you're looking for - there's no need for designing a graph, because the array represents the problem in a perfect way.
You don't need dedicated classes to solve it this way.
bool myMap[9][5]; //the array containing the map info. 0 = impassable, 1 = passable
vector<pair<int,int>> route; //the way you need to go
pair<int,int> start = pair<int,int>(1,1); //The route starts at (1,1)
pair<int,int> end = pair<int,int>(7,3); //The road ends at (7,3)
route = findWay(myMap,start,end); //Finding the way with the algorithm you code
Where findWay has a prototype of vector<pair<int,int>> findWay(int[][] map, pair<int,int> begin, pair<int,int> end), and implements the algorithm you desire. Inside the function you'll probably need another two dimensional array of type bool, that indicates which places were tested.
When the algorithm finds a route, you usually have to read it in reverse, but I guess it depends on the algorithm.
In your particular example, myMap would contain:
bool myMap[9][5] = {0,0,0,0,0,0,0,0,0,
0,1,1,0,1,1,1,1,0,
0,1,0,0,1,0,0,1,0,
0,1,1,1,1,1,0,1,0,
0,0,0,0,0,0,0,0,0};
And findWay would return a vector containing (1,1),(1,2),(1,3),(2,3),(3,3),(4,3),(4,2),(4,1),(5,1),(6,1),(7,1),(7,2),(7,3)
Related
Finding cycles in a directed graph implemented using an unordered multimap
So, I've implemented a directed graph using an unordered multimap. Each pair within the map is made up of two strings: the vertex and its adjacent vertex. Now, I am trying to determine if my graph has a cycle, and if so, how big is the cycle. This is the code I have so far: int findCycle(const unordered_multimap<string,string> & connectedURLVertices, string y, string key) { string position; position=y.find(key); if(position!=string::npos) { return 1; } auto nodesToCheck=connectedURLVertices.equal_range(key); for(auto & node : nodesToCheck) { int z=findCycle(connectedURLVertices,y+key,node); } } I've walked through the code on paper and it seems to be logically correct, but I would appreciate it if anyone could take a look and see if I am on the right track or missing anything. Thanks!
To search for cycles in a graph you have to descend recursively through the arcs from some initial node until you reach one already visited node (you can construct a std::set of already visited nodes or mark the nodes as you visit them) or exhaust all the nodes without getting one already visited (absence of cycles) The criterion to select the arc can be adjusted to find it more quickly or the kind of search (first in depth, search by level, etc.)
Sorting a 2D vector of objects
I am working on a little puzzle game ( Gem Puzzle). I have a puzzle Piece object for each piece on the board that has the following attributes: Position Pcorrect_; Position Pactuel_; bool estvide_; (the 3rd attribute is irrelevant for this question) The Position is simple structure consisting of: unsigned ligne; unsigned colonne; Each Piece is stored in a vector of a vector. std::vector<std::vector<Piece>> board_; The Pieces eventually get mixed around so the correct attribute (location) does not match the actual attribute (location). I am stuck on a method that should sort the board.The actual position has to match the current position for each piece of the board. Is there an elegant way of doing this with a sort function ?My current approach is using 4 loops and lots of conditions which is probably the wrong way of doing it.
if you use C++11, you can create a tuple and sort it. You can define a custom comparison, like in this example: http://www.hongliangjie.com/2011/10/10/sortin-tuples-in-c/
Constructing a tree from an array for a DFS solver
I am making a maze solver using DFS and I want to implement the search tree for it but I am a bit new to artificial intelligence and I want a little bit of help on this matter. Let me give a maze example first: char maze[5][9] = "#########", "# # #", "# ## # #", "# # #", "#########", So my search tree for DFS should be something like this: "#########", "#12#15 10 11 #", "#3##14 9 #12 #", "#456 7 8 #13 #", "#########", 1st child of parent -> Right Cell if it is empty 2nd child of parent -> Bottom Cell if it is empty 3rd child of parent -> Left Cell if it is empty 4th child of parent -> Top Cell if it is empty My solver will receive as an argument my maze array. My questions are these: 1st question: Is this actually the way the nodes are going to get visited by my actor? 2nd question: In the code do I need to declare 15 as child of 10? (also in other cases like 9 with 14) 3rd question: When my solver receives the array do I need to make a pre-process on the array and construct the tree from the array or will my actor construct it as he goes?
I also assume the rule of "do not include a node in the solution tree if it was already in the tree"? Because that sure helps. Typically the tree is implicit, and you only construct the parts of the tree you actually visit, often tearing things down as you roll it back. Your solver keeps track of the current steps along the tree. You probably also want to keep track of what cells you have explored in the maze. If the maze has only # and characters, use * to indicate you have visited the cell in this solver. You start at some location. If that location is valid, you mark it with a * so you don't come back to it, and add that location (say, (1,1))to your "stack" of your path. Now, you follow the rules you wrote above. Check the cell under your current location. Is it empty? (not a # or a *) If so, recurse, asking if that finds the way out. If it finds the way out, take the path it found, prepend your current node, and return that path as the way out. If it does not, search in the next adjacent cell (by the order above). Finally, wrap the above recursive routine with a function that calls it, then removes the * marks from the map. The tree you walk is implicitly coded. Building the tree forces you to visit every node, and you only want to build the parts that you have to. This can be optimized in a number of ways. You can avoid writing to the map by working on a "ghost" copy of it. You can avoid prepending by passing the stack to the recursive versions, which carefully remove any extra nodes if they fail, and leave them on if they succeed. Or you can use a real stack, and encode the path backwards, with a wrapping function that (after all the work is done) reverses the path so it is in a more conventional order.
C++ recursion for connectivity graph
I haven't implemented anything yet, but I was thinking of using recursion to identify all cells in a grid that are 'actively connected' to a given cell, i.e., cells that are 'active' and directly connected by virtue of sharing a face with the (active) cell in question or more distantly/indirectly connected by sharing a face with one of its (active) neighbors. The disconnections come about because some of the cells in the grid maybe deemed 'inactive' (by whatever definition). My idea/pseudo-code is as follows: //Call function to traverse connections traverse_connections(cell); //Traverse function definition bool traverse_connections(cell) { //Check if cell is inactive or traversed - base case if (current cell is inactive or traversed) { return true; } //-Mark cell then move on to its neighbors Mark cell as traversed and add it to the list of 'actively connected' cells; bool ok = true; for(neighbor_cell in neighbors of cell) { ok &= traverse_connections(neighbor_cell); } return ok; } I think this covers the base case, marks the cell, then moves on to do the same for its neighbors, its neighbors' neighbors, and so on. Does this look OK? Are there any obvious gaps I am missing? Would appreciate if anyone with expertise in graph connectivity and recursion can weigh in. I am also having trouble coming up with an iterative equivalent. Any ideas on that would be much appreciated too. Thanks in advance!
This solution will not work, because it mixes up the concepts of "traversed" and "active/connected". The two are orthogonal: for example, a cell may be inactive and traversed, or active and not traversed. The if statement at the top of your pseudocode returns true for both, which is incorrect. You should keep a table that marks cells traversed separate from the table that marks cells active. You need to make sure that a cell is marked traversed before going into the recursive call, otherwise the solution may be too slow, or even run out of stack. Finally, the solution does not need to be recursive: you can accomplish what you need by a straightforward Breadth-first search, which can be done with a queue instead of recursion.
The way you are marking the cells at the moment will most likely cause you problems. For example if one of these cells you are marking has neighbouring cells which need to be traversed later then they may go untraversed. If you look into the A* (A-Star) algorithm it should give you a good idea of graph traversal. UCS (uniform cost search) is also another algorithm which uses graph traversal.
Choosing the best stucture for my list of players
I am in trouble choosing the most pertinent structure for my data, here are the explanations: I am actually working on a game project for school, a Bomberman like game in c++. I am designing the Map object, who contain Bombs, Boxes, Players and Walls. The map is 2D, I have already 2 containers of type: std::unordered_map<int, std::unordered_map<int, AEntity*> > *UMap; One contain Walls, the other contain destructible objects (Bombs, Boxes). I have already discussed this choice here -> Choice of unsorted_map. It's mainly for fast access time and because there can only be one element per map's box. Now as the title suggest I'am in trouble choosing a data container for my players, because there can be multiple players on a single map's box, unordered_maps can't be used. In a first time I was going to use a std::list<AEntity*> sorted with std::sorted, AEntity containing the entity information (coords), but while coding my playerOn(const int x, const int y); function I found it was a poor choice. I can't retrieve fast enough which player(s) is on the given box using dichotomies, and if there is no player of this box it's a waste of time. How should I store my (AEntity)Players in order to be able to retrieve them fast (On of the itchy thing is that there can be more than 500 player at the single time, on big map, that's why I am looking for optimization) I am running out of brain juice. Thanks for your future answers. Edit about my probleme It's mainly because I want to know if there is another solution to go trough my whole std::list of player to find if there is someone on box(x, y). Looks slow and not optimized, but i can't figure another way to do this. (I can change container type if needed)
First of all, before trying any optimization, you should profile your code to detect where is the bottleneck. You will be surprised. Once that said : 1) Your unordered_maps seem like a lot of over-engineering. The answers provided in your previous post are true but I think it is useless in your case. You absolutely do not care of a O(log(n)) cost when n = 500. Just make a vector of Entities*. It is much enough. 2) You seem to be falling in the god object anti-design pattern. A bomberman game is an excellent project for studying OOP, as it teaches you to avoid the God Object design pattern. Make sure each class does its own business and no class handles all the logic (I suspect your class Map or Game has too much power). a) Create a vector of players, a vector of bombs, a vector of walls, a vector of fires, etc. b) Map should be a 2-dimensionnal array storing list of pointers to the entities that are present on each Map's box. (Each Map[i][j] holds pointers to all the elements that are on the box of index (i,j)). c) Bombs should create fire elements. d) Your central routine should be something like : while(gameContinued) { for each entity in the game { entity.Update(map); } game.Render(); } Bomb update consists in making the bomb's texture rendering dynamic and create fires if delay is over-due (and update the Map with the fires pointers accordingly). Fire update consists in nothing except vanishing if delay is over-due (and update the Map). Player update consists in moving through keyboard event handling (and updating their current internal x and y values ), creating bomb if needed, dying if for their position (x,y), there is a fire in the Map[i][j] list of entities. 3) In most of my students implementation of bomberman, the only issue they can get is with textures and deep copy of objects. Make sure you have a Texture Loader (using Singleton Pattern) to avoid loading multiple times the same textures, and you should be fine.