9

抱歉标题太长了。
希望它尽可能具有描述性。

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

稍后我将使用这些术语:
'userguess':用户将输入的单词
'solution':需要猜测的秘密单词。

我需要创建什么

一个猜词游戏,其中:

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

  • 然后,一个 PHP 函数检查“用户猜测”并突出显示(绿色)该单词中位于正确位置的字母,并突出显示(红色)尚未在正确位置但确实出现在其他地方的字母在这个词中。
    未出现在“解决方案”中的字母将保持黑色。



陷阱场景:-假设“解决方案”是 “aabbc”,而用户猜测“abaac”
在上述场景中,这将导致:(绿色)a(/green)(red)b(/red)(red)a (/red)(black) a (/black)(green) c (/green)
注意最后一个“ a ”是黑色的,因为“userguess”有 3 个a,而“solution”只有 2 个

到目前为止我所拥有的

代码或多或少都在工作,但我感觉它可以精简 10 倍。
我正在填充 2 个新数组(一个用于解决方案,一个用于用户猜测),以防止陷阱(见上文)搞砸。

 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
4

2 回答 2

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>"

于 2012-07-08T09:59:46.097 回答
1

来试试这个See In Action

示例输出:在此处输入图像描述

<?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;
}
?>
于 2012-07-08T10:33:19.390 回答