2012-07-08 14 views
9

Xin lỗi cho tiêu đề dài.
Muốn nó mô tả càng tốt.Trò chơi đoán từ PHP (đánh dấu các chữ cái ở vị trí đúng và sai - giống như mastermind)

Tuyên bố từ chối: Có thể tìm thấy một số mã "tìm sự khác biệt" ở đây và ở nơi khác trên Stackoverflow, nhưng không hoàn toàn là chức năng tôi đang tìm kiếm.

tôi sẽ sử dụng những terminoligy sau:
'userguess': một từ sẽ được nhập vào bởi người sử dụng
'giải pháp': từ bí mật mà cần phải được đoán .

Những gì tôi cần phải tạo ra

Một từ trò chơi đoán nơi:

  • Người dùng nhập một từ (Tôi sẽ đảm bảo thông qua Javascript/jQuery rằng từ bước chứa cùng một số chữ cái như từ để được đoán).

  • Chức năng PHP sau đó kiểm tra 'userguess' và đánh dấu (màu xanh lá cây) các chữ cái trong từ đó ở đúng vị trí và các điểm nổi bật (màu đỏ) các chữ cái chưa ở đúng nơi , nhưng hiển thị ở một nơi khác trong từ.
    Các chữ cái không hiển thị trong 'giải pháp' bị để lại màu đen.



Pitfall Kịch bản: - Hãy nói rằng 'giải pháp' là 'aabbc' và người dùng đoán 'abaac'
Trong kịch bản ở trên này sẽ cho kết quả: (màu xanh) một (/ xanh) (màu đỏ) b (/ đỏ) (màu đỏ) một (/ đỏ) (màu đen) một (/ đen) (màu xanh) c (/ xanh)
Thông báo như thế nào cuối cùng "một" là nguyên nhân đen 'userguess' có 3 một là nhưng 'giải pháp' chỉ có 2

Những gì tôi có cho đến nay

Mã đang làm việc nhiều hơn hoặc ít hơn, nhưng tôi có cảm giác nó có thể gầy hơn và có ý nghĩa hơn gấp 10 lần.
Tôi đang điền 2 mảng mới (một cho giải pháp và một cho userguess) khi tôi đi cùng để ngăn chặn các pitfall (xem ở trên) từ những điều rối tung lên.

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 
+0

"// kiểm tra tất cả các chữ cái bên phải ở vị trí RIGHT" không phải chỉ giống như kiểm tra ===? Nếu hầu hết các pple sẽ nhận được nó ngay sau đó bạn cần phải làm ngược lại của "không đầu tiên" tức là kiểm tra, vượt qua đầu tiên, trở lại. – Cups

+0

+1, Không bao giờ tôi thấy một người mới viết câu hỏi chi tiết như vậy! :) – SuperSaiyan

+0

+1 cho câu hỏi gọn gàng ... – Red

Trả lời

2

Câu hỏi hay. Tôi có thể làm điều đó hơi khác với bạn :) (Tôi đoán đó là những gì bạn đang hy vọng!)

Bạn có thể tìm thấy chức năng giải pháp hoàn chỉnh của mình tại đây http://ideone.com/8ojAG - nhưng tôi cũng sẽ phá vỡ từng bước.

Trước tiên, hãy thử và tránh sử dụng global. Không có lý do tại sao bạn không thể xác định chức năng của bạn như:

function checkWord($toCheck, $solution) {

Bạn có thể vượt qua các giải pháp trong và tránh hung hãn sống tiềm năng sau này.

Tôi muốn bắt đầu bằng cách chia cả hai đoán người dùng, và các giải pháp vào mảng, và có một mảng để lưu trữ kết quả của tôi trong.

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

Ở mỗi giai đoạn của quá trình này, tôi muốn loại bỏ các các ký tự đã được xác định là chính xác hoặc không chính xác từ người dùng đoán hoặc giải pháp, vì vậy tôi không cần gắn cờ chúng theo bất kỳ cách nào và các giai đoạn còn lại của hàm chạy hiệu quả hơn.

Vì vậy, để kiểm tra các kết quả phù hợp.

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

Vì vậy, ví dụ đoán của bạn/giải pháp, $out bây giờ chứa một màu xanh lá cây 'a' ở vị trí 0 và c xanh ở vị trí 4. Cả đoán và giải pháp không còn có các chỉ số này, và sẽ không được kiểm tra lại.

Quy trình tương tự để kiểm tra các chữ cái hiện diện, nhưng ở sai vị trí.

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

Trong trường hợp này, chúng tôi đang tìm kiếm thư được đoán trong giải pháp và xóa nó nếu tìm thấy. Chúng tôi không cần tính số lần xuất hiện vì các chữ cái bị xóa khi chúng tôi đi.

Cuối cùng các chữ cái duy nhất còn lại trong người đoán, là những người mà không có mặt ở tất cả các giải pháp, và vì chúng ta duy trì các chỉ số đánh số khắp, chúng tôi chỉ đơn giản là có thể kết hợp các chữ cái còn sót lại trong.

$out += $toCheck;

Hầu như ở đó. $out có mọi thứ chúng tôi cần, nhưng không đúng thứ tự. Mặc dù các chỉ số là số, chúng không được đặt hàng. Chúng tôi kết thúc với:

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

Kết quả từ này là: sản lượng

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

+0

cảm ơn rất nhiều vì đã dành thời gian để viết bài này. Như tôi đã nói: bộ não của tôi chỉ tầm thường khi nói đến thuật toán hardcore. Tôi là một nhà thiết kế web nhiều hơn một nhà phát triển. Tôi không thể cảm ơn bạn đủ cho 1) cung cấp cho tôi tầm nhìn của bạn về mã và 2) dành thêm thời gian để giải thích chi tiết cách bạn xây dựng nó. Chỉ ước tôi có thể chọn 2 câu trả lời làm câu trả lời được chấp nhận của tôi. – Wayfarer

+0

@belgianwolfie Tôi đã cố gắng viết một nhỏ gọn hơn cho bạn quá dựa trên một số chức năng thư viện mảng nội bộ. Chúng là các hàm hữu dụng và bạn có thể sử dụng được trong các dự án tương lai của bạn: ['array_intersect'] (http://php.net/manual/en/function.array-intersect.php) và [' array_diff'] (http://php.net/manual/en/function.array-diff.php) (chúng cũng có các phiên bản '_assoc' để giữ phím) - Cảm ơn bạn đã đặt nỗ lực vào câu hỏi của bạn, rất nhiều người xem SO là một nơi để có được những người khác chỉ làm công việc của họ cho họ những ngày này. Chúc bạn may mắn về những câu hỏi và câu trả lời trong tương lai! – Leigh

1

đây thử này, See In Action

Ví dụ: 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; 
} 
?> 
+0

Không thực sự cần thiết để làm 'isset ($ arr2 [$ key])' bên trong 'foreach ($ arr2 là $ key => $ value) {' nơi bạn không thay đổi mảng hoặc khóa. Không đặc biệt cần thiết để kiểm tra '$ arr1' hoặc kể từ khi tác giả câu hỏi đề xuất xác thực được đặt ở nơi khác để đảm bảo dự đoán và giải pháp có cùng độ dài – Leigh

+0

nó không bị tổn thương, p, một kiểm tra được yêu cầu trên' isset ($ arr1 [ $ key]) 'như từ đoán có thể dài hơn –

+0

đó là một vẻ đẹp. Vẫn cố gắng để bọc não tầm thường của tôi xung quanh các hoạt động bên trong, ngay cả khi mã rất nhỏ gọn :) cảm ơn rất nhiều cho thời gian của bạn. – Wayfarer

Các vấn đề liên quan