/// <summary> /// Konstruktor /// </summary> /// <param name="spielFeld">Spielfeld als Textzeilen</param> public SokoWahn_5th(string spielFeld) { SokowahnStaticTools.SpielfeldEinlesen(spielFeld, out feldBreite, out feldHöhe, out feldSpielerStartPos, out feldData, out feldDataLeer); raumBasis = new SokowahnRaum(feldData, feldBreite); Directory.CreateDirectory(TempOrdner); // --- Vorwärtssuche initialisieren --- bekannteStellungen = new SokowahnHash_Index24Multi(); bekannteStellungen.Add(raumBasis.Crc, 0); vorwärtsTiefe = 0; vorwärtsTiefeAktuell = 0; vorwärtsSucher = new SokowahnLinearList2[0]; vorwärtsSucherPunkte = new Dictionary<int, int>[0]; VorwärtsAdd(raumBasis.GetStellung(), new SokowahnPunkte()); // --- Zielstellungen und Rückwärtssuche initialisieren --- zielStellungen = new SokowahnHash_Index24Multi(); rückwärtsTiefe = 0; rückwärtsSucher = new SokowahnLinearList2[0]; foreach (SokowahnStellung stellung in SokowahnStaticTools.SucheZielStellungen(raumBasis)) { zielStellungen.Add(stellung.crc64, 60000); RückwärtsAdd(stellung); } ulong spielFeldCrc = Crc64.Start.Crc64Update(raumBasis.FeldBreite, raumBasis.FeldHöhe, raumBasis.FeldData); blocker = new SokowahnBlockerB2(Environment.CurrentDirectory + "\\temp\\blocker2_x" + spielFeldCrc.ToString("x").PadLeft(16, '0') + ".gz", raumBasis); }
/// <summary> /// Rekursive Suchmethode einer einzelnen Kiste /// </summary> /// <param name="raum">Raum mit der einzelnen Kiste und Spielerstellung</param> /// <returns>Mindestzahl der Schritte zum Ziel (oder 60000 = wenn kein Ziel möglich)</returns> int RechneMindestZüge(SokowahnRaum raum) { List<List<SokowahnStellung>> list = new List<List<SokowahnStellung>>(); list.Add(new List<SokowahnStellung>(raum.GetStellung().SelfEnumerable())); int listTiefe = 0; SokowahnHash_Index0 hash = new SokowahnHash_Index0(); while (listTiefe < list.Count) { foreach (var stellung in list[listTiefe]) { raum.LadeStellung(stellung); if (raumZiele[stellung.kistenZuRaum[0]]) return listTiefe; foreach (var variante in raum.GetVarianten()) { int find = hash.Get(variante.crc64); if (find < 65535) { if (find <= variante.zugTiefe) continue; hash.Update(variante.crc64, variante.zugTiefe); } else { hash.Add(variante.crc64, variante.zugTiefe); } while (list.Count <= variante.zugTiefe) { list.Add(new List<SokowahnStellung>()); } list[variante.zugTiefe].Add(variante); } } listTiefe++; } return 60000; }
/// <summary> /// ermittelt alle möglichen Zielstellungen /// </summary> /// <param name="raumBasis">Raumsystem mit Basis-Stellung</param> /// <returns>Enumerable aller möglichen Zielstellungen</returns> public static IEnumerable<SokowahnStellung> SucheZielStellungen(SokowahnRaum raumBasis) { int feldBreite = raumBasis.FeldBreite; int feldHöhe = raumBasis.FeldHöhe; char[] feldData = raumBasis.FeldDataLeer.Select(c => c == '.' ? '*' : c).ToArray(); for (int spielerY = 1; spielerY < feldHöhe - 1; spielerY++) { for (int spielerX = 1; spielerX < feldBreite - 1; spielerX++) { int pos = spielerX + spielerY * feldBreite; if (feldData[pos] == ' ' && (feldData[pos - 1] == '*' || feldData[pos + 1] == '*' || feldData[pos - feldBreite] == '*' || feldData[pos + feldBreite] == '*')) { feldData[pos] = '@'; SokowahnRaum tmpRaum = new SokowahnRaum(feldData, feldBreite); tmpRaum.SpielerZugTiefe = 60000; var findStellungen = tmpRaum.GetVariantenRückwärts().ToArray(); if (findStellungen.Length > 0) { yield return tmpRaum.GetStellung(); // foreach (var findStellung in findStellungen) yield return findStellung; } feldData[pos] = ' '; } } } yield break; }