Gå til innhold

Anbefalte innlegg

Har en skoleoppgave gående, hvor jeg skal implementere A* i C#. Har brukt denne artikkelen som utgangspunkt for koden:A*. Er litt usikker på om jeg har gjort dette riktig, og vil gjerne at noen ser over den før jeg leverer den.

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Text;

namespace AStar2
{
class AMethod
{
 /// <summary>
 /// Returns the shortest path between two squares in a given grid, if a valid one exists. Otherwise returns null.
 /// </summary>
 /// <param name="startPos">The starting position from which to search</param>
 /// <param name="endPos">The goal of the search</param>
 /// <param name="grid">The network which contains startPos and endPos</param>
 /// <param name="unwalkables">Rectangle array containing the squares which cannot be used in the path</param>
 /// <param name="rootOfA">Value representing the height/width of each square</param>
 /// <param name="gridFactorX">The number of squares in the grid on the X-axis</param>
 /// <param name="gridFactorY">The number of squares in the grid on the Y-axis</param>
 /// <param name="straightCost">One of two values indicating how to prioritze between straight and diagonal movement</param>
 /// <param name="diagonalCost">One of two values indicating how to prioritze between straight and diagonal movement</param>
 /// <param name="SpecialCostRects">Rectangle array containing all squares that should have a diffrent priority from the norm</param>
 /// <param name="specialCost">Int array indicating how to prioritze the special squares</param>

