Click here to Skip to main content
15,894,460 members
Articles / Programming Languages / C# 4.0

A Complex - Yet Quite Intelligible - Pathfinding in C#

Rate me:
Please Sign up or sign in to vote.
4.96/5 (41 votes)
30 Aug 2013CPOL21 min read 59.9K   2.5K   88  
A semi-analytic 2D path-finding for large dynamic scenarios.
using System;
using System.Drawing;
using YinYang.CodeProject.Projects.SimplePathfinding.PathFinders.AStar;

namespace YinYang.CodeProject.Projects.SimplePathfinding.PathFinders
{
    public abstract class BaseGraphSearchMap<TNode> where TNode : BaseGraphSearchNode<TNode>
    {
        #region | Fields |

        private readonly Int32 width;
        private readonly Int32 height;

        private TNode[] nodes;
        private Int32[] fastY;

        #endregion

        #region | Properties |

        /// <summary>
        /// Gets the open nodes count.
        /// </summary>
        public Int32 OpenCount
        {
            get { return OnGetCount(); }
        }

        #endregion

        #region | Indexers |

        /// <summary>
        /// Gets the <see cref="AStarNode"/> on a given coordinates.
        /// </summary>
        public TNode this[Int32 x, Int32 y]
        {
            get { return nodes[x + fastY[y]]; }
        }

        #endregion

        #region | Constructors |

        /// <summary>
        /// Initializes a new instance of the <see cref="BaseGraphSearchMap{TNode}"/> class.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        protected BaseGraphSearchMap(Int32 width, Int32 height)
        {
            this.width = width;
            this.height = height;

            Precalculate();
        }

        #endregion

        #region | Helper methods |

        private void Precalculate()
        {
            fastY = new Int32[height];

            for (Int32 y = 0; y < height; y++)
            {
                fastY[y] = y * width;
            }
        }

        private void OpenNodeInternal(Point point, TNode result)
        {
            nodes[point.X + fastY[point.Y]] = result;
            OnAddNewNode(result);
        }

        #endregion

        #region | Virtual/abstract methods |

        protected abstract TNode OnCreateFirstNode(Point startPoint, Point endPoint);
        protected abstract TNode OnCreateNode(Point point, TNode origin, params Object[] arguments);

        protected abstract Int32 OnGetCount();
        protected abstract void OnAddNewNode(TNode result);
        protected abstract TNode OnGetTopNode();
        protected abstract void OnClear();

        #endregion

        #region | Methods |

        /// <summary>
        /// Creates new open node on a map at given coordinates and parameters.
        /// </summary>
        public void OpenNode(Point point, TNode origin, params Object[] arguments)
        {
            TNode result = OnCreateNode(point, origin, arguments);
            OpenNodeInternal(point, result);
        }

        public void OpenFirstNode(Point startPoint, Point endPoint)
        {
            TNode result = OnCreateFirstNode(startPoint, endPoint);
            OpenNodeInternal(startPoint, result);
        }

        /// <summary>
        /// Creates the empty node at given point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <returns></returns>
        public TNode CreateEmptyNode(Point point)
        {
            return OnCreateNode(point, null); 
        }

        /// <summary>
        /// Returns top node (best estimated score), and closes it.
        /// </summary>
        /// <returns></returns>
        public TNode CloseTopNode()
        {
            TNode result = OnGetTopNode();
            result.MarkClosed();
            return result;
        }

        /// <summary>
        /// Clears map for another round.
        /// </summary>
        public void Clear()
        {
            nodes = new TNode[width*height];
            OnClear();
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Czech Republic Czech Republic
Contacts: EMAIL - smartk8@gmail.com

Comments and Discussions