Skapa ett spel - Gissa talet

I denna guiden visar vi hur man kan skapa ett gissningsspel i PHP. Besökaren ombeds gissa ett tal som sidan tänker på. Vi börjar med en väldigt enkelt version, som säger om gissningen var korrekt eller ej, och utvecklar den sen till att vara betydligt mer avancerad.

Den här guiden förutsätter att du har läst de fem första lektionerna i vår PHP-skola (första lektionen till och med lektionen om villkorssatser). Om du inte har det finns det troligtvis kod nedan du inte förstår och som inte förklaras här. Fortsätt läs på egen risk om du har skolkat!

Spelet är väldigt simpelt. Vi har ett enkelt formulär där besökaren ska få skriva in en gissning på ett tal mellan 0 och 100.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p> <form method="post" action="gissat.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>

Vi har även en sida som kollar om talet besökaren gissade var rätt tal.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissade du rätt?</title> </head> <body> <?php // Bedöm om gissningen ($_POST['gissning']) är rätt eller ej echo '<p>Du gissade på talet '.$_POST['gissning'].'.</p>'; // Skriv ut gissningen (för att se om det fungerar) ?> </body> </html>

Det här kan vi bygga vidare på, men vanligtvis finns det många fördelar med att ha all kod i en fil, vilket vi kommer ta tillvara på. Formuläret besökaren fyller i kommer alltså skickas till sidan formuläret finns på. Med hjälp av en villkorssats och funktionen isset kan man avgöra om besökaren har skickat formuläret eller inte när sidan laddas.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <?php if(isset($_POST['gissning'])){ // $_POST['gissning'] finns, alltså har besökaren skickat formuläret // Här ska vi alltså bedöma gissningen (återstår att göra) echo '<p>Du gissade på talet '.$_POST['gissning'].'.</p>'; // Skriv ut gissningen (för att se om det fungerar) }else{ // $_POST['gissning'] finns inte, alltså har besökaren inte skickat formuläret // Visa en instruktionstext echo '<p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p>'; } ?> <!-- Formuläret visas alltid, oavsett om man skickat det eller inte --> <form method="post" action="gissaTalet.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>

Låt oss fortsätta med att bedöma gissningen. Med en vanlig villkorssats och jämförelseoperatorn == kan vi enkelt bedöma om besökarens gissning är korrekt. Vi behöver dock först avgöra vad som är rätt gissningen, och i det här fallet låter vi 42 vara det sökta talet.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <?php if(isset($_POST['gissning'])){ // Rätt gissning? if($_POST['gissning'] == 42){ echo '<p>Mitt i prick! Bra jobbat!</p>'; }else{ echo '<p>Tyvärr, det där är inte helt rätt.</p>'; } }else{ echo '<p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p>'; } ?> <form method="post" action="gissaTalet2.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>

Tada! Vår första version av spelet är färdigt.

Just nu är det inte ett så roligt spel, men det ska vi ändra på. Eftersom det sökta talet ligger mellan 0 och 100 behövs i genomsnitt 50 gissningar innan man lyckats hitta det sökta talet. Det klart ingen tycker det är kul, så hur kan vi få ner antalet gissningar? Ett sätt är att ge besökaren tips denne kan använda för nästa gissning. I vårat exempel ska vi tala om för besökaren ifall dennes gissning är för lågt eller för högt, om det inte är rätt. Då borde antalet gissningar som behövs för att hitta det sökta talet minska drastiskt. Om optimala gissningar görs behövs i värsta fall 7 gissningar (hur man kommer fram till det få du lära dig om någon annan stans).

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <?php if(isset($_POST['gissning'])){ if($_POST['gissning'] == 42){ echo '<p>Mitt i prick! Bra jobbat!</p>'; }else{ // För lågt? if($_POST['gissning'] < 42){ echo '<p>Tyvärr, det sökta talet är högre än '.$_POST['gissning'].'.</p>'; }else{ echo '<p>Tyvärr, det sökta talet är lägre än '.$_POST['gissning'].'.</p>'; } } }else{ echo '<p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p>'; } ?> <form method="post" action="gissaTalet3.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>

Nu har vi dock skrivit något vi kan göra bättre. På två ställen i koden har vi skrivit in det sökta talet (42), vilket är dumt. Om vi i framtiden vill byta ut det sökta talet måste vi gå in i koden och ändra på två ställen. Visst, det är inte så jobbigt att ändra på två ställen, men just nu är det två ställen, när vi har gjort spelet lite mer avancerat ligger troligtvis 42 hårdkodat på fler ställen än två, och då börjar vi önska att vi inte hårdkodat in det. Lösningen på det är att tilldela en variabel värdet 42, och så fort vi vill använda det sökta talet använder vi oss av variabeln istället.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <?php // Det sökta talet $korrektTal = 42; if(isset($_POST['gissning'])){ // Jämför med variabelns värde istället för talet 42 hårdkodat if($_POST['gissning'] == $korrektTal){ echo '<p>Mitt i prick! Bra jobbat!</p>'; }else{ // Jämför med variabelns värde istället för talet 42 hårdkodat if($_POST['gissning'] < $korrektTal){ echo '<p>Tyvärr, det sökta talet är högre än '.$_POST['gissning'].'.</p>'; }else{ echo '<p>Tyvärr, det sökta talet är lägre än '.$_POST['gissning'].'.</p>'; } } }else{ echo '<p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p>'; } ?> <form method="post" action="gissaTalet4.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>

Spelet har nu nått version 2 och har blivit lite enklare att klara av (testa själv), men vad är nästa steg i dess utveckling? En lyxig funktion skulle vara om man kunde se hur många gånger man har gissat, men hur kan man implementera något sådant? Jo, vi behöver en variabel som börjar på 0, innan man gissat någon gång, och sedan ökar med 1 för varje gissning man gör. Men PHP-koden på en sida exekveras ju en gång för varje sidladdning, hur kan man ha en variabel som finns tillgänglig mellan olika sidladdningar? Jo, den speciella variabeln $_SESSION, som skapas när man anropat funktionen session_start, återupptar sitt gamla värde mellan varje sidladdning, så lösningen är att använda denna. Vi kommer låta nyckeln "antalGissningar" hålla reda på hur många gånger besökaren har gissat.

<?php /* Vi lägger anropet till session_start högst upp i koden, då den måste anropas innan någon output skickas till webbläsaren. */ session_start(); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <?php $korrektTal = 42; if(isset($_POST['gissning'])){ /* Om formuläret skickats finns antalet gissningar man gjort i $_SESSION['antalGissningar'] */ $_SESSION['antalGissningar']++; // Öka även antalet gissningar med 1 if($_POST['gissning'] == $korrektTal){ echo '<p>Mitt i prick! Bra jobbat!</p>'; }else{ if($_POST['gissning'] < $korrektTal){ echo '<p>Tyvärr, det sökta talet är högre än '.$_POST['gissning'].'.</p>'; }else{ echo '<p>Tyvärr, det sökta talet är lägre än '.$_POST['gissning'].'.</p>'; } } // Skriv även ut antalet gissningar echo '<p>Antalet gissningar du gjort är nu: '.$_SESSION['antalGissningar'].'.</p>'; }else{ // Om man inte skickat formuläret har man aldrig gissat $_SESSION['antalGissningar'] = 0; echo '<p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p>'; } ?> <form method="post" action="gissaTalet5.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>

Version 3 av spelet är nu klart, vilken funktionalitet skulle man kunna lägga till för version 4? Jo, det är ju lite tråkigt att 42 är det sökta talet hela tiden, det skulle vara mycket roligare om det var olika tal varje gång. För att åstadkomma detta kan vi använda funktionen mt_rand, som generar ett slumpat heltal inom ett visst heltalsintervall. Intervallet gränser skickar man med som argument till funktionen.

En första känsla är att man enbart behöver ändra en rad i koden för att få det att fungera.

<?php session_start(); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <?php // Slumpa det korrekta talet (mellan 0 och 100) istället $korrektTal = mt_rand(0, 100); if(isset($_POST['gissning'])){ $_SESSION['antalGissningar']++; if($_POST['gissning'] == $korrektTal){ echo '<p>Mitt i prick! Bra jobbat!</p>'; }else{ if($_POST['gissning'] < $korrektTal){ echo '<p>Tyvärr, det sökta talet är högre än '.$_POST['gissning'].'.</p>'; }else{ echo '<p>Tyvärr, det sökta talet är lägre än '.$_POST['gissning'].'.</p>'; } } echo '<p>Antalet gissningar du gjort är nu: '.$_SESSION['antalGissningar'].'.</p>'; }else{ $_SESSION['antalGissningar'] = 0; echo '<p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p>'; } ?> <form method="post" action="gissaTalet6.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>

Om du testar spelet nu får du verkligen problem med att klara det. Om du först chansar på talet 50 kan till exempel spelet tala om att det sökta talet är lägre än det, och om du chansar på 50 en gång till så finns chansen att spelet nu säger att det sökta talet är högre än 50!

Hur kommer detta sig? Jo, nu får variabeln $korrektTal ett nytt värde slumpat till sig varje sidladdning, så när besökaren skickat sin första gissning kanske det korrekta talet har värdet 25, medan den under andra sidladdningen har värdet 75. Men vi vill ju att $korrektTal ska ha samma slumpade värde igenom hela spelet. En lösning på detta är att spara det i $_SESSION.

<?php session_start(); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Gissa talet!</title> </head> <body> <?php if(isset($_POST['gissning'])){ $_SESSION['antalGissningar']++; // Jämför med $_SESSION['korrektTal'] istället för $korrektTal if($_POST['gissning'] == $_SESSION['korrektTal']){ echo '<p>Mitt i prick! Bra jobbat!</p>'; }else{ // Jämför med $_SESSION['korrektTal'] istället för $korrektTal if($_POST['gissning'] < $_SESSION['korrektTal']){ echo '<p>Tyvärr, det sökta talet är högre än '.$_POST['gissning'].'.</p>'; }else{ echo '<p>Tyvärr, det sökta talet är lägre än '.$_POST['gissning'].'.</p>'; } } echo '<p>Antalet gissningar du gjort är nu: '.$_SESSION['antalGissningar'].'.</p>'; }else{ /* Slumpa bara fram det sökta talet första sidladdningen och spara det i $_SESSION['korrektTal'] */ $_SESSION['korrektTal'] = mt_rand(0, 100); $_SESSION['antalGissningar'] = 0; echo '<p>Jag tänker på ett tal mellan 0 och 100, gissa vilket!</p>'; } ?> <form method="post" action="gissaTalet7.php"> Gissning: <input type="text" name="gissning"> <input type="submit" value="Rätta gissning"> </form> </body> </html>