Example #1
0
    /// <summary>
    /// ermittelt alle möglichen Zugvarianten und gibt deren Stellungen zurück
    /// </summary>
    /// <param name="blocker">Klasse mit bekannten Blockern</param>
    /// <returns>Enumerable der gefundenen Stellungen</returns>
    public IEnumerable<SokowahnStellung> GetVarianten(ISokowahnBlocker blocker)
    {
      int checkRaumVon = 0;
      int checkRaumBis = 0;

      Array.Clear(tmpRaumCheckFertig, 0, raumAnzahl);

      // erste Spielerposition hinzufügen
      tmpRaumCheckFertig[raumSpielerPos] = true;
      tmpCheckRaumPosis[checkRaumBis] = raumSpielerPos;
      tmpCheckRaumTiefe[checkRaumBis] = spielerZugTiefe;
      checkRaumBis++;

      // alle möglichen Spielerposition berechnen
      while (checkRaumVon < checkRaumBis)
      {
        raumSpielerPos = tmpCheckRaumPosis[checkRaumVon];
        int pTiefe = tmpCheckRaumTiefe[checkRaumVon] + 1;

        int p, p2;

        #region # // --- links ---
        if (!tmpRaumCheckFertig[p = raumLinks[raumSpielerPos]])
        {
          if (raumZuKisten[p] < kistenAnzahl) // steht eine Kiste auf den benachbarten Feld?
          {
            if (raumZuKisten[p2 = raumLinks[p]] == kistenAnzahl && p2 < raumAnzahl) // Feld hinter der Kiste frei?
            {
              kistenZuRaum[raumZuKisten[p2] = raumZuKisten[p]] = p2; raumZuKisten[p] = kistenAnzahl; // linke Kiste weiter nach links schieben
              raumSpielerPos = p;                                                                    // Spieler nach links bewegen

              if (blocker.CheckErlaubt(raumSpielerPos, raumZuKisten))
              {
                yield return new SokowahnStellung { raumSpielerPos = raumSpielerPos, kistenZuRaum = kistenZuRaum.TeilArray(kistenAnzahl), crc64 = Crc, zugTiefe = pTiefe };
              }

              raumSpielerPos = tmpCheckRaumPosis[checkRaumVon];                                      // Spieler zurück nach rechts bewegen
              kistenZuRaum[raumZuKisten[p] = raumZuKisten[p2]] = p; raumZuKisten[p2] = kistenAnzahl; // linke Kiste eins zurück nach rechts schieben
            }
          }
          else
          {
            tmpRaumCheckFertig[p] = true;
            tmpCheckRaumPosis[checkRaumBis] = p;
            tmpCheckRaumTiefe[checkRaumBis] = pTiefe;
            checkRaumBis++;
          }
        }
        #endregion

        #region # // --- rechts ---
        if (!tmpRaumCheckFertig[p = raumRechts[raumSpielerPos]])
        {
          if (raumZuKisten[p] < kistenAnzahl) // steht eine Kiste auf den benachbarten Feld?
          {
            if (raumZuKisten[p2 = raumRechts[p]] == kistenAnzahl && p2 < raumAnzahl) // Feld hinter der Kiste frei?
            {
              kistenZuRaum[raumZuKisten[p2] = raumZuKisten[p]] = p2; raumZuKisten[p] = kistenAnzahl; // rechte Kiste weiter nach rechts schieben
              raumSpielerPos = p;                                                                    // Spieler nach rechts bewegen

              if (blocker.CheckErlaubt(raumSpielerPos, raumZuKisten))
              {
                yield return new SokowahnStellung { raumSpielerPos = raumSpielerPos, kistenZuRaum = kistenZuRaum.TeilArray(kistenAnzahl), crc64 = Crc, zugTiefe = pTiefe };
              }

              raumSpielerPos = tmpCheckRaumPosis[checkRaumVon];                                      // Spieler zurück nach links bewegen
              kistenZuRaum[raumZuKisten[p] = raumZuKisten[p2]] = p; raumZuKisten[p2] = kistenAnzahl; // rechte Kiste eins zurück nach links schieben
            }
          }
          else
          {
            tmpRaumCheckFertig[p] = true;
            tmpCheckRaumPosis[checkRaumBis] = p;
            tmpCheckRaumTiefe[checkRaumBis] = pTiefe;
            checkRaumBis++;
          }
        }
        #endregion

        #region # // --- oben ---
        if (!tmpRaumCheckFertig[p = raumOben[raumSpielerPos]])
        {
          if (raumZuKisten[p] < kistenAnzahl) // steht eine Kiste auf den benachbarten Feld?
          {
            if (raumZuKisten[p2 = raumOben[p]] == kistenAnzahl && p2 < raumAnzahl) // Feld hinter der Kiste frei?
            {
              kistenZuRaum[raumZuKisten[p2] = raumZuKisten[p]] = p2; raumZuKisten[p] = kistenAnzahl; // obere Kiste weiter nach oben schieben
              raumSpielerPos = p;                                                                    // Spieler nach oben bewegen

              #region # // Kisten sortieren (sofern notwendig)
              while (raumZuKisten[p2] > 0 && kistenZuRaum[raumZuKisten[p2] - 1] > p2 && raumZuKisten[p2] < kistenAnzahl)
              {
                int tmp = kistenZuRaum[raumZuKisten[p2] - 1];
                kistenZuRaum[raumZuKisten[p2]--] = tmp;
                kistenZuRaum[raumZuKisten[tmp]++] = p2;
              }
              #endregion

              if (blocker.CheckErlaubt(raumSpielerPos, raumZuKisten))
              {
                yield return new SokowahnStellung { raumSpielerPos = raumSpielerPos, kistenZuRaum = kistenZuRaum.TeilArray(kistenAnzahl), crc64 = Crc, zugTiefe = pTiefe };
              }

              raumSpielerPos = tmpCheckRaumPosis[checkRaumVon];                                      // Spieler zurück nach unten bewegen
              kistenZuRaum[raumZuKisten[p] = raumZuKisten[p2]] = p; raumZuKisten[p2] = kistenAnzahl; // obere Kiste eins zurück nach unten schieben

              #region # // Kisten zurück sortieren (sofern notwendig)
              while (raumZuKisten[p] < kistenAnzahl - 1 && kistenZuRaum[raumZuKisten[p] + 1] < p)
              {
                int tmp = kistenZuRaum[raumZuKisten[p] + 1];
                kistenZuRaum[raumZuKisten[p]++] = tmp;
                kistenZuRaum[raumZuKisten[tmp]--] = p;
              }
              #endregion
            }
          }
          else
          {
            tmpRaumCheckFertig[p] = true;
            tmpCheckRaumPosis[checkRaumBis] = p;
            tmpCheckRaumTiefe[checkRaumBis] = pTiefe;
            checkRaumBis++;
          }
        }
        #endregion

        #region # // --- unten ---
        if (!tmpRaumCheckFertig[p = raumUnten[raumSpielerPos]])
        {
          if (raumZuKisten[p] < kistenAnzahl) // steht eine Kiste auf den benachbarten Feld?
          {
            if (raumZuKisten[p2 = raumUnten[p]] == kistenAnzahl && p2 < raumAnzahl) // Feld hinter der Kiste frei?
            {
              kistenZuRaum[raumZuKisten[p2] = raumZuKisten[p]] = p2; raumZuKisten[p] = kistenAnzahl; // untere Kiste weiter nach unten schieben
              raumSpielerPos = p;                                                                    // Spieler nach unten bewegen

              #region # // Kisten sortieren (sofern notwendig)
              while (raumZuKisten[p2] < kistenAnzahl - 1 && kistenZuRaum[raumZuKisten[p2] + 1] < p2)
              {
                int tmp = kistenZuRaum[raumZuKisten[p2] + 1];
                kistenZuRaum[raumZuKisten[p2]++] = tmp;
                kistenZuRaum[raumZuKisten[tmp]--] = p2;
              }
              #endregion

              if (blocker.CheckErlaubt(raumSpielerPos, raumZuKisten))
              {
                yield return new SokowahnStellung { raumSpielerPos = raumSpielerPos, kistenZuRaum = kistenZuRaum.TeilArray(kistenAnzahl), crc64 = Crc, zugTiefe = pTiefe };
              }

              raumSpielerPos = tmpCheckRaumPosis[checkRaumVon];                                      // Spieler zurück nach oben bewegen
              kistenZuRaum[raumZuKisten[p] = raumZuKisten[p2]] = p; raumZuKisten[p2] = kistenAnzahl; // untere Kiste eins zurück nach oben schieben

              #region # // Kisten zurück sortieren (sofern notwendig)
              while (raumZuKisten[p] > 0 && kistenZuRaum[raumZuKisten[p] - 1] > p && raumZuKisten[p] < kistenAnzahl)
              {
                int tmp = kistenZuRaum[raumZuKisten[p] - 1];
                kistenZuRaum[raumZuKisten[p]--] = tmp;
                kistenZuRaum[raumZuKisten[tmp]++] = p;
              }
              #endregion
            }
          }
          else
          {
            tmpRaumCheckFertig[p] = true;
            tmpCheckRaumPosis[checkRaumBis] = p;
            tmpCheckRaumTiefe[checkRaumBis] = pTiefe;
            checkRaumBis++;
          }
        }
        #endregion

        checkRaumVon++;
      }

      raumSpielerPos = tmpCheckRaumPosis[0]; // alte Spielerposition wieder herstellen
    }
