IoIiderp

floodfill pathfinding

Nov 26th, 2018
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.12 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. #include <SFML/Graphics.hpp>
  5.  
  6. struct Cell
  7. {
  8.     int dist;
  9. };
  10.  
  11. struct Position
  12. {
  13.     int x;
  14.     int y;
  15.  
  16.     Position(int x, int y)
  17.     : x(x), y(y)
  18.     {}
  19.  
  20.     bool operator==(Position& b)
  21.     {
  22.         if(b.x != x)
  23.             return false;
  24.         if(b.y != y)
  25.             return false;
  26.  
  27.         return true;
  28.     }
  29.  
  30.     bool operator!=(Position& b)
  31.     {
  32.         if(b.x != x)
  33.             return true;
  34.         if(b.y != y)
  35.             return true;
  36.  
  37.         return false;
  38.     }
  39. };
  40.  
  41. const unsigned int cellsHorizontal = 30,
  42.                    cellsVertical   = 20;
  43.  
  44. Cell cells[cellsHorizontal][cellsVertical];
  45. Cell startCells[cellsHorizontal][cellsVertical];
  46.  
  47. Position startpos(5, 10);
  48. Position endpos(7, 17);
  49.  
  50. std::vector<Position> getNeighbours(Position pos, int width, int height)
  51. {
  52.     std::vector<Position> neighbours;
  53.  
  54.     if(pos.y+1 != height)
  55.         if(cells[pos.x][pos.y+1].dist == 0)
  56.             neighbours.push_back({pos.x, pos.y+1});
  57.  
  58.     if(pos.y-1 >= 0)
  59.         if(cells[pos.x][pos.y-1].dist == 0)
  60.             neighbours.push_back({pos.x, pos.y-1});
  61.  
  62.     if(pos.x+1 != width)
  63.         if(cells[pos.x+1][pos.y].dist == 0)
  64.             neighbours.push_back({pos.x+1, pos.y});
  65.  
  66.     if(pos.x-1 >= 0)
  67.         if(cells[pos.x-1][pos.y].dist == 0)
  68.             neighbours.push_back({pos.x-1, pos.y});
  69.  
  70.     return neighbours;
  71. }
  72.  
  73. std::vector<Position> getPathNeighbours(Position pos, int width, int height)
  74. {
  75.     std::vector<Position> neighbours;
  76.  
  77.     if(pos.y+1 != height)
  78.         if(cells[pos.x][pos.y+1].dist > 0)
  79.             neighbours.push_back({pos.x, pos.y+1});
  80.  
  81.     if(pos.y-1 >= 0)
  82.         if(cells[pos.x][pos.y-1].dist > 0)
  83.             neighbours.push_back({pos.x, pos.y-1});
  84.  
  85.     if(pos.x+1 != width)
  86.         if(cells[pos.x+1][pos.y].dist > 0)
  87.             neighbours.push_back({pos.x+1, pos.y});
  88.  
  89.     if(pos.x-1 >= 0)
  90.         if(cells[pos.x-1][pos.y].dist > 0)
  91.             neighbours.push_back({pos.x-1, pos.y});
  92.  
  93.     return neighbours;
  94. }
  95.  
  96. bool isPartOfPath(Position pos, std::vector<Position> path)
  97. {
  98.     for(Position& pathPos : path)
  99.     {
  100.         if(pathPos == pos)
  101.             return true;
  102.     }
  103.  
  104.     return false;
  105. }
  106.  
  107. std::vector<Position> filterCells(std::vector<Position> vec)
  108. {
  109.     std::vector<Position> ret;
  110.  
  111.     for(int i=0; i<vec.size(); i++)
  112.     {
  113.         bool duplicate = false;
  114.  
  115.         for(int r=0; r<ret.size(); r++)
  116.         {
  117.             if(ret[r].x == vec[i].x)
  118.             {
  119.                 if(ret[r].y == vec[i].y)
  120.                 {
  121.                     duplicate = true;
  122.                     break;
  123.                 }
  124.             }
  125.         }
  126.  
  127.         if(!duplicate)
  128.         {
  129.             int x = vec[i].x;
  130.             int y = vec[i].y;
  131.             if(cells[x][y].dist == 0)
  132.                 ret.push_back(vec[i]);
  133.         }
  134.     }
  135.  
  136.     return ret;
  137. }
  138.  
  139. void calculateDistances(int width, int height)
  140. {
  141.     std::vector<Position> currCells, nextCells;
  142.     currCells.push_back(endpos);
  143.     int dist = 1;
  144.  
  145.     while(currCells.size())
  146.     {
  147.         for(int i=0; i<currCells.size(); i++)
  148.         {
  149.             int x = currCells[i].x;
  150.             int y = currCells[i].y;
  151.             cells[x][y].dist = dist;
  152.             std::vector<Position> neighbours = getNeighbours(currCells[i], width, height);
  153.             nextCells.insert(nextCells.end(), neighbours.begin(), neighbours.end());
  154.         }
  155.  
  156.         dist++;
  157.  
  158.         currCells = filterCells(nextCells);
  159.     }
  160. }
  161.  
  162. std::vector<Position> findPath(int width, int height)
  163. {
  164.     std::vector<Position> path;
  165.  
  166.     Position currCell = startpos;
  167.     while(currCell != endpos)
  168.     {
  169.         std::vector<Position> neighbours = getPathNeighbours(currCell, width, height);
  170.         std::sort(neighbours.begin(), neighbours.end(), [](Position &a, Position &b){
  171.             return cells[a.x][a.y].dist < cells[b.x][b.y].dist;
  172.         });
  173.  
  174.         if(neighbours.size() == 0)
  175.             return path;
  176.  
  177.         currCell = neighbours[0];
  178.         path.push_back(currCell);
  179.     }
  180.  
  181.     return path;
  182. }
  183.  
  184. int main()
  185. {
  186.     for(int x = 0; x < cellsHorizontal; x++)
  187.     {
  188.         for(int y = 0; y < cellsVertical; y++)
  189.         {
  190.             // Initialise
  191.             startCells[x][y].dist = 0;
  192.  
  193.             // Create walls
  194.             if(!x || !y || x==cellsHorizontal-1 || y==cellsVertical-1)
  195.                 startCells[x][y].dist = -1;
  196.         }
  197.     }
  198.  
  199.  
  200.     sf::RenderWindow window({800, 600}, "Floodfill example");
  201.  
  202.     while(window.isOpen())
  203.     {
  204.         // Events
  205.         sf::Event event;
  206.         while(window.pollEvent(event))
  207.         {
  208.             if(event.type == sf::Event::Closed)
  209.                 window.close();
  210.  
  211.             if(event.type == sf::Event::MouseButtonPressed)
  212.             {
  213.                 if(sf::Mouse::isButtonPressed(sf::Mouse::Button::Left))
  214.                 {
  215.                     sf::Vector2i cellClicked = sf::Mouse::getPosition(window) / 21;
  216.                     int x = cellClicked.x;
  217.                     int y = cellClicked.y;
  218.                     if(x < cellsHorizontal && y < cellsVertical)
  219.                     {
  220.                         if(startCells[x][y].dist == 0)
  221.                         {
  222.                             startCells[x][y].dist = -1;
  223.                         } else {
  224.                             startCells[x][y].dist = 0;
  225.                         }
  226.                     }
  227.                 }
  228.             }
  229.         }
  230.  
  231.         // Rendering
  232.         window.clear({35, 35, 35});
  233.  
  234.         sf::RectangleShape rect({20.f, 20.f});
  235.         sf::Text txt;
  236.         sf::Font fnt;
  237.         fnt.loadFromFile("arial.ttf");
  238.         txt.setFont(fnt);
  239.         txt.setCharacterSize(12);
  240.         txt.setColor(sf::Color::Black);
  241.  
  242.         for(int x = 0; x < cellsHorizontal; x++)
  243.         {
  244.             for(int y = 0; y < cellsVertical; y++)
  245.             {
  246.                 cells[x][y].dist = startCells[x][y].dist;
  247.             }
  248.         }
  249.  
  250.         calculateDistances(cellsHorizontal, cellsVertical);
  251.         std::vector<Position> path = findPath(cellsHorizontal, cellsVertical);
  252.  
  253.         for(int x = 0; x < cellsHorizontal; x++)
  254.         {
  255.             for(int y = 0; y < cellsVertical; y++)
  256.             {
  257.                 rect.setPosition({21.f*x, 21.f*y});
  258.  
  259.                 if(cells[x][y].dist < 0)
  260.                 {
  261.                     rect.setFillColor({120,120,120});
  262.                 } else {
  263.                     rect.setFillColor(sf::Color::White);
  264.                 }
  265.  
  266.                 if(isPartOfPath(Position(x,y), path))
  267.                     rect.setFillColor(sf::Color::Yellow);
  268.  
  269.                 if(Position(x,y) == startpos)
  270.                     rect.setFillColor(sf::Color::Green);
  271.  
  272.                 if(Position(x,y) == endpos)
  273.                     rect.setFillColor(sf::Color::Red);
  274.  
  275.                 window.draw(rect);
  276.  
  277.  
  278.                 txt.setPosition({21.f*x, 21.f*y});
  279.                 txt.setString(std::to_string(cells[x][y].dist));
  280.                 window.draw(txt);
  281.             }
  282.         }
  283.  
  284.         window.setView(sf::View({0, 0, window.getSize().x, window.getSize().y}));
  285.  
  286.         window.display();
  287.     }
  288. }
Advertisement
Add Comment
Please, Sign In to add comment