	public static List<Rectangle> ShortestPath (Rectangle startPos, Rectangle endPos, List<Rectangle> grid, List<Rectangle> unwalkables,int rootOfA, int gridFactorX,int gridFactorY,int straightCost,int diagonalCost,List<Rectangle>SpecialCostRects,int[] specialCost)
	{
		// Declarations
		bool onClosedList = false;

		int[] gScore = new int[1000];
		int[] hScore = new int[1000];
		int[] fScore = new int[1000];
		int currCost = 0;

		Rectangle currSquare = startPos;
		Rectangle adjSquare = new Rectangle();

		List<Rectangle> openList = new List<Rectangle>();
		List<Rectangle> closedList = new List<Rectangle>();
		List<Rectangle> parents = new List<Rectangle>();

		List<Rectangle> pathSquares = new List<Rectangle>();

		// iinitialisèr openList, f,g,og hScore, med startPos sine verdier
		openList.Add(startPos);
		fScore[grid.IndexOf(startPos)] = 0;
		gScore[grid.IndexOf(startPos)] = 0;
		hScore[grid.IndexOf(startPos)] = 0;

		while (openList.Count != 0 && !onClosedList)// While løkke som vil fortsette til den finner en sti, eller til det ikke finnes flere alternativ
		{
			foreach (Rectangle square in openList)
			{
				if (fScore[grid.IndexOf(square)] < fScore[grid.IndexOf(currSquare)])
					currSquare = square;
			}

			// Legg currSquare over i closedList
			openList.Remove(currSquare);
			closedList.Add(currSquare);

			for (int i = 0; i < 8; i++)// For løkke som ser etter alternativ, og legger dem i openList
			{
				switch (i)
				{
					case 0:
						adjSquare = grid[grid.IndexOf(currSquare) - 1];					//N
						currCost = straightCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
					case 1:
						adjSquare = grid[grid.IndexOf(currSquare) + 1];					//S
						currCost = straightCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
					case 2:
						adjSquare = grid[grid.IndexOf(currSquare) + gridFactorY];		  //E
						currCost = straightCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
					case 3:
						adjSquare = grid[grid.IndexOf(currSquare) - gridFactorY];		  //W
						currCost = straightCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
					case 4:
						adjSquare = grid[grid.IndexOf(currSquare) + gridFactorY + 1];	 //SE
						currCost = diagonalCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
					case 5:
						adjSquare = grid[grid.IndexOf(currSquare) - gridFactorY + 1];	 //SW
						currCost = diagonalCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
					case 6:
						adjSquare = grid[grid.IndexOf(currSquare) + gridFactorY - 1];	 //NE
						currCost = diagonalCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
					case 7:
						adjSquare = grid[grid.IndexOf(currSquare) - gridFactorY - 1];	 //NW
						currCost = diagonalCost;
						if (SpecialCostRects.Contains(adjSquare))
							currCost += specialCost[SpecialCostRects.IndexOf(adjSquare)];
						break;
				}

				if (!unwalkables.Contains(adjSquare) && !closedList.Contains(adjSquare))
				{

					if (!openList.Contains(adjSquare))
					{
						openList.Add(adjSquare);
						parents[grid.IndexOf(adjSquare)] = currSquare;

						// Calculate f g og h value
						if (adjSquare.X > endPos.X)// h value calculation start 
						{
							if (adjSquare.Y > endPos.Y)
								hScore[grid.IndexOf(adjSquare)] = ((adjSquare.Y - endPos.Y) /rootOfA) + ((adjSquare.X - endPos.X) / rootOfA);
							else
								hScore[grid.IndexOf(adjSquare)] = ((endPos.Y - currSquare.Y) / rootOfA) + ((adjSquare.X - endPos.X) / rootOfA);
						}
						else
						{
							if (currSquare.Y > endPos.Y)
								hScore[grid.IndexOf(adjSquare)] = ((currSquare.Y - endPos.Y) / rootOfA) + ((-endPos.X - currSquare.X) / rootOfA);
							else
								hScore[grid.IndexOf(adjSquare)] = ((endPos.Y - currSquare.Y) / rootOfA) + ((endPos.X - currSquare.X) / rootOfA);
						}// h value calculation end

						gScore[grid.IndexOf(adjSquare)] = gScore[grid.IndexOf(currSquare)] + currCost;// g value calculation
						fScore[grid.IndexOf(adjSquare)] = gScore[grid.IndexOf(adjSquare)] + hScore[grid.IndexOf(adjSquare)];//f value calculation
					}
					else// Hvis kvadratet allerede finnes i openList
					{
						if (gScore[grid.IndexOf(adjSquare)] < gScore[grid.IndexOf(currSquare)])// Hvis kvadratet er et bedre alternativ enn currSquare
						{//[b]Er spesiellt usikker på dette, virker rett i forhold til beskrivelsen i artikkelen, men ikke ifølge mitt hode.[/b]
							parents[grid.IndexOf(adjSquare)] = currSquare;
							gScore[grid.IndexOf(adjSquare)] = gScore[grid.IndexOf(parents[grid.IndexOf(currSquare)])]+currCost;
							fScore[grid.IndexOf(currSquare)] = gScore[grid.IndexOf(currSquare)] + hScore[grid.IndexOf(currSquare)];
						}
					}
				}
			}
			if (closedList.Contains(endPos))
				onClosedList = true;
		}
		if (onClosedList)// Fant et alternativ
		{
		  currSquare = endPos;
		  while(!pathSquares.Contains(startPos))// while løkke som reverserer stien og legger den i pathSquares
		  {
			pathSquares.Add(grid.IndexOf(currSquare)); 
			currSquare = parents[grid.IndexOf(currSquare)];
		  }  return pathSquares;
		}
		else
			return null;// Ingen sti funnet, funksjonen returnerer null.
	}
}
}

Koden er ment å gi samme resultat som den forfatteren til artikkelen bruker, hvis den ikke gjør dette, vil jeg gjerne vite hva som er galt.Btw, prøvde å utheve en kommentar som jeg synes var vesentlig, men dette gikk ikke. Går det ann å bruke fet skrift i kodebokser? Takk på forhånd =).

Endret av Velena
Lenke til kommentar
Videoannonse
Annonse

Ville bare vite om jeg hadde gjort det riktig. Driver og tester det selv nå, og har støtt på et aldri så lite problem:

