Buchstabenrätsel-Generator

Hallo
mir ist noch eine Idee zu einem Programm gekommen, mit dessen Hilfe sich Buchstabenrätsel generieren lassen.

Anforderungen und Kriterien:
  • Schwierigkeit (Größe der Tabelle, ob die Wörter waagerecht, senkrecht, diagonal, vorwärts und/oder rückwärts versteckt werden sollen) vom User wählbar
  • Die Zellen in denen keine Buchstaben der gesuchten/gegebenen Wörter versteckt sind werden mit "Buchstabenmüll" gefüllt, bestehend aus zufällig verteilten Großbuchstaben.
  • Der "Buchstabenmüll" darf kein Wort bilden was gesucht wird
  • Bestimmte Bedingungen müssen von vorneherein ausgeschlossen werden, zb 5x5 Felder und 20 Wörter
  • Pro Zelle nur ein Buchstabe
  • Am Ende wird eine Lösung ausgegebn in der die Wörter hervorgehoben sind
Ich habe mal ein von Hand erstelltes Beispiel (das dort ein Wort mehr versteckt ist als angegeben ist gewollt) angehangen.
 
[OT]
Aber bitte eine Hot-Button-Funktion einbauen, die Ratefüchse verteilt und 1?/ Klick verlangt *scnr*
[/OT]
 
Hab da mal ne (vorläufige) Lösung. Ist vielleicht noch nicht alles optimal Gelöst.

PHP Klasse "game"

PHP:
<?php
/*@author:n3or*/
/*@php-version: 5.x*/
define('HORIZONTAL', 1);
define('VERTICAL', 2);
define('DIAGONAL', 3);
class game
{
  public $fieldWidth;
  public $fieldHeight;
  public $squareWidth;
  public $squareHeight;
  public $toLower;
  public $diagonal;
  public $back;
  private $strlenAllWords;
  private $words = array();
  
