jshc86 Posted May 8, 2010 Share Posted May 8, 2010 I have an interesting dilemma. I am writing a script for a game called Jotto. If you haven't heard of it, a challenger selects a five letter word and people try to guess what the word is by choosing other five letter words; at that point, the challenger tells the guesser how many letters their word has in common with the challenger's word. Using logic, you can eventually deduce what the word is by eliminating letters of the alphabet. As an example, say the challenger's word is "class". A typical game would look something like this. Note: I'm including which letters are in common for demonstrative purposes...I wouldn't actually do that if a game is going on. Guessed word[/td]Letters in common slimy2 (l and s) saucy3 (a, c and s) sassy3 (a and s twice) class[td]5 (winner) You'll notice for "sassy", their are three letters in common, two of which come from the double "s". BUT, the extra "s" in "sassy" does not count because the challenge word only contains the letter "s" twice. Anyways, I am writing a script to take a guessed word and compare it to the challenger's word. Here's the original script I tried which DOESN'T work: <?php $guessed_word = "sassy"; $challenge_word = "class"; // Break up each word into its letters $g_array = str_split($guessed_word); $c_array = str_split($challenge_word); // Check for letters in common $common = array_intersect($g_array, $c_array); echo count($common); // Returns 4 and NOT 3 ?> Now I'm aware that switching the order of the arguments in the array_intersect part of my code WILL return a value of 3 like I wanted, but if you fiddle around with it enough, you'll see that the array_intersect function won't do. So, I decided to write a custom function instead. The method behind the function is: break up the two words into their letters, run a while loop for the guessed word while array_shift returns true, check if the letter from array_shift is found in the challenge word array, if it is found remove the letter from the challenge word array, add 1 to my counter variable and repeat. Here's what that looks like: <?php function jots($word1, $word2) { // The guessed word $g_word = str_split($word1); // The challenger's word $c_word = str_split($word2); // Initialize counter $i = 0; if($c_word == $g_word) { echo 6; // This is if the person gets the word correct...6 is my indicator for a winning game } else { while($letter = array_shift($g_word)) { if($key = array_search($letter, $c_word)) { // Remove the found letter from the challenge word array unset($c_word[$key]); $i++; } } echo "The word has {$i} letters in common"; } } ?> Theoretically this should work. However it still gives me problems. See the code below to see what I mean. <?php jots("linus", "linux"); // Returns "The word has 3 letters in common" when really it's 4 jots("light", "right"); // Returns "The word has 4 letters in common", which is correct...but it's similar to the above example where only 1 letter is different. GRRR!! ?> This is pretty frustrating. Does anyone have any ideas? Quote Link to comment Share on other sites More sharing options...
JAY6390 Posted May 8, 2010 Share Posted May 8, 2010 How abouts we make it a really simple function instead function jotts($answer, $guess) { $out = array_diff(str_split($answer), str_split($guess)); return strlen($answer) - count($out); } echo jotts('linus', 'linux'); Quote Link to comment Share on other sites More sharing options...
JAY6390 Posted May 8, 2010 Share Posted May 8, 2010 Wait, I think I've misunderstood, you don't want just the number of letters that aren't present do you? You want the number of letters right and in the right place is that correct? Quote Link to comment Share on other sites More sharing options...
JAY6390 Posted May 8, 2010 Share Posted May 8, 2010 How about this instead - I finally guessed what it was the game did function jotts($answer, $guess) { $count = 0; $a = str_split($answer); $g = str_split($guess); foreach($g as $v) { $key = array_search($v, $a); if($key !== FALSE) { unset($a[$key]); $count++; } } echo 'Total jotts for <strong>'.$guess.'</strong> in word <strong>'.$answer.'</strong> is <strong>'.$count.'</strong><br />'; } jotts('class', 'slimy'); jotts('class', 'saucy'); jotts('class', 'sassy'); jotts('class', 'class'); jotts('linus', 'linux'); jotts('light', 'right'); This returns Total jotts for slimy in word class is 2 Total jotts for saucy in word class is 3 Total jotts for sassy in word class is 3 Total jotts for class in word class is 5 Total jotts for linux in word linus is 4 Total jotts for right in word light is 4 Quote Link to comment Share on other sites More sharing options...
jshc86 Posted May 8, 2010 Author Share Posted May 8, 2010 Thanks JAY for your help. Right after I posted I actually thought that the foreach loop would work. I'm curious as to why array_shift gives unpredictable results though? To clarify, there are multiple versions of Jotto that are played. In my case, the exact placement of the letters is not important. So if the challenge word was "tenet", and my guess was "atlas", it would still count for 1 even though the "t" is not in the correct place. However, if exact placement DID matter, my guess of "atlas" would yield zero because none of the letters are in the correct place. Quote Link to comment Share on other sites More sharing options...
JAY6390 Posted May 8, 2010 Share Posted May 8, 2010 The problem is that you have the assigning of array_search() to $key in an if() statement. The first pass of this won't work simply because 0 is equivalent to false, meaning that the unset will never happen for the first character (at key 0). This is visible if you do some debugging. Just add echo "LETTER: $letter - KEY: $key - i: $i<br />"; at the very end of the while loop just before the } and you get the following output LETTER: l - KEY: 0 - i: 0 LETTER: i - KEY: 1 - i: 1 LETTER: n - KEY: 2 - i: 2 LETTER: u - KEY: 3 - i: 3 LETTER: s - KEY: - i: 3 It becomes more apparent with this, as you see the $key is matched as 0 with the l, but $i does not increase when it should. Changing your code to function jots($word1, $word2) { // The guessed word $g_word = str_split($word1); // The challenger's word $c_word = str_split($word2); // Initialize counter $i = 0; if ($c_word == $g_word) { echo 6; // This is if the person gets the word correct...6 is my indicator for a winning game } else { while ($letter = array_shift($g_word)) { $key = array_search($letter, $c_word); if ($key !== FALSE) { // Remove the found letter from the challenge word array unset($c_word[$key]); $i++; } } echo "The word has {$i} letters in common"; } } Hope that clears up the reasoning Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.