PHP Word猜谜游戏(在正确和错误的位置突出显示字母 - 像主脑一样)

时间:2012-07-08 09:17:10

标签: php

对不起,标题很长 希望它尽可能具有描述性。

免责声明:可以在此处和Stackoverflow上的其他地方找到一些“找到差异”代码,但不是我正在寻找的功能。

我稍后将使用这些术语:
'userguess':用户输入的字词 '解决方案':需要猜到的秘密词。

我需要创建什么

一个单词猜谜游戏,其中:

  • 用户输入一个单词(我将通过Javascript / jQuery确认 输入的单词包含与单词to相同的字母数 猜猜)。

  • 然后PHP函数检查'userguess'和高亮显示(绿色) 那个词中的字母在正确的位置,和 突出显示(红色)尚未在正确位置的字母, 但确实出现在单词的其他地方。
    字母没有 在“解决方案”中显示为黑色。



陷阱场景: - 假设“解决方案”为'aabbc',用户猜测'abaac'
在上述情况下,这将导致:(绿色) a (/绿色)(红色) b (/红色)(红色) a (/红色)(黑色)的(/黑色)(绿色)的 C (/绿色)
注意最后一个“ a ”是黑色的,因为'userguess'有3个 a 但是'解决方案'只有2个

到目前为止我有什么

代码工作或多或少,但我觉得它可以是精益和平均值的10倍 我正在填写2个新数组(一个用于解决方案,一个用于userguess),因为我一直在努力防止陷阱(见上文)搞乱。

 function checkWord($toCheck) {
        global $solution;      // $solution word is defined outside the scope of this function
        $goodpos = array();    // array that saves the indexes of all the right letters in the RIGHT position
        $badpos  = array();    // array that saves the indexes of all the right letters in the WRONG position
        $newToCheck = array(); // array that changes overtime to help us with the Pitfall (see above)
        $newSolution = array();// array that changes overtime to help us with the Pitfall (see above)

        // check for all the right letters in the RIGHT position in entire string first
        for ($i = 0, $j = strlen($toCheck); $i < $j; $i++) {
           if ($toCheck[$i] == $solution[$i]) {
               $goodpos[] = $i;
               $newSolution[$i] = "*"; // RIGHT letters in RIGHT position are 'deleted' from solution
           } else {
               $newToCheck[] = $toCheck[$i]; 
               $newSolution[$i] = $solution[$i];
           }
        }

        // go over the NEW word to check for letters that are not in the right position but show up elsewhere in the word
        for ($i = 0, $j = count($newSolution); $i <= $j; $i++) {
           if (!(in_array($newToCheck[$i], $newSolution))) {
               $badpos[] = $i;
               $newSolution[$i] = "*";
           } 
        }

        // use the two helper arrays above 'goodpos' and 'badpos' to color the characters
        for ($i = 0, $j = strlen($toCheck), $k = 0; $i < $j; $i++) {
            if (in_array($i,$goodpos)) {
                $colored .= "<span class='green'>";
                $colored .= $toCheck[$i];
                $colored .= "</span>";
            } else if (in_array($i,$badpos)) {
                $colored .= "<span class='red'>";
                $colored .= $toCheck[$i];
                $colored .= "</span>";
            } else {
                $colored .= $toCheck[$i];   
            }
        }

        // output to user
        $output  = '<div id="feedbackHash">';
        $output .= '<h2>Solution was : &nbsp;' . $solution . '</h2>';
        $output .= '<h2>Color corrected: ' . $colored . '</h2>';
        $output .= 'Correct letters in the right position : ' . count($goodpos) . '<br>';
        $output .= 'Correct letters in the wrong position : ' . count($badpos)  . '<br>';
        $output .= '</div>';

        return $output;
    } // checkWord

2 个答案:

答案 0 :(得分:2)

好问题。我可能会对你做的有点不同:)(我想这就是你所希望的!)

你可以在http://ideone.com/8ojAG找到我的完整解决方案功能 - 但我也会逐步分解它。

首先,请尽量避免使用global。你没有理由不能将你的功能定义为:

function checkWord($toCheck, $solution) {

您可以通过该解决方案,以后避免潜在的恶意行为。

我首先将用户猜测和解决方案分成数组,并使用另一个数组来存储我的输出。

$toCheck = str_split($toCheck, 1);
$solution = str_split($solution, 1);
$out = array();

在流程的每个阶段,我都会从用户猜测或解决方案中删除已被识别为正确或不正确的字符,因此我不需要以任何方式标记它们,以及其余的阶段该功能运行效率更高。

所以要检查比赛。

foreach ($toCheck as $pos => $char) {
    if ($char == $solution[$pos]) {
        $out[$pos] = "<span class=\"green\">$char</span>";
        unset($toCheck[$pos], $solution[$pos]);
    }
}

因此,对于您的示例猜测/解决方案,$out现在在位置0处包含绿色'a',在位置4处包含绿色c。猜测和解决方案都不再具有这些索引,并且不会再次检查。

用于检查存在但在错误位置的字母的类似过程。

foreach ($toCheck as $pos => $char) {
    if (false !== $solPos = array_search($char, $solution)) {
        $out[$pos] = "<span class=\"red\">$char</span>";
        unset($toCheck[$pos], $solution[$solPos]);
    }
}

在这种情况下,我们正在搜索解决方案中的猜测字母,如果找到则将其删除。我们不需要计算出现次数,因为我们去的时候会删除这些字母。

最后,用户猜测中剩下的唯一字母是解决方案中根本不存在的字母,并且由于我们始终保持编号索引,我们可以简单地合并剩余的字母。

$out += $toCheck;

几乎就在那里。 $out拥有我们需要的一切,但它的顺序并不正确。即使索引是数字的,它们也不是有序的。我们完成了:

ksort($out);
return implode($out);

这样做的结果是:

"<span class="green">a</span><span class="red">b</span><span class="red">a</span>a<span class="green">c</span>"

答案 1 :(得分:1)

在此尝试此操作, See In Action

示例输出:enter image description here

<?php 
echo checkWord('aabbc','abaac').PHP_EOL;
echo checkWord('funday','sunday').PHP_EOL;
echo checkWord('flipper','ripple').PHP_EOL;
echo checkWord('monkey','kenney').PHP_EOL;

function checkWord($guess, $solution){
    $arr1 = str_split($solution);
    $arr2 = str_split($guess);
    $arr1_c = array_count_values($arr1);
    $arr2_c = array_count_values($arr2);
    $out = '';
    foreach($arr2 as $key=>$value){
        $arr1_c[$value]=(isset($arr1_c[$value])?$arr1_c[$value]-1:0);
        $arr2_c[$value]=(isset($arr2_c[$value])?$arr2_c[$value]-1:0);

        if(isset($arr2[$key]) && isset($arr1[$key]) && $arr1[$key] == $arr2[$key]){
            $out .='<span style="color:green;">'.$arr2[$key].'</span>';
        }elseif(in_array($value,$arr1) && $arr2_c[$value] >= 0 && $arr1_c[$value] >= 0){
            $out .='<span style="color:red;">'.$arr2[$key].'</span>';
        }else{
            $out .='<span style="color:black;">'.$arr2[$key].'</span>';
        }
    }
    return $out;
}
?>