  public function randAlpha()
  {
    $letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
    if ($this->toLower)
    {
      return $letters[rand(0,23)];
    }
    else
    {
      return strToUpper($letters[rand(0,23)]);
    }
  }
  private function randWordByAdjustment($adjustment, $sum = false)
  {
    $this->returnWords = array();
    foreach ($this->words as $this->word)
    {
      if ($this->word['adjustment'] == $adjustment)
      {
        $this->returnWords[] = $this->word['word'];
      }
    }
    
    $this->returnWordsCount = count($this->returnWords);
    if ($sum)
    {
      return $this->returnWordsCount;
    }
    
    if ($this->returnWordsCount > 0)
    {
      $this->rand = rand(0, --$this->returnWordsCount);
      $this->deleteWord($this->returnWords[$this->rand]);
      return $this->returnWords[$this->rand];
    }
    return false;
  }
  private function getPartition()
  {
    $this->engaged = array();
    while ($this->randWord = $this->randWordByAdjustment(HORIZONTAL))
    {
      $this->ok = false;
      $this->i = 0;
      while (!$this->ok)
      {
        $this->row = rand(0, $this->fieldHeight-1);
        $this->col = rand(0, ($this->fieldWidth-1)-strlen($this->randWord));
        
        $this->ok = true;
        for ($this->i=0;$this->i!=strlen($this->randWord);$this->i++)
        {
          if (isset($this->engaged[$this->row.'_'.($this->col+$this->i)]))
          {
            $this->ok = false;
          }
        }
        $this->i++;
        if ($this->i == 50) { break; }
      }
      if ($this->i == 50)
      {
        trigger_error('Too less place for this words..', E_USER_WARNING);
      }
      $this->align = rand(0, 3);
      if (!$this->back) { $this->align = 0; }
      for ($this->i=0;$this->i!=strlen($this->randWord);$this->i++)
      {
        if ($this->align != 3)
        {
          $this->engaged[$this->row.'_'.($this->col+$this->i)] = $this->randWord{$this->i};
        }
        else
        {
          $this->engaged[$this->row.'_'.(($this->col+strlen($this->randWord))-$this->i)] = $this->randWord{$this->i};
        }
      }
    }
    while ($this->randWord = $this->randWordByAdjustment(VERTICAL))
    {
      $this->ok = false;
      $this->i = 0;
      while (!$this->ok)
      {
        $this->row = rand(0, ($this->fieldHeight-1)-strlen($this->randWord));
        $this->col = rand(0, $this->fieldWidth-1);
        
        $this->ok = true;
        for ($this->i=0;$this->i!=strlen($this->randWord);$this->i++)
        {
          if (isset($this->engaged[($this->row+$this->i).'_'.$this->col]))
          {
            if ($this->engaged[($this->row+$this->i).'_'.$this->col] != $this->randWord{$this->i} or isset($this->engaged[($this->row+1+$this->i).'_'.$this->col]) or isset($this->engaged[($this->row-1+$this->i).'_'.$this->col]))
            {
              $this->ok = false;
            }
          }
        }
        $this->i++;
        if ($this->i == 50) { break; }
      }
      if ($this->i == 50)
      {
        trigger_error('Too less place for this words..', E_USER_WARNING);
      }
      $this->align = rand(0, 3);
      if (!$this->back) { $this->align = 0; }
      for ($this->i=0;$this->i!=strlen($this->randWord);$this->i++)
      {
        if ($this->align != 3)
        {
          $this->engaged[($this->row+$this->i).'_'.$this->col] = $this->randWord{$this->i};
        }
        else
        {
          $this->engaged[(($this->row+strlen($this->randWord))-$this->i).'_'.$this->col] = $this->randWord{$this->i};
        }
      }
    }
    if ($this->diagonal)
    {
      while ($this->randWord = $this->randWordByAdjustment(DIAGONAL))
      {
        $this->ok = false;
        $this->i = 0;
        while (!$this->ok)
        {
          $this->row = rand(0, ($this->fieldHeight-1)-strlen($this->randWord));
          $this->col = rand(0, ($this->fieldWidth-1)-strlen($this->randWord));
          
          $this->ok = true;
          for ($this->i=0;$this->i!=strlen($this->randWord);$this->i++)
          {
            if (isset($this->engaged[($this->row+$this->i).'_'.($this->col+$this->i)]))
            {
              $this->ok = false;
            }
          }
          $this->i++;
          if ($this->i == 50) { break; }
        }
        
        if ($this->i == 50)
        {
          trigger_error('Too less place for this words..', E_USER_WARNING);
        }
        
        $this->align = rand(0, 3);
        if (!$this->back)
        {
          if ($this->align == 2) { $this->align = 3; }
          if ($this->align == 1) { $this->align = 0; }
        }
        for ($this->i=0;$this->i!=strlen($this->randWord);$this->i++)
        {
          switch ($this->align)
          {
            case 3:
              $this->engaged[($this->row+(strlen($this->randWord)-1)-$this->i).'_'.($this->col+$this->i)] = $this->randWord{$this->i};
              break;
            case 2:
              $this->engaged[($this->row+$this->i).'_'.(($this->col+(strlen($this->randWord)-1))-$this->i)] = $this->randWord{$this->i};
              break;
            case 1:
              $this->engaged[(($this->row+(strlen($this->randWord)-1))-$this->i).'_'.(($this->col+(strlen($this->randWord)-$this->i)-1))] = $this->randWord{$this->i};
              break;
            default:
              $this->engaged[($this->row+$this->i).'_'.($this->col+$this->i)] = $this->randWord{$this->i};
              break;
          }
        }
      }
    }
    return($this->engaged);
  }
  public function __construct($fieldWidth = 50, $fieldHeight = 25, $squareWidth = '20px', $squareHeight = '20px', $toLower = false)
  {
    $this->fieldWidth = $fieldWidth;
    $this->fieldHeight = $fieldHeight;
    $this->squareWidth = $squareWidth;
    $this->squareHeight = $squareHeight;
    $this->toLower = $toLower;
    $this->strlenAllWords = 0;
    $this->back = true;
    $this->diagonal = true;
  }
  public function createWordArray()
  {
    $this->returnArray = array();
    foreach ($this->words as $this->word)
    {
      $this->returnArray[] = $this->word['word'];
    }    
    return $this->returnArray;
  } 
  public function addWord($word, $adjustment)
  {
    $word = str_replace('ä', 'ae', $word);
    $word = str_replace('ö', 'oe', $word);
    $word = str_replace('ü', 'ue', $word);
    $word = str_replace('ß', 'ss', $word);
    
    if ($this->toLower)
    {
      $word = strToLower($word);
    }
    else
    {
      $word = strToUpper($word);
    }
    
    if ($adjustment == HORIZONTAL or $adjustment == DIAGONAL or $adjustment == VERTICAL)
    {
      if (($adjustment == HORIZONTAL and strlen($word) <= $this->fieldWidth) or ($adjustment == VERTICAL and strlen($word) <= $this->fieldHeight) or ($adjustment == DIAGONAL and strlen($word) <= $this->fieldWidth and strlen($word) <= $this->fieldHeight))
      {
        if (($this->strlenAllWords + strlen($word)) < ((($this->fieldWidth * $this->fieldHeight) / 100) * 80))
        {
          if (!in_array($word, $this->createWordArray()))
          {
            $this->words[] = array('word' => $word, 'adjustment' => $adjustment);
            return true;
          }
          else
          {
            trigger_error('Word "'.$word.'" already exists!', E_USER_WARNING);
            return false;
          }
        }
        else
        {
          trigger_error('There are too much Words!', E_USER_WARNING);
          return false;
        }
      }
      else
      {
        trigger_error('Word "'.$word.'" is too long!', E_USER_WARNING);
        return false;
      }
    }
    else
    {
      trigger_error('No valid adjustment!', E_USER_ERROR);
      return false;
    }
  }
  public function deleteWord($word)
  {
    if ($this->toLower)
    {
      $word = strToLower($word);
    }
    else
    {
      $word = strToUpper($word);
    }
    
    $this->newWords = array();
    foreach ($this->words as $this->word)
    {
      if ($this->word['word'] != $word)
      {
        $this->newWords[] = array('word' => $this->word['word'], 'adjustment' => $this->word['adjustment']);
      }
    }
    $this->words = $this->newWords;
    
    return true;
  }
  public function createHtmlField()
  {
    $this->engaged = $this->getPartition();
    
    echo('<table id="words">');
      for ($this->r=0;$this->r<$this->fieldHeight;$this->r++)
      {
        echo('<tr id="'.$this->r.'">');
          for ($this->c=0;$this->c<$this->fieldWidth;$this->c++)
          {
            echo('<td onclick="changeColor(this.id)" id="'.$this->r.'_'.$this->c.'" style="width:'.$this->squareWidth.'; height:'.$this->squareHeight.';">');
              if (isset($this->engaged[$this->r.'_'.$this->c]))
              {
                echo('<span class="mark">'.$this->engaged[$this->r.'_'.$this->c].'</span>');
              }
              else
              {
                echo($this->randAlpha());
              }
            echo('</td>');
          }
        echo('</tr>');
      }
    echo('</table>');
  }
}
?>

Im Anhang ist die Klasse und eine index.php mit dem Optionen-Formular,..

mfg
n3or
 
das sieht doch schonmal super aus, man muss zusätzliche/andere Wörter zwar noch im Source ändern, aber das ist ja mal egal, es klappt ja immerhin :)
 
Ich werde das noch machen, dass die anderen wörter auch über die eingabemaske zu ändern sind. Je nach dem wie ich Zeit finde mach ichs dieses Wochenende noch.

mfg
n3or
 
Zurück
Oben