List<Rectangle> someArray = new List<Rectangle>();
Rectangle someRect = new Rectangle(80,80,20,20);
someArray[10] = someRect;

Koden over ser ikke ut til å fungere, må jeg legge til en verdi for alle indexene opp til 10 for at jeg skal kunne legge en verdi i den indexen?

Edit: Har prøvd å omgå problemet ved å legge null verdier i alle indexene før jeg setter de riktige verdiene:

// count er antall kvadrater lagret i grid
public static void assign(int[] someInt, int count)
	{
		for (int i = 0; i < count; i++)
		{
			someInt[i] = 0;
		}
	}
// Har en slik for List<Rectangle> også

Men koden gir fremdeles et indexOutOfRange unntak, denne gang ved int arrayen.

Endret av Velena
Lenke til kommentar

Javel? Så det som en god nok måte å løse problemet >.>. Mener dere at jeg kunne gjort det enklere?

Edit: Fant noen slurvefeil i koden. Har rettet dem, så nå kjører den ihvertfall.Problemet nå er at det virker som koden er veldig ressurs krevende.

Edit 2: Var vist ikke det at den var ressurs-krevende, men at currSquare ikke oppdateres riktig, noe som resulterer i en evig loop.

Endret av Velena
Lenke til kommentar

Gjerne det manfred:

       public static List<Rectangle> ShortestPath (Rectangle startPos, Rectangle endPos,
List<Rectangle> grid, List<Rectangle> unwalkables,int rootOfA, int gridFactorX,int 
gridFactorY,int straightCost,int diagonalCost,List<Rectangle>SpecialCostRects,
int[] specialCost)
       {

           bool onClosedList = false;

           int[] gScore = new int[1600];
           int[] hScore = new int[1600];
           int[] fScore = new int[1600];
           int currCost = 0;

           Rectangle currSquare = startPos;
           Rectangle adjSquare = new Rectangle();

           List<Rectangle> openList = new List<Rectangle>();
           List<Rectangle> closedList = new List<Rectangle>();
           List<Rectangle> parents = new List<Rectangle>();

           List<Rectangle> pathSquares = new List<Rectangle>();


           openList.Add(startPos);



           assign(parents, grid.Count);
           assign(gScore, grid.Count);
           assign(hScore, grid.Count);
           assign(fScore, grid.Count);

           fScore[grid.IndexOf(startPos)] = 0;
           gScore[grid.IndexOf(startPos)] = 0;
           hScore[grid.IndexOf(startPos)] = 0;


           while (openList.Count != 0 && !onClosedList)
           {
               foreach (Rectangle square in openList)
               {
                   if (fScore[grid.IndexOf(square)] <= fScore[grid.IndexOf(currSquare)])
                       currSquare = square;

               }


               // Switch currSquare from openList to closedList
               openList.Remove(currSquare);
               closedList.Add(currSquare);

               for (int i = 0; i < 8; i++)
               {
                   switch (i)
                   {
                       case 0:
                           adjSquare = grid[grid.IndexOf(currSquare) - 1];                    
                           currCost = straightCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                       case 1:
                           adjSquare = grid[grid.IndexOf(currSquare) + 1];                    
                           currCost = straightCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                       case 2:
                           adjSquare = grid[grid.IndexOf(currSquare) + gridFactorY];          
                           currCost = straightCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                       case 3:
                           adjSquare = grid[grid.IndexOf(currSquare) - gridFactorY];          
                           currCost = straightCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                       case 4:
                           adjSquare = grid[grid.IndexOf(currSquare) + gridFactorY + 1];     
                           currCost = diagonalCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                       case 5:
                           adjSquare = grid[grid.IndexOf(currSquare) - gridFactorY + 1];     
                           currCost = diagonalCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                       case 6:
                           adjSquare = grid[grid.IndexOf(currSquare) + gridFactorY - 1];     
                           currCost = diagonalCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                       case 7:
                           adjSquare = grid[grid.IndexOf(currSquare) - gridFactorY - 1];     
                           currCost = diagonalCost;
                           if (SpecialCostRects.Contains(adjSquare))
                               currCost += specialCost[specialCostRects.IndexOf(adjSquare)];
                           break;
                   }

                   if (!unwalkables.Contains(adjSquare) && !closedList.Contains(adjSquare))
                   {
                       if (!openList.Contains(adjSquare))
                       {

                           openList.Add(adjSquare);
                           parents[grid.IndexOf(adjSquare)] = currSquare;


                           if (adjSquare.X > endPos.X)
                           {
                               if (adjSquare.Y > endPos.Y)
                                   hScore[grid.IndexOf(adjSquare)] = (((adjSquare.Y - endPos.Y) /rootOfA) + ((adjSquare.X - endPos.X) / rootOfA))*straightCost;
                               else
                                   hScore[grid.IndexOf(adjSquare)] = (((endPos.Y - adjSquare.Y) / rootOfA) + ((adjSquare.X - endPos.X) / rootOfA))*straightCost;
                           }
                           else
                           {
                               if (adjSquare.Y > endPos.Y)
                                   hScore[grid.IndexOf(adjSquare)] = (((adjSquare.Y - endPos.Y) / rootOfA) + ((endPos.X - adjSquare.X) / rootOfA))*straightCost;
                               else
                                   hScore[grid.IndexOf(adjSquare)] = (((endPos.Y - adjSquare.Y) / rootOfA) + ((endPos.X - adjSquare.X) / rootOfA))*straightCost;
                           }

                           gScore[grid.IndexOf(adjSquare)] = gScore[grid.IndexOf(currSquare)] + currCost;
                           fScore[grid.IndexOf(adjSquare)] = gScore[grid.IndexOf(adjSquare)] + hScore[grid.IndexOf(adjSquare)];


                       }
                       else
                       {
                           if (gScore[grid.IndexOf(adjSquare)] < gScore[grid.IndexOf(currSquare)])
                           {
                               parents[grid.IndexOf(adjSquare)] = parents[grid.IndexOf(currSquare)];
                               gScore[grid.IndexOf(adjSquare)] = gScore[grid.IndexOf(parents[grid.IndexOf(adjSquare)])]+currCost;
                               fScore[grid.IndexOf(adjSquare)] = gScore[grid.IndexOf(adjSquare)] + hScore[grid.IndexOf(adjSquare)];
                           }
                       }

                   }
                   if (i == 7)
                   {
                       if (openList.Count != 0)
                           currSquare = openList[0];
                   }
               }
               if (closedList.Contains(endPos))
                   onClosedList = true;
           }
           if (onClosedList)
           {
             currSquare = endPos;
             while(!pathSquares.Contains(startPos))
             {
               pathSquares.Add(grid[grid.IndexOf(currSquare)]); 
               currSquare = parents[grid.IndexOf(currSquare)];
             }  return pathSquares;
           }
           else
               return null;
       }
       public static void assign(List<Rectangle> rect, int count)
       {
           for (int i = 0; i < count; i++)
           {
               rect.Add(new Rectangle(0, 0, 0, 0));
           }
       }
       public static void assign(int[] someInt, int count)
       {
           for (int i = 0; i < count; i++)
           {
               someInt[i] = 0;
           }
       }

=D. Forslag til forbedring er selvsagt fortsatt velkomne.

Edit: Hvorfor ble kodeboksene så enormt brede? Prøvde å justere dem ved å dele noen av linjene i to, men det ser ikke ut til å ha hjulpet =/.

Endret av Velena
Lenke til kommentar

I stedet for

 

for(int i = 0; i < 3; i++)
{
 switch(i)
 {
case 0:
	func1();
	break;
case 1:
	func2();
	break;
case 2:
	func3();
	break;
 }
}

 

Så kan du liksom gjøre

 

func1();
func2();
func3();

 

Der vil jeg liksom si at det første eksempelet virkelig er waste.

 

Edit: typo

Endret av Manfred
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...