Here is a sample code showing how to perform A* path finding in C# using SFML library:
main.csusing System;
using System.Collections.Generic;
using SFML.Graphics;
using SFML.System;
namespace AStarDemo
{
class Program
{
private static readonly int tileSize = 32; // size of each tile
static void Main(string[] args)
{
RenderWindow window = new RenderWindow(new VideoMode(640, 640), "A* Path Finding Demo");
window.Closed += Window_Closed;
// create the grid of tiles
int rowCount = window.Size.X / tileSize;
int colCount = window.Size.Y / tileSize;
Tile[,] tiles = new Tile[rowCount, colCount];
for (int row = 0; row < rowCount; ++row)
{
for (int col = 0; col < colCount; ++col)
{
tiles[row, col] = new Tile(TileType.Floor, new Vector2i(row, col));
}
}
tiles[2, 2].Type = TileType.Block; // add an obstacle
tiles[3, 2].Type = TileType.Block;
tiles[4, 2].Type = TileType.Block;
tiles[5, 2].Type = TileType.Block;
// perform A* path finding
List<Tile> path = AStar(tiles, new Vector2i(0, 0), new Vector2i(rowCount-1, colCount-1));
// draw the tiles and the path in the window
while (window.IsOpen)
{
window.DispatchEvents();
window.Clear(Color.White);
for (int row = 0; row < rowCount; ++row)
{
for (int col = 0; col < colCount; ++col)
{
RectangleShape shape = new RectangleShape(new Vector2f(tileSize, tileSize));
shape.Position = new Vector2f(row * tileSize, col * tileSize);
if (tiles[row, col].Type == TileType.Block)
{
shape.FillColor = Color.Black;
}
else
{
shape.FillColor = Color.White;
}
window.Draw(shape);
}
}
for (int i = 0; i < path.Count; ++i)
{
CircleShape shape = new CircleShape(tileSize / 2);
shape.Origin = shape.Radius * Vector2f.One;
shape.Position = new Vector2f(path[i].Position.X * tileSize + tileSize / 2, path[i].Position.Y * tileSize + tileSize / 2);
shape.FillColor = Color.Red;
window.Draw(shape);
}
window.Display();
}
}
private static List<Tile> AStar(Tile[,] tiles, Vector2i start, Vector2i end)
{
// initialize the start and end tiles
Tile startTile = tiles[start.X, start.Y];
startTile.GScore = 0;
startTile.FScore = startTile.GScore + Heuristic(startTile, tiles[end.X, end.Y]);
Tile endTile = tiles[end.X, end.Y];
endTile.GScore = float.MaxValue; // infinity
// initialize the list of open and closed tiles
List<Tile> openSet = new List<Tile> { startTile };
List<Tile> closedSet = new List<Tile>();
while (openSet.Count > 0)
{
// get the tile with the lowest f-score
Tile currentTile = GetLowestFScoreTile(openSet);
// if the current tile is the end tile, then we have found a path
if (currentTile == endTile)
{
return ReconstructPath(endTile);
}
// move the current tile from open to closed set
openSet.Remove(currentTile);
closedSet.Add(currentTile);
// process the neighbors of the current tile
foreach (Tile neighbor in GetNeighbors(currentTile, tiles))
{
// skip the neighbor if it has already been evaluated
if (closedSet.Contains(neighbor))
{
continue;
}
// calculate the tentative g-score
float tentativeGScore = currentTile.GScore + 1f;
// add the neighbor to the open set if it is a new tile
if (!openSet.Contains(neighbor))
{
openSet.Add(neighbor);
}
else if (tentativeGScore >= neighbor.GScore)
{
continue;
}
// update the neighbor's g-score and f-score
neighbor.Parent = currentTile;
neighbor.GScore = tentativeGScore;
neighbor.FScore = neighbor.GScore + Heuristic(neighbor, endTile);
}
}
// no path found
return null;
}
private static Tile GetLowestFScoreTile(List<Tile> tiles)
{
Tile lowest = tiles[0];
for (int i = 1; i < tiles.Count; ++i)
{
if (tiles[i].FScore < lowest.FScore)
{
lowest = tiles[i];
}
}
return lowest;
}
private static float Heuristic(Tile a, Tile b)
{
return MathF.Sqrt((a.Position.X - b.Position.X) * (a.Position.X - b.Position.X) + (a.Position.Y - b.Position.Y) * (a.Position.Y - b.Position.Y));
}
private static List<Tile> GetNeighbors(Tile tile, Tile[,] tiles)
{
List<Tile> neighbors = new List<Tile>();
int rowCount = tiles.GetLength(0);
int colCount = tiles.GetLength(1);
Vector2i[] offsets = new Vector2i[]
{
new Vector2i(-1, 0),
new Vector2i(1, 0),
new Vector2i(0, -1),
new Vector2i(0, 1)
};
foreach (Vector2i offset in offsets)
{
Vector2i position = tile.Position + offset;
if (position.X >= 0 && position.X < rowCount && position.Y >= 0 && position.Y < colCount)
{
neighbors.Add(tiles[position.X, position.Y]);
}
}
return neighbors;
}
private static List<Tile> ReconstructPath(Tile endTile)
{
List<Tile> path = new List<Tile>();
Tile currentTile = endTile;
while (currentTile != null)
{
path.Insert(0, currentTile);
currentTile = currentTile.Parent;
}
return path;
}
private static void Window_Closed(object sender, EventArgs e)
{
RenderWindow window = (RenderWindow)sender;
window.Close();
}
}
enum TileType
{
Floor,
Block
}
class Tile
{
public TileType Type { get; set; }
public Vector2i Position { get; set; }
public float GScore { get; set; } = float.MaxValue; // infinity
public float FScore { get; set; } = float.MaxValue; // infinity
public Tile Parent { get; set; }
public Tile(TileType type, Vector2i position)
{
Type = type;
Position = position;
}
}
}
7503 chars215 lines
Note that this is just a basic example of A* path finding using SFML in C#. You may need to modify the code to suit your specific requirements.
gistlibby LogSnag