Räkna ut bowlingpoäng med PHP – en komplett guide
Har du någonsin undrat hur man egentligen räknar poäng i bowling? Kanske bygger du ett litet verktyg för din bowlingklubb, en webbapp för att följa dina serier, eller bara vill förstå logiken bättre. I den här guiden visar jag hur du kan implementera en poängräknare i PHP – från grunderna i poängsystemet till färdig kod du kan anpassa.
Själva konceptet är inte så komplicerat, men det finns några knepiga detaljer som den tionde rutan och hur bonusar från strikes och spares fungerar. Låt oss dyka ner i det!
Hur fungerar bowlingpoäng egentligen?
Innan vi skriver någon kod måste vi förstå reglerna. Ett bowlingparti består av 10 rutor (frames). I varje ruta har du två slag (förutom i den tionde rutan där du kan få tre).
- Strike: Alla tio käglor i första slaget. Rutan får då 10 poäng plus summan av dina nästa två slag.
- Spare: Du slår ner resten av käglorna i andra slaget. Rutan får 10 poäng plus nästa slag.
- Öppen ruta: Du får antalet käglor du slagit ner.
- Tionde rutan: Specialregler. Om du slår strike eller spare får du extra slag för att beräkna bonusen.
Exempel: slår du strike i ruta 1 och sedan 7 och 2 i ruta 2, får ruta 1 10+7+2 = 19 poäng. Spare i ruta 2 (7+3) och sedan 5 i första slaget i ruta 3: ruta 2 får 10+5 = 15 poäng.
Grunderna i PHP för poängberäkning
För att beräkna poängen i PHP behöver vi en array med slagresultat. Varje ruta representeras av ett eller två slag, förutom den tionde som kan ha tre. Enklast är att lagra alla slag i en enda lista och sedan tolka dem.
Vi kommer att skriva en funktion calculateScore($rolls) som tar emot en array med antal käglor per slag (0-10) och returnerar den totala poängen.
Här är ett enkelt exempel på hur du kan strukturera koden:
function calculateScore($rolls) {
$score = 0;
$rollIndex = 0;
for ($frame = 0; $frame < 10; $frame++) {
if ($rolls[$rollIndex] == 10) { // strike
$score += 10 + $rolls[$rollIndex + 1] + $rolls[$rollIndex + 2];
$rollIndex++;
} elseif ($rolls[$rollIndex] + $rolls[$rollIndex + 1] == 10) { // spare
$score += 10 + $rolls[$rollIndex + 2];
$rollIndex += 2;
} else { // öppen ruta
$score += $rolls[$rollIndex] + $rolls[$rollIndex + 1];
$rollIndex += 2;
}
}
return $score;
}
Den här funktionen fungerar för de första nio rutorna och hanterar strike och spare korrekt, men den tar inte hänsyn till den tionde rutans specialregler. Vi fixar det i nästa steg.
Steg-för-steg: Bygg din egen poängräknare
Låt oss bygga en mer komplett lösning som hanterar alla fall.
1. Indataformat
Anta att vi har en array med alla slag, till exempel för en perfekt serie (12 strikes): [10,10,10,10,10,10,10,10,10,10,10,10]. För en vanlig serie med spares och öppna rutor: [10,7,3,9,0,10,0,8,8,2,0,6,10,10,10,8,1] (detta är en godtycklig serie).
2. Implementering av tionde rutan
I den tionde rutan kan du slå upp till tre slag. Poängberäkningen för den tionde rutan är annorlunda: om du slår strike på första slaget får du två extra slag, och summan av alla tre är rutan poäng (ingen extra bonus). Om du slår spare (två slag som ger 10) får du ett extra slag, och rutan poäng är 10 plus det tredje slaget. Annars är det bara summan av de två slagen.
Här är en förbättrad version som hanterar detta:
function calculateBowlingScore($rolls) {
$score = 0;
$rollIndex = 0;
for ($frame = 0; $frame < 10; $frame++) {
if ($frame == 9) { // sista rutan
if ($rolls[$rollIndex] == 10) { // strike
$score += 10 + $rolls[$rollIndex + 1] + $rolls[$rollIndex + 2];
$rollIndex += 3;
} elseif ($rolls[$rollIndex] + $rolls[$rollIndex + 1] == 10) { // spare
$score += 10 + $rolls[$rollIndex + 2];
$rollIndex += 3;
} else {
$score += $rolls[$rollIndex] + $rolls[$rollIndex + 1];
$rollIndex += 2;
}
} else {
if ($rolls[$rollIndex] == 10) { // strike
$score += 10 + $rolls[$rollIndex + 1] + $rolls[$rollIndex + 2];
$rollIndex++;
} elseif ($rolls[$rollIndex] + $rolls[$rollIndex + 1] == 10) { // spare
$score += 10 + $rolls[$rollIndex + 2];
$rollIndex += 2;
} else {
$score += $rolls[$rollIndex] + $rolls[$rollIndex + 1];
$rollIndex += 2;
}
}
}
return $score;
}
Testa med perfekt serie: calculateBowlingScore([10,10,10,10,10,10,10,10,10,10,10,10]) bör ge 300.
3. Hantera kantiga fall
Se till att din array är korrekt – till exempel måste den ha rätt antal element. En strike i ruta 1-9 förbrukar bara ett slag, medan en öppen ruta förbrukar två. Tionde rutan kan ha 2 eller 3 slag. Du kan validera indata, men för enkelhetens skull antar vi att arrayen är giltig.
Vanliga fallgropar och hur du undviker dem
- Index utanför array: När du slår strike i ruta 9 och sedan tittar på
$rolls[$rollIndex+2]måste du se till att det finns tillräckligt med slag. Använd funktioner somarray_key_existseller kontrollera längden. - Felaktig tolkning av tionde rutan: Många nybörjare blandar ihop att den tionde rutan kan ha upp till tre slag, men bonusen fungerar inte som i tidigare rutor. Var noggrann med villkoren.
- Blandning av slag från olika rutor: Håll reda på rullindex. Ett vanligt fel är att hoppa över för många slag vid strike (man ska bara öka med 1, inte 2).
Ett tips är att använda en enkel testdriven utveckling: skriv först tester för kända serier (t.ex. alla strikes, alla spares med 5, blandade) och se till att din funktion ger rätt resultat.
FAQ
Fråga 1: Varför blir poängen 300 vid 12 strikes?
Svar: Varje strike ger 10 poäng plus summan av nästa två slag. Om du slår 12 strikes innebär det att varje strike från ruta 1–9 får 10+10+10=30 poäng. Ruta 10 får 10+10+10=30 eftersom du har tre strikes. Totalt 10*30 = 300.
Fråga 2: Måste jag använda en array eller kan jag räkna poäng i realtid?
Svar: Det går att räkna i realtid medan spelaren slår, men då måste du buffra slag tills du har tillräckligt med information. För enkelhetens skull är det lättast att först samla alla slag och sedan beräkna poängen. I en webbapp kan du spara varje slag i sessionen och beräkna efter varje ruta.
Fråga 3: Hur hanterar man en serie med ofullständiga slag?
Svar: Din funktion bör förvänta sig en fullständig serie. Om du vill hantera pågående spel kan du skicka de slag som hittills gjorts och beräkna poängen för de rutor som är klara. För rutor som inte är klara (t.ex. en strike utan två efterföljande slag) kan du inte beräkna poängen förrän bonusen är känd. Antingen returnerar du poängen hittills eller markerar rutor som ofullständiga.
Nu har du alla verktyg för att bygga en egen poängräknare i PHP. Kom ihåg att testa noga med olika serier. Lycka till med kodandet och nästa gång du bowlar en strike, tänk på att din PHP-funktion redan räknat ut poängen!