Vladimirov
Vladimirov

Reputation: 21

What and how do I need to change to successfully generate a complete crossword puzzle (backtracking and recursion)?

I have posted so far what I have done and follow the following principles below, but I seem to be mistaken. The way I generated a crossword puzzle 2-3 years ago was:

  1. I have a class that represents one word. It has coordinates (x, y) - where it starts, orientation (horizontal, vertical), and the word itself.
  2. I have a list of words, which I mix if I want before the algorithm starts.
  3. I take the first word and put it on (0,0), horizontally and put it in the list of solutions.
  4. "I go one level inside" (recursion), I take the next word.
  5. I go through the list of solutions and try to put it somewhere (conditions: two words have a common letter and the orientation is different)
  6. if I find it, I add it to the solutions - if they have a common letter, you can easily calculate the starting point and the orientation.
  7. I check if the partial solution is correct (all words that intersect have the same letters) - maybe this is the most complicated. Maybe it will help to keep in every word where it intersects. 8.1. IF OK, continue (until the word list or other condition, such as the size of the crossword puzzle, is complete) 8.2. IF it is wrong, I remove the word from the solution, remove one level of recursion (backtracking) - for example return null, and try the next word.

Would someone help me or guide me where I am wrong in solving the problem? I am currently generating a crossword puzzle with words (which are not correct crossword arrow type)

<?php 
class Board {
    private $arrBoard;
    private $arrWords;
    private $iCols;
    private $iRows;
       
    public function Board($nRows, $nCols) {
        $this->iCols = $nCols;
        $this->iRows = $nRows;

        for ($col = 0; $col < $this->iCols; $col++) {
            for ($row = 0; $row < $this->iRows; $row++) {
                $this->arrBoard[$row][$col] = '*';
            }
        }
    }
       
    public function visualize() {
        echo "<table border='1'>";
        for ($col = 0; $col < $this->iCols; $col++) {
            echo "<tr c='$col'>";
            for ($row = 0; $row < $this->iRows; $row++) {
                echo "<td r='$row'>" . $this->arrBoard[$row][$col]  . '</td>';
            }
            echo "</tr>";
        }
        echo "</table>";
    }
       
    private function fillRubish() {
           
    }
    public function assignWordList($arrList) {
        $this->arrWords = $arrList;
    }
    private function writeHorizontalWord($sWord) {
        $arrWord = preg_split('//u', $sWord, 0, PREG_SPLIT_NO_EMPTY);
        echo "Horizontal word: $sWord  </br>";
        $arrPos = $this->getRandPosH($sWord);       
        $col = $arrPos['col'];
        $row = $arrPos['row'];
        foreach ($arrWord as $sLetter) {
            $this->arrBoard[$col][$row] = $sLetter;
            $col++;
        }
    }
    private function writeVerticalWord($sWord) {
        $arrWord = preg_split('//u', $sWord, 0, PREG_SPLIT_NO_EMPTY);
        echo "Vertical word: $sWord  </br>";
        $arrPos = $this->getRandPosV($sWord);
        $col = $arrPos['col']; 
        $row = $arrPos['row'];
        foreach ($arrWord as $sLetter) {
            $this->arrBoard[$col][$row] = $sLetter;
            $row++;
        }
    }

    private function getRandPosH($sWord) {
        $iWordLength = strlen($sWord);
        $row = rand(0, $this->iRows-1);
        $col = rand(0, ($this->iCols-$iWordLength)-1);
        return array('col' => $col,'row' => $row);
    }

    private function getRandPosV($sWord) {
        $iWordLength = strlen($sWord);
        $row = rand(0, ($this->iRows-$iWordLength)-1);
        $col = rand(0, $this->iCols-1);
        return array('col' => $col,'row' => $row);
    }



    public function writeWords() {
        foreach($this->arrWords as $sWord => $sArrange) {
            $i++;
            if ($sArrange == 'v') {
                $this->writeVerticalWord($sWord);
            } else if ($sArrange == 'h') {
                $this->writeHorizontalWord($sWord);
            }
        }
    }
}
$oBoard = new Board(6,6);
//$oBoard->visualize();
$arrWords = array('smart' => 'h',
'one' => 'h',
'two' => 'h',
'market' => 'h',
'zoomarket' => 'h',
'store' => 'h',
'shop' => 'h',
'everyday' => 'h',
'everyone' => 'h',
'underground' => 'h',
'business' => 'h',
'small' => 'h',
'okay' => 'h',
'big' => 'h',
'climate' => 'v',
'cocacola' => 'v',
'talk' => 'v',
'me' => 'v',
'tibel' => 'v',
'maxima' => 'v',
'dog' => 'v',
'cat' => 'v',
'frog' => 'v',
'human' => 'v',
'blue' => 'v',
'red' => 'v',
'phone' => 'v',
'telephone' => 'v',
    );
   
$oBoard->assignWordList($arrWords);
$oBoard->writeWords();
echo '</br>================================================== </br>';
$oBoard->visualize();

Output:

s   l   t   p   r   m
*   e   i   h   e   a
s   p   b   o   d   x
e   h   e   n   l   i
o   o   l   e   k   m
b   n   t   l   n   a

Upvotes: 1

Views: 177

Answers (0)

Related Questions