Beispiel #1
0
 /// <summary>
 /// bewegt den Spieler um eins nach unten
 /// </summary>
 /// <param name="zielHash">Ziel, in dem das neue Spielfeld erstellt wird</param>
 /// <returns>true, wenn auch eine Box verschoben wurde</returns>
 public bool BewegeUnten(HashFeld zielHash)
 {
  int ziel = zielHash.hashPos;
  int spieler = this.SpielerPos;
  for (int i = 0; i < hashSatzGro; i++) hashData[ziel + i] = hashData[hashPos + i];
  hashData[ziel + spieler] ^= 8; // Spielerfigur entfernen
  spieler += feldBreite;
  zielHash.SpielerPos = spieler;
  hashData[ziel + spieler] ^= 8; // Spielerfigur setzen
  if ((hashData[ziel + spieler] & 2) > 0) // Box vorhanden?
  {
   hashData[ziel + spieler] ^= 2; // Box entfernen
   hashData[ziel + spieler + feldBreite] ^= 2; // Box neu setzen
   switch ((hashData[ziel + spieler] & 0x4) | ((hashData[ziel + spieler + feldBreite] << 4) & 0x40))
   {
    case 0x00: break;
    case 0x04: zielHash.RestWürfel++; break;
    case 0x40: zielHash.RestWürfel--; break;
    case 0x44: break;
   }
   return true;
  }
  return false;
 }
Beispiel #2
0
  /// <summary>
  /// System, welche die FehlerMapErstellen erstellt
  /// </summary>
  /// <param name="würfel">Anzahl der zu testenden Würfel (muss immer weniger sein als die Ziel-Anzahl)</param>
  void FehlerMapErstellen(int würfel)
  {
   int[] kannFelder = Enumerable.Range(0, feldAnzahl).Where(pos => erlaubteBoxFelder[pos]).ToArray();
   var ofss = new[] { -1, +1, -feldBreite, +feldBreite };

   switch (würfel)
   {
    #region # case 1: // --- einzelne unerlaubte Boxen ermitteln ---
    case 1:
    {
     Dictionary<int, bool> spielerFertig = kannFelder.ToDictionary(p => p, p => false);

     foreach (int boxPos in kannFelder)
     {
      List<int> spielerGut = new List<int>();
      List<int> spielerSchlecht = new List<int>();

      foreach (int p in kannFelder) spielerFertig[p] = false;

      MapReset(true);
      feldData[boxPos] ^= 2;
      spielerFertig[boxPos] = true;

      foreach (int spielerPos in kannFelder.Where(pos => !spielerFertig[pos]))
      {
       #region # // --- Spieler setzen und Hash resetten ---
       feldData[spielerPos] ^= 8;
       HashFeld hashFeld = new HashFeld(0, feldData, true);
       hashIndex.Clear();
       hashGro = hashSatzGro;
       feldData[spielerPos] ^= 8;
       #endregion

       #region # // --- prüfen, ob Stellung gelöst werden kann ---
       bool find = false;

       for (int hashPos = 0; hashPos < hashGro; hashPos += hashSatzGro)
       {
        hashFeld = new HashFeld(hashPos);

        if (hashFeld.RestWürfel == 0) // machbare Lösung gefunden?
        {
         find = true;
         break;
        }

        if (hashGro > hashInfoMax * hashSatzGro)
        {
         hashInfoMax *= 2;
         Array.Resize(ref hashInfo, hashInfoMax + 65536);
        }

        if (hashFeld.KannLinks)
        {
         HashFeld neuHash = new HashFeld(hashGro);
         hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeLinks(neuHash));
         if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
        }

        if (hashFeld.KannRechts)
        {
         HashFeld neuHash = new HashFeld(hashGro);
         hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeRechts(neuHash));
         if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
        }

        if (hashFeld.KannOben)
        {
         HashFeld neuHash = new HashFeld(hashGro);
         hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeOben(neuHash));
         if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
        }

        if (hashFeld.KannUnten)
        {
         HashFeld neuHash = new HashFeld(hashGro);
         hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeUnten(neuHash));
         if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
        }
       }
       #endregion

       #region # // --- alle zusätzlich erreichbare Spielerpositionen ermitteln ---
       List<int> alleSpielerPos = new List<int>();
       alleSpielerPos.Add(spielerPos); spielerFertig[spielerPos] = true;
       for (int i = 0; i < alleSpielerPos.Count; i++)
       {
        int checkPos = alleSpielerPos[i];
        foreach (int ofs in ofss)
        {
         if ((feldData[checkPos + ofs] & 3) == 0 && !alleSpielerPos.Any(p => p == checkPos + ofs))
         {
          alleSpielerPos.Add(checkPos + ofs);
          if (erlaubteBoxFelder[checkPos + ofs]) spielerFertig[checkPos + ofs] = true;
         }
        }
       }
       #endregion

       if (find)
       {
        spielerGut.AddRange(alleSpielerPos);
       }
       else
       {
        spielerSchlecht.AddRange(alleSpielerPos);
        hashGro = 0;
        hashIndex.Clear();
       }

      }

      if (spielerGut.Count == 0) erlaubteBoxFelder[boxPos] = false;
     }

     FehlerDataInit();
    } break;
    #endregion

    #region # case 2: // --- unerlaubte Zweier-Kombinationen der Boxen ermitteln ---
    case 2:
    {
     Dictionary<int, bool> spielerFertig = kannFelder.ToDictionary(p => p, p => false);

     MapReset(true);

     for (int p1 = 0; p1 < kannFelder.Length; p1++)
     {
      int boxPos1 = kannFelder[p1];
      feldData[boxPos1] ^= 2;

      feldZeichner.Zeichne(pictureBox1, feldData); Application.DoEvents();

      for (int p2 = p1 + 1; p2 < kannFelder.Length; p2++)
      {
       int boxPos2 = kannFelder[p2];
       feldData[boxPos2] ^= 2;

       List<int> spielerGut = new List<int>();
       List<int> spielerSchlecht = new List<int>();

       foreach (int p in kannFelder) spielerFertig[p] = false;

       spielerFertig[boxPos1] = true;
       spielerFertig[boxPos2] = true;

       foreach (int spielerPos in kannFelder.Where(pos => !spielerFertig[pos]))
       {
        #region # // --- Spieler setzen und Hash resetten ---
        feldData[spielerPos] ^= 8;
        HashFeld hashFeld = new HashFeld(0, feldData, true);
        hashIndex.Clear();
        hashGro = hashSatzGro;
        feldData[spielerPos] ^= 8;
        #endregion

        #region # // --- prüfen, ob Stellung gelöst werden kann ---
        bool find = false;

        for (int hashPos = 0; hashPos < hashGro; hashPos += hashSatzGro)
        {
         hashFeld = new HashFeld(hashPos);

         if (hashFeld.RestWürfel == 0) // machbare Lösung gefunden?
         {
          find = true;
          break;
         }

         if (hashGro > hashInfoMax * hashSatzGro)
         {
          hashInfoMax *= 2;
          Array.Resize(ref hashInfo, hashInfoMax + 65536);
         }

         if (hashFeld.KannLinks)
         {
          HashFeld neuHash = new HashFeld(hashGro);
          hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeLinks(neuHash));
          if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
         }

         if (hashFeld.KannRechts)
         {
          HashFeld neuHash = new HashFeld(hashGro);
          hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeRechts(neuHash));
          if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
         }

         if (hashFeld.KannOben)
         {
          HashFeld neuHash = new HashFeld(hashGro);
          hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeOben(neuHash));
          if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
         }

         if (hashFeld.KannUnten)
         {
          HashFeld neuHash = new HashFeld(hashGro);
          hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeUnten(neuHash));
          if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
         }
        }
        #endregion

        #region # // --- alle zusätzlich erreichbare Spielerpositionen ermitteln ---
        List<int> alleSpielerPos = new List<int>();
        alleSpielerPos.Add(spielerPos); spielerFertig[spielerPos] = true;
        for (int i = 0; i < alleSpielerPos.Count; i++)
        {
         int checkPos = alleSpielerPos[i];
         foreach (int ofs in ofss)
         {
          if ((feldData[checkPos + ofs] & 3) == 0 && !alleSpielerPos.Any(p => p == checkPos + ofs))
          {
           alleSpielerPos.Add(checkPos + ofs);
           if (erlaubteBoxFelder[checkPos + ofs]) spielerFertig[checkPos + ofs] = true;
          }
         }
        }
        #endregion

        if (find)
        {
         spielerGut.AddRange(alleSpielerPos);
        }
        else
        {
         spielerSchlecht.AddRange(alleSpielerPos);
        }
       }

       if (spielerGut.Count == 0 || spielerSchlecht.Count > 0)
       {
        #region # // --- Box 1 -> Box 2 ---
        List<short> dazu = new List<short>();

        dazu.Add((short)boxPos2);
        if (spielerGut.Count < spielerSchlecht.Count) // nur die guten Felder merken?
        {
         dazu.Add((short)spielerGut.Count);
         dazu.AddRange(spielerGut.Select(pos => (short)pos));
        }
        else // nur die schlechten Felder merken (da weniger)
        {
         dazu.Add((short)-spielerSchlecht.Count);
         dazu.AddRange(spielerSchlecht.Select(pos => (short)pos));
        }

        FehlerDataUpdate(ref fehlerBox2[boxPos1], dazu);
        fehlerVorhanden[boxPos1] |= 1;
        #endregion

        #region # // --- Box 2 -> Box 1 ---
        dazu.Clear();

        dazu.Add((short)boxPos1);
        if (spielerGut.Count < spielerSchlecht.Count) // nur die guten Felder merken?
        {
         dazu.Add((short)spielerGut.Count);
         dazu.AddRange(spielerGut.Select(pos => (short)pos));
        }
        else // nur die schlechten Felder merken (da weniger)
        {
         dazu.Add((short)-spielerSchlecht.Count);
         dazu.AddRange(spielerSchlecht.Select(pos => (short)pos));
        }

        FehlerDataUpdate(ref fehlerBox2[boxPos2], dazu);
        fehlerVorhanden[boxPos2] |= 1;
        #endregion
       }

       feldData[boxPos2] ^= 2;
      }
      feldData[boxPos1] ^= 2;
     }
    } break;
    #endregion

    #region # case 3: // --- unerlaubte Dreier-Kombinationen der Boxen ermitteln ---
    case 3:
    {
     Dictionary<int, bool> spielerFertig = kannFelder.ToDictionary(p => p, p => false);

     MapReset(true);

     for (int p1 = 0; p1 < kannFelder.Length; p1++)
     {
      int boxPos1 = kannFelder[p1];
      int boxPos1x = boxPos1 % feldBreite;
      int boxPos1y = boxPos1 / feldBreite;
      feldData[boxPos1] ^= 2;

      for (int p2 = p1 + 1; p2 < kannFelder.Length; p2++)
      {
       int boxPos2 = kannFelder[p2];
       if (FehlerCheckDirekt(boxPos2)) continue;
       int boxPos2x = boxPos2 % feldBreite;
       int boxPos2y = boxPos2 / feldBreite;
       if (Math.Abs(boxPos2x - boxPos1x) > 2) continue;
       if (Math.Abs(boxPos2y - boxPos1y) > 2) continue;

       feldData[boxPos2] ^= 2;

       feldZeichner.Zeichne(pictureBox1, feldData); Application.DoEvents();

       for (int p3 = p2 + 1; p3 < kannFelder.Length; p3++)
       {
        int boxPos3 = kannFelder[p3];
        if (FehlerCheckDirekt(boxPos3)) continue;
        int boxPos3x = boxPos3 % feldBreite;
        int boxPos3y = boxPos3 / feldBreite;
        if (Math.Abs(boxPos3x - boxPos2x) > 2 && Math.Abs(boxPos3x - boxPos1x) > 2) continue;
        if (Math.Abs(boxPos3y - boxPos2y) > 2 && Math.Abs(boxPos3y - boxPos1y) > 2) continue;

        feldData[boxPos3] ^= 2;

        List<int> spielerGut = new List<int>();
        List<int> spielerSchlecht = new List<int>();

        foreach (int p in kannFelder) spielerFertig[p] = false;

        spielerFertig[boxPos1] = true;
        spielerFertig[boxPos2] = true;
        spielerFertig[boxPos3] = true;

        foreach (int spielerPos in kannFelder.Where(pos => !spielerFertig[pos]))
        {
         #region # // --- Spieler setzen und Hash resetten ---
         feldData[spielerPos] ^= 8;
         HashFeld hashFeld = new HashFeld(0, feldData, true);
         hashIndex.Clear();
         hashGro = hashSatzGro;
         feldData[spielerPos] ^= 8;
         #endregion

         #region # // --- prüfen, ob Stellung gelöst werden kann ---
         bool find = false;

         for (int hashPos = 0; hashPos < hashGro; hashPos += hashSatzGro)
         {
          hashFeld = new HashFeld(hashPos);

          if (hashFeld.RestWürfel == 0) // machbare Lösung gefunden?
          {
           find = true;
           break;
          }

          if (hashGro > hashInfoMax * hashSatzGro)
          {
           hashInfoMax *= 2;
           Array.Resize(ref hashInfo, hashInfoMax + 65536);
          }

          if (hashFeld.KannLinks)
          {
           HashFeld neuHash = new HashFeld(hashGro);
           hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeLinks(neuHash));
           if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
          }

          if (hashFeld.KannRechts)
          {
           HashFeld neuHash = new HashFeld(hashGro);
           hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeRechts(neuHash));
           if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
          }

          if (hashFeld.KannOben)
          {
           HashFeld neuHash = new HashFeld(hashGro);
           hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeOben(neuHash));
           if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
          }

          if (hashFeld.KannUnten)
          {
           HashFeld neuHash = new HashFeld(hashGro);
           hashInfo[hashGro / hashSatzGro] = new HashInfo(hashPos, hashFeld.BewegeUnten(neuHash));
           if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
          }
         }
         #endregion

         #region # // --- alle zusätzlich erreichbare Spielerpositionen ermitteln ---
         List<int> alleSpielerPos = new List<int>();
         alleSpielerPos.Add(spielerPos); spielerFertig[spielerPos] = true;
         for (int i = 0; i < alleSpielerPos.Count; i++)
         {
          int checkPos = alleSpielerPos[i];
          foreach (int ofs in ofss)
          {
           if ((feldData[checkPos + ofs] & 3) == 0 && !alleSpielerPos.Any(p => p == checkPos + ofs))
           {
            alleSpielerPos.Add(checkPos + ofs);
            if (erlaubteBoxFelder[checkPos + ofs]) spielerFertig[checkPos + ofs] = true;
           }
          }
         }
         #endregion

         if (find)
         {
          spielerGut.AddRange(alleSpielerPos);
         }
         else
         {
          spielerSchlecht.AddRange(alleSpielerPos);
         }
        }

        if (spielerGut.Count == 0 || spielerSchlecht.Count > 0)
        {
         #region # // --- Box 1 -> Box 2 + 3 ---
         List<short> dazu = new List<short>();

         dazu.Add((short)boxPos2);
         dazu.Add((short)boxPos3);
         if (spielerGut.Count < spielerSchlecht.Count) // nur die guten Felder merken?
         {
          dazu.Add((short)spielerGut.Count);
          dazu.AddRange(spielerGut.Select(pos => (short)pos));
         }
         else // nur die schlechten Felder merken (da weniger)
         {
          dazu.Add((short)-spielerSchlecht.Count);
          dazu.AddRange(spielerSchlecht.Select(pos => (short)pos));
         }

         FehlerDataUpdate(ref fehlerBox3[boxPos1], dazu);
         fehlerVorhanden[boxPos1] |= 1;
         #endregion

         #region # // --- Box 2 -> Box 1 + 3 ---
         dazu.Clear();

         dazu.Add((short)boxPos1);
         dazu.Add((short)boxPos3);
         if (spielerGut.Count < spielerSchlecht.Count) // nur die guten Felder merken?
         {
          dazu.Add((short)spielerGut.Count);
          dazu.AddRange(spielerGut.Select(pos => (short)pos));
         }
         else // nur die schlechten Felder merken (da weniger)
         {
          dazu.Add((short)-spielerSchlecht.Count);
          dazu.AddRange(spielerSchlecht.Select(pos => (short)pos));
         }

         FehlerDataUpdate(ref fehlerBox3[boxPos2], dazu);
         fehlerVorhanden[boxPos2] |= 1;
         #endregion

         #region # // --- Box 3 -> Box 1 + 2 ---
         dazu.Clear();

         dazu.Add((short)boxPos1);
         dazu.Add((short)boxPos2);
         if (spielerGut.Count < spielerSchlecht.Count) // nur die guten Felder merken?
         {
          dazu.Add((short)spielerGut.Count);
          dazu.AddRange(spielerGut.Select(pos => (short)pos));
         }
         else // nur die schlechten Felder merken (da weniger)
         {
          dazu.Add((short)-spielerSchlecht.Count);
          dazu.AddRange(spielerSchlecht.Select(pos => (short)pos));
         }

         FehlerDataUpdate(ref fehlerBox3[boxPos3], dazu);
         fehlerVorhanden[boxPos3] |= 1;
         #endregion
        }

        feldData[boxPos3] ^= 2;
       }

       feldData[boxPos2] ^= 2;
      }

      feldData[boxPos1] ^= 2;
     }
    } break;
    #endregion

    default: throw new NotSupportedException();
   }

  }
Beispiel #3
0
 /// <summary>
 /// Konstruktor zum erstellen eines neuen Hash-Eintrages
 /// </summary>
 /// <param name="hashPos">Hashposition im Hash-Array</param>
 /// <param name="feldData">Daten des Feldes</param>
 public HashFeld(int hashPos, int[] feldData)
 {
  this = new HashFeld(hashPos, feldData, false);
 }
Beispiel #4
0
  /// <summary>
  /// berechnet einen oder mehrere Schritte
  /// </summary>
  /// <param name="limit">maximal zu berechnende Schritte</param>
  void Tick(int limit)
  {
   zurückButton.Enabled = false;
   vorButton.Enabled = false;

   for (int lim = 0; lim < limit; lim++)
   {
    do
    {
     if (merkHashPos == hashGro)
     {
      tickButton.Text = "keine weiteren Knoten bekannt";
      return;
     }

     if (hashGro > hashInfoMax * hashSatzGro)
     {
      hashInfoMax *= 2;
      Array.Resize(ref hashInfo, hashInfoMax + 65536);
     }

     HashFeld h = new HashFeld(merkHashPos);

     if (h.RestWürfel == 0)
     {
      feldZeichner.Zeichne(pictureBox1, new HashFeld(merkHashPos));
      tickButton.Text = "Ziel gefunden! (" + hashIndex.Count.ToString("#,##0") + " Knoten)";
      int pos = merkHashPos;
      List<int> posListe = new List<int>();
      posListe.Add(pos);
      while (pos > 0)
      {
       pos = hashInfo[pos / hashSatzGro].vorgänger;
       posListe.Add(pos);
      }
      posListe.Reverse();
      viewListe = posListe.ToArray();
      viewPos = 0;
      zurückButton.Enabled = false;
      vorButton.Enabled = true;
      return;
     }

     if (h.KannLinks)
     {
      HashFeld neuHash = new HashFeld(hashGro);
      hashInfo[hashGro / hashSatzGro] = new HashInfo(merkHashPos, h.BewegeLinks(neuHash));
      if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
     }

     if (h.KannRechts)
     {
      HashFeld neuHash = new HashFeld(hashGro);
      hashInfo[hashGro / hashSatzGro] = new HashInfo(merkHashPos, h.BewegeRechts(neuHash));
      if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
     }

     if (h.KannOben)
     {
      HashFeld neuHash = new HashFeld(hashGro);
      hashInfo[hashGro / hashSatzGro] = new HashInfo(merkHashPos, h.BewegeOben(neuHash));
      if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
     }

     if (h.KannUnten)
     {
      HashFeld neuHash = new HashFeld(hashGro);
      hashInfo[hashGro / hashSatzGro] = new HashInfo(merkHashPos, h.BewegeUnten(neuHash));
      if (!HashBekannt(neuHash)) hashGro += hashSatzGro;
     }

     merkHashPos += hashSatzGro;
    } while (merkHashPos < hashGro && !hashInfo[merkHashPos / hashSatzGro].verschoben);

    if (merkHashPos < hashGro)
    {
     if (lim + 1 == limit)
     {
      feldZeichner.Zeichne(pictureBox1, new HashFeld(merkHashPos));
      int schritte = OptiErmitteleTiefe(merkHashPos / hashSatzGro);
      tickButton.Text = (hashGro / hashSatzGro).ToString("#,##0") + " Felder (" + ((double)hashGro / 1048576.0).ToString("#,##0.0") + " MB) [" + schritte + "]";
      tickButton.Update();
     }
    }
    else
    {
     tickButton.Text = "keine weiteren Knoten bekannt";
     return;
    }
   }
  }
Beispiel #5
0
  /// <summary>
  /// gibt an, ob der Hashknoten schon bekannt ist
  /// </summary>
  /// <param name="suchHash">Hash nach dem gesucht werden soll</param>
  /// <returns>true, wenn der Hashknoten schon bekannt ist</returns>
  bool HashBekannt(HashFeld suchHash)
  {
   ulong suchCrc = suchHash.GetCrc64();

   bool find;

   if (hashIndex.TryGetValue(suchCrc, out find)) return true;

   hashIndex.Add(suchCrc, true);
   return false;
  }
Beispiel #6
0
 public void Zeichne(PictureBox pictureBox, HashFeld hashFeld)
 {
  Zeichne(pictureBox, Enumerable.Range(hashFeld.hashPos, hashSatzGro).Select(i => (int)hashData[i]).ToArray());
 }
Beispiel #7
0
  private void button1_Click(object sender, EventArgs e)
  {
   button1.Text = "scan";
   button1.Update();
   pictureBox1.Image = null;
   pictureBox1.Update();

   ScanFelder(2 + 16, 26 + 32);

   if (feldData != null)
   {
    #region # // --- Feld auf das nötigste verkleinern ---
    // --- obere leere Zeilen entfernen ---
    for (int c = 0; ; )
    {
     for (int i = 0; i < feldBreite; i++) if (feldData[i] == 0) c++;
     if (c < feldBreite) break;
     for (int i = feldBreite; i < feldData.Length; i++) feldData[i - feldBreite] = feldData[i];
     feldHöhe--;
     Array.Resize(ref feldData, feldData.Length - feldBreite);
     c = 0;
    }

    // --- untere leere Zeilen entfernen ---
    for (int c = 0; ; )
    {
     for (int i = 0; i < feldBreite; i++) if (feldData[i + (feldHöhe - 1) * feldBreite] == 0) c++;
     if (c < feldBreite) break;
     feldHöhe--;
     Array.Resize(ref feldData, feldData.Length - feldBreite);
     c = 0;
    }

    // --- linke leere Spalten entfernen ---
    for (int c = 0; ; )
    {
     for (int i = 0; i < feldHöhe; i++) if (feldData[i * feldBreite] == 0) c++;
     if (c < feldHöhe) break;
     for (int y = 0; y < feldHöhe; y++) for (int x = 1; x < feldBreite; x++) feldData[(x - 1) + y * (feldBreite - 1)] = feldData[x + y * feldBreite];
     feldBreite--;
     Array.Resize(ref feldData, feldData.Length - feldHöhe);
     c = 0;
    }

    // --- rechte leere Spalten entfernen ---
    for (int c = 0; ; )
    {
     for (int i = 0; i < feldHöhe; i++) if (feldData[i * feldBreite + feldBreite - 1] == 0) c++;
     if (c < feldHöhe) break;
     for (int y = 1; y < feldHöhe; y++) for (int x = 0; x < feldBreite - 1; x++) feldData[x + y * (feldBreite - 1)] = feldData[x + y * feldBreite];
     feldBreite--;
     Array.Resize(ref feldData, feldData.Length - feldHöhe);
     c = 0;
    }
    #endregion

    feldAnzahl = feldBreite * feldHöhe;
    hashSatzGro = feldAnzahl + 1 + 1 + 1; // Anzahl + SpielerL + SpielerH + Restwürfel

    button1.Text = "rechne...";
    button1.Update();

    ErstelleErlaubteBoxFelder((new HashFeld(0, feldData)).SpielerPos);

    int[] merkFelder = new int[feldAnzahl];
    Array.Copy(feldData, merkFelder, feldAnzahl);

    FehlerMapErstellen(1);
    FehlerMapErstellen(2);
    FehlerMapErstellen(3);

    MapReset(true);

    hashGro = hashSatzGro;

    Array.Copy(merkFelder, feldData, feldAnzahl);

    HashFeld h = new HashFeld(0, feldData);

    feldZeichner.Zeichne(pictureBox1, h);

    merkHashPos = 0;
    hashInfo[0].verschoben = true;
    hashInfo[0].vorgänger = 0;

    zurückButton.Enabled = false;
    vorButton.Enabled = false;

    hashIndex.Clear();
   }

   button1.Text = "ok";
  }