Set condition in wordsearch so letters of words will not intersect with each other?

StackOverflow https://stackoverflow.com/questions/21247683

  •  30-09-2022
  •  | 
  •  

Question

I'm trying to make a wordsearch game using php. First I will create the table/grid and then populate the table with random letters and then I will replace the random letters with the letters of the words as well as determining the direction of the words either HORIZONTAL, VERTICAL or DIAGONAL. The problem is, the letters of words intersect with each other, which messed up the table. The questions are,

  • How to set condition where in letters of words will not intersect with each other
  • How to determine if the current position is already occupied by the other words letter?

I'm having problem with the letters of words they keep intersecting with each other. Any idea?

$row = 5;
$col = 5;

$characters = range('a','z');

        $max = count($characters) - 1;  
        $rc = array();

        for ($r=1;$r<=$row;$r++) 
        {
            for ($c=1;$c<=$col;$c++) 
           {
                $rc['r'.$r.'c'.$c] = $characters[mt_rand(0,$max)];
                $fill['r'.$r.'c'.$c] = '';

            }
        }

        $directions = array('H', 'V', 'D');

        $wrdList =array('four', 'data', 'howl');

        foreach ($wrdList as $wrd) 
        {

            $wrdLen = strlen($wrd);
            $dir = $directions[mt_rand(0,2)];

            if ($dir =="H" or $dir=="D" )
            {

                $limitRow = $row - $wrdLen+1;
                $limitCol =  $col - $wrdLen+1;
                $startPointRow = 1;
                $startPointCol = 1;

            }

            elseif ($dir=="V")
            {
                $limitRow = $row  - $wrdLen + 1;
                $limitCol =  $col;
                $startPointRow = 1;
                $startPointCol = 1; 
            }

            $temprow = mt_rand($startPointRow,$limitRow);
            $tempcol =  mt_rand($startPointCol,$limitCol);  


            while($wrdLen >0)
            {

                $thisChar= substr($wrd,0,1);
                $wrd = substr($wrd,1);
                $wrdLen--;  

                $x = 'r'.$temprow.'c'.$tempcol;


                $rc[$x] = $thisChar;


                $fill[$x] = '#2952f8';

                if($dir=="D")
                {
                    $tempcol++;
                    $temprow++;
                }
                elseif($dir=="V")
                {
                    $temprow++;

                }
                elseif($dir=="H")
                {

                    $tempcol++;
                }

            }

        }


        #--Display the random letters and the words
        echo '<table style="border:1px solid #000">';
        for ($r=1;$r<=$row;$r++) 
        {
            echo '<tr style="border:1px solid #000">';
            for ($c=1;$c<=$col;$c++) 
            {
                $thisChar=$rc['r'.$r.'c'.$c]; 
                $fills = $fill['r'.$r.'c'.$c];

                echo '<td style="border:1px solid #000; background-color: '.$fills.'">';
                echo $thisChar;
                echo '</td>';

           }
            echo '</tr>';           
        }
        echo '</table>';
?>
Was it helpful?

Solution

You're doing it backwards. First put in the words you want, then put in the random letters.

Before you put in each successive word, choose the random path for that word, and then along that path, check that there aren't any non-matching letters. (E.g. if 'alphabet' crosses the word 'graph' in a place where they both have a letter 'a', it's okay; otherwise, find a different spot for 'alphabet'). Finally, after all the words are in place, go through the whole thing and put random letters in the spots that don't have letters. Or, if you can't find a place for all the words, start over again.

EDIT:

How to find letters in particular spots. Okay. So, taking a look at your code, you are doing something illogical here:

$rc['r'.$r.'c'.$c] = $characters[mt_rand(0,$max)];

You are creating a one-dimensional array out of, essentially, the product of two keys. Instead, you want to do a two-dimensional array. This makes complete sense because a) you have two keys, and b) word searches have two dimensions.

$rc[$r][$c] = $characters[mt_rand(0,$max)];

So, let's start at the beginning with everything rearranged. Please note that I have rewritten things to start your row/column count at 0 instead of 1 because that's the programming convention for arrays, and I'm not going to try to bend my brain around counting from 1 just for this.

$wrdList =array('four', 'banana', 'howl');
$row = 5;  //six rows counting from 0
$col = 5;  //six columns counting from 0

$rc = array();  //our tableau array
$directions = array('H', 'V', 'D');

foreach ($wrdList as $wrd)
{
    $found = false;  // by default, no spot has been found
    $tries = $row*$col; // we will try a reasonable number of times to find a spot

    while(!$found && $tries > 0) {
        $wrdLen = strlen($wrd);
        $dir = $directions[mt_rand(0,2)];

        if ($dir =="H")
        {
            $limitRow = $row;
            $limitCol =  $col - ($wrdLen - 1);
        }
        elseif($dir=="D")
        {
            $limitRow = $row - ($wrdLen - 1);
            $limitCol =  $col - ($wrdLen - 1);
        }
        elseif ($dir=="V")
        {
            $limitRow = $row  - ($wrdLen - 1);
            $limitCol =  $col;
        }

        $temprow = mt_rand(0,$limitRow);
        $tempcol = mt_rand(0,$limitCol);

        //this is my temporary placement array
        $placement = array();

        //let's use for loop so we can capitalize on having numeric keys
        $r = $temprow;
        $c = $tempcol;
        for($w = 0; $w < $wrdLen; $w++) {
            $thisChar = $wrd{$w};

            //find array keys
            if($dir == 'V' || $dir == 'D') {
                $r = $temprow + $w;
            }
            if($dir == 'H' || $dir == 'D') {
                $c = $tempcol + $w;
            }

            //look at the current tableau
            if(isset($rc[$r][$c])) {  //the intended spot has a letter
                if($rc[$r][$c] == $thisChar) {  //the intended spot's letter is the same
                    $placement[$r][$c] = $thisChar;
                    if($w == $wrdLen-1) { // this is the last letter
                        $found = true;  // we have found a path
                    }
                } else {
                    break;  //this path doesn't work
                }
            } else {
                $placement[$r][$c] = $thisChar;
                if($w == $wrdLen-1) { // this is the last letter
                    $found = true;  // we have found a path
                }
            }
        }
        if($found) {
            //put the letters out of the temporary array and into the tableau
            foreach($placement as $r=>$set) {
                foreach($set as $c=>$letter) {
                    $rc[$r][$c] = $letter;
                }
            }
        }
        $tries--;
    }

    //handle the error where no spot was found for the word
    if(!$found) {
        //your error handling here
    }
}

//random fillers
$characters = range('a','z');
$max = count($characters) - 1;
for($r = 0; $r <= $row; $r++) {
    for($c = 0; $c <= $col; $c++) {
        if(!isset($rc[$r][$c])) {
            $rc[$r][$c] = $characters[mt_rand(0,$max)];
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top