public List<Vertex> Successors(Vertex v)
 {
     int colLeft = v.X - 1;
     int colRight = v.X + 1;
     int rowTop = v.Y - 1;
     int rowBottom = v.Y + 1;
     List<Vertex> successors = new List<Vertex>();
     if(rowTop > 0 && colLeft > 0)
         for(int i = 0 ; i < 3; i++)
             successors.Add(new Vertex(rowTop,i+colLeft));
     return successors;
 }
 public List<Vertex> SearchShortestPath(Vertex start,Func<Vertex,bool> IsGoal, Func<Vertex,List<Vertex>> Successors)
 {
     Queue<List<Vertex>> frontier = new Queue<List<Vertex>>();
     HashSet<Vertex> explored = new HashSet<Vertex>();
     frontier.Enqueue(new List<Vertex>(){start});
     while(frontier.Count > 0){
         List<Vertex> path = frontier.Dequeue();
         Vertex v = path[path.Count - 1];
         if(!explored.Contains(v)){
             explored.Add(v);
             if(IsGoal(v))
                 return path;
             List<Vertex> successors = Successors(v);
             foreach(Vertex vertex in successors){
                 path.Add(vertex);
                 frontier.Enqueue(path);}
         }
     }
     return null;
 }
 public bool IsGoal(Vertex v)
 {
     return (v.X == end.X && v.Y == end.Y);
 }