Example #2
0
    /// <summary>
    /// Konstruktor
    /// </summary>
    /// <param name="raum">Basisdaten anhand eines vorhanden Raumes nutzen</param>
    /// <param name="blocker">bekannte Blocker</param>
    /// <param name="startHash">bekannte Einträge in der Start-Hashtable</param>
    /// <param name="zielHash">bekannte Einträge in der Ziel-Hashtable</param>
    public SokowahnRaum(SokowahnRaum raum, ISokowahnBlocker blocker, ISokowahnHash startHash, ISokowahnHash zielHash)
    {
      this.feldData = raum.feldData;
      this.feldBreite = raum.feldBreite;
      this.raumAnzahl = raum.raumAnzahl;
      this.raumLinks = raum.raumLinks;
      this.raumRechts = raum.raumRechts;
      this.raumOben = raum.raumOben;
      this.raumUnten = raum.raumUnten;

      this.raumSpielerPos = raum.raumSpielerPos;
      this.spielerZugTiefe = raum.spielerZugTiefe;
      this.raumZuKisten = raum.raumZuKisten.ToArray(); // Kopie erstellen
      this.kistenAnzahl = raum.kistenAnzahl;
      this.kistenZuRaum = raum.kistenZuRaum.ToArray(); // Kopie erstellen

      this.tmpCheckRaumPosis = new int[raumAnzahl];
      this.tmpCheckRaumTiefe = new int[raumAnzahl];
      this.tmpRaumCheckFertig = new bool[raumAnzahl + 1];
      this.tmpRaumCheckFertig[raumAnzahl] = true; // Ende-Feld schon auf fertig setzen

      this.merkBlocker = blocker;
      this.merkStartHash = startHash;
      this.merkZielHash = zielHash;
    }