Ejemplo n.º 1
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();
   }

  }
Ejemplo n.º 2
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;
    }
   }
  }