• Home
  • About
    • Hanna's Blog photo

      Hanna's Blog

      I wanna be a global developer.

    • Learn More
    • Email
    • LinkedIn
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

[C#] BFS Maze

28 Dec 2020

Reading time ~2 minutes

Reference by [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part2: 자료구조와 알고리즘

Code

  • Player.cs
  using System;
  using System.Collections.Generic;
  using System.Text;

  namespace BFSMaze
  {
    class Pos
    {
      public Pos(int y, int x) { Y = y; X = x; }
      public int Y;
      public int X;
    }

    class Player
    {
      public int PosY { get; private set; }
      public int PosX { get; private set; }
      Random _random = new Random();
      Board _board;

      enum Dir
      {
        Up = 0,
        Left = 1,
        Down = 2,
        Right = 3
      }

      int _dir = (int)Dir.Up;
      List<Pos> _points = new List<Pos>();

      public void Initialize(int posY, int posX, Board board)
      {
        PosY = posY;
        PosX = posX;
        _board = board;

        BFS();
      }

      void BFS()
      {
        int[] deltaY = new int[] { -1, 0, 1, 0};
        int[] deltaX = new int[] { 0, -1, 0, 1 };

        bool[,] found = new bool[_board.Size, _board.Size];
        Pos[,] parent = new Pos[_board.Size, _board.Size];

        Queue<Pos> q = new Queue<Pos>();
        q.Enqueue(new Pos(PosY, PosX));
        found[PosY, PosX] = true;
        parent[PosY, PosX] = new Pos(PosY, PosX);

        while ( q.Count > 0)
        {
          Pos pos = q.Dequeue();
          int nowY = pos.Y;
          int nowX = pos.X;

          for(int i=0; i<4; i++)
          {
            int nextY = nowY + deltaY[i];
            int nextX = nowX + deltaX[i];

            if (nextX < 0 || nextX >= _board.Size || nextY < 0 || nextY >= _board.Size)
              continue;
            if (_board.Tile[nextY, nextX] == Board.TileType.Wall)
              continue;
            if (found[nextY, nextX] == true)
              continue;

            q.Enqueue(new Pos(nextY, nextX));
            found[nextY, nextX] = true;
            parent[nextY, nextX] = new Pos(nowY, nowX);
          }
        }

        int y = _board. DestY;
        int x = _board.DestX;
        while (parent[y,x].Y != y || parent[y, x].X != x)
        {
          _points.Add(new Pos(y, x));
          Pos pos = parent[y, x];
          y = pos.Y;
          x = pos.X;
        }

        _points.Add(new Pos(y, x));
        _points.Reverse();
      }

      const int MOVE_TICK = 10;
      int _sumTick = 0;
      int _lastIndex = 0;

      public void Update(int deltaTick)
      {
        if (_lastIndex >= _points.Count)
          return;

        _sumTick += deltaTick;
        if (_sumTick >= MOVE_TICK)
        {
          _sumTick = 0;

          PosY = _points[_lastIndex].Y;
          PosX = _points[_lastIndex].X;
          _lastIndex++;
        }
      }
    }
  }

Algorithm

  • Breadth First Search
    • Start at the root node
    • Navigate to adjacent nodes first
  • BFS shortest Path Algorithm
    • Use Queue
    • Enqueue start root, looping while not empty
    • Dequeue in loop
    • If the node is not visited, change to be visited
    • Save parent node, reverse

Queue

  • Enqueue
    • Insert new node to last
  • Dequeue
    • Pop first node
  Queue<Pos> q = new Queue<Pos>();
  q.Enqueue(new Pos(PosY, PosX));
  ...
  while ( q.Count > 0)
  {
    Pos pos = q.Dequeue();
    ...

List

  • Reverse
    • Reverse order of list
  _points.Reverse();

Search Path

  • deltaY & deltaX
    • Can go every direction
    • If path faces wall, dequeue
    • As a result, only shortest path remains
  int[] deltaY = new int[] { -1, 0, 1, 0};
  int[] deltaX = new int[] { 0, -1, 0, 1 };

  for(int i=0; i<4; i++)
  {
    int nextY = nowY + deltaY[i];
    int nextX = nowX + deltaX[i];
    ...

Result

Download



C#GameAlgorithm Share Tweet +1