Jeopardy - ett inspirerat spel

Bakgrund

Inför ett event vi skulle hålla så byggde jag ihop ett Jeopardy-spel i Javascript. Tanken var att alla var i samma sal och man hade tre personer samlade vid samma tangentbord och varje spelare hade sin tangentbordsknapp att trycka på.

Detta funkade ok i de provspelningar som gjordes, och vi bjöd in till ett större event men sedan kom corona och det blev gravt olämpligt att hålla större sammankomster.

Efter ett tag gjorde jag om så att det fanns en mobilklient för Jeopardy-spelet och en backend som höll reda på spelstatus. Detta funkade bra och vi körde detta några gånger både IRL på kräftskiva och över Teams/Zoon och liknande videomötestjänster. Det är den versionen som beskrivs här.

Spelidé

Om du glömt vad Jeopardy är så är det ett frågespel där man måste formulera sitt svar som en fråga. Det kan låta enkelt, men i entusiasmens hetta glöms det lätt bort.

Spelet har några olika faser:

  1. Spelplan nummer 1
  2. Eventuell spelplan 2 med dubbelt så höga poäng för att hålla spänningen uppe
  3. En final där deltagarna får satsa de poäng de samlat ihop i ett kvitt-eller-dubbelt-moment

Ingående spelverktyg

Huvudspelplanen

Spelledaren har en viktig roll för genomförandet av detta spel. Det är några olika kortkommandon och sekvenser att komma ihåg.

Spelplan

Det är alltid spelaren som senast fått poäng tilldelat till sig som väljer kategor och poängvalör. Spelledaren klickar därefter på vald ruta och börjar läsa upp frågan. När spelledaren har läst hela frågan trycker denne på Enter för att starta nedräkningen. En status-stapel börjar då krympa i frågans nederkant.

Spelplan med öppen fråga

När någon spelare klickat på knappen i sin mobilklient får den första spelaren att trycka meddelandet om att denne är först (de andra får veta att de inte är det), och nedräkningen pausas. Om personen svarar fel, alltså inte kan det rätta svaret ELLER glömmer att formulera det som en fråga, så trycker spelledaren ENTER igen och nedräkningen fortsätter och andra spelare kan svara.

Om tiden rinner ut utan att någon spelare svarat rätt blir frågan röd och ingen får poäng. Spelförare är den spelare som senast fick poäng.

Ett klick på en öppen fråga stänger frågan. Frågan kan även stängas med ESCAPE.

TangentFunktion
1Tilldela aktiv spelare poäng för att denne svarat rätt
0Ångra senaste poängtilldelning
EnterStartar tidnedräkningen när en fråga visas (eller återstartar den efter paus)
EscapeStänger aktiv fråga och återgår till spelbrädet

Final

När spelplanen/spelplanerna är rensad(e) så är det dags för final.

Spelledaren läser upp kategorin som finalfrågan tillhör och spelarnas mobilklienter ändrar utseende så att dessa nu kan satsa poäng utifrån vetskapen om hur många poäng de själva har, kategorn och hur många poäng de andra spelarna har.

När alla spelarna har satsat sina poäng klickar spelledaren igen och läser upp den finalfråga som då visas. Spelarnas spelklienter ändrar ånyo utseende så att de nu kan skriva sitt svar och skicka in detta.

När alla spelare har sänt in sitt svar växlar spelledaren till final-URL:en för att avslöja resultatet.

Finalskärmen

final

Traditionellt börjar man med den spelare som har lägst poäng och spelledaren klickar först på den ljusblå rutan för satsade poäng för denna spelare för att avslöja hur många poäng denne satsat och därefter på spelarens svar. Om svaret är rätt - och formulerat som en fråga - så tilldelas satsade poäng genom ett klick på OK-knappen, annars dras satsade poäng ifrån med No-knappen.

När alla spelare har fått sina svar avslöjade ser man vem som vann.

final med svar

Spelarnas mobilklient

Mobilklient screenshot

Mobilklienten som används av spelarna är väldigt enkel. Första gången man surfar dit får man ange sitt användarnamn och sedan domineras skärmen av en stor knapp. Denna knapp används för att svara på fråga.

Området under knappen är en meddelandeyta där meddelanden visas men tonas bort efter några sekunder.

Den enda övriga funktionaliteten är att man kan byta användarnamn genom att klicka på sitt namn. Spelar-ID kvarstår dock som den korta GUID som skapas vid första användning.

Om spelaren klickar på knappen innan spelledaren har startat nedräkningen så blir spelaren utelåst i någon sekund för att hindra att folk är för trigger-happy.

För finalen kommer mobilklienten att ändra funktion. Först visas en skärm för att välja hur mycket av de poäng man samlat ihop som man vill satsa i finalen, givet att man nu vet finalfrågans kategori och hur mycket även de andra spelarna har tjänat ihop.

final

När spelaren skickat in sitt val av satsade poäng återgår spelklienten till en utgråad vanlig spelklient i väntan på att spelledaren ska ha fått in alla satsade poäng och kan visa själva finalfrågan.

Därefter, när spelledaren visar upp finalfrågan får spelklienten ett nytt formulär med ett fält att skriva sitt svar.

finalsvar

En QR-kod för att enkelt koppla upp mobilklienten

QR-kod till spelklienten

Admin-gränssnittet

För att underlätta debugging och för att kunna hantera mutor, överkomma orättvisor och liknande så finns det ett Admin-gränssnitt för spelet. Det kontrollerar primärt serversidan av spelet genom att tillrättalägga saker i databasen.

Admin-gränssnitt

Man kan alltså styra spelsekvernser, lägga till användare och påverka spelpoäng.

Spelförberedelser

De viktigaste Spelförberedelserna är att rigga en skärm som alla kan se. Det kan vara skärmdelning över videotjänst, en projektor eller en större TV. Det är spelledaren som sköter denna skärm.

Spelledaren ska även gå in i Admin-gränssnittet och resetta databasen med knappen som finns där. Då töms spelare och poäng och allt återställs redo för nytt spel.

En annan viktig spelförberedelse är att förbereda bra frågor. Dessa läggs direkt i HTML-filen på JSON-format:


var cat1 = {
    name: 'Datorns kortkommandon',
    answers: [
        'Spara ett öppet dokument', //Vad är Ctrl+S?
        'Skriva ut på skrivare', //Vad är Ctrl+P?
        'Låsa skrivbordet i Windows', //Vad är Windows+L?
        'Ny slide i PowerPoint', //Vad är Ctrl+M?
        'Linting i Visual Studio' //Vad är Ctrl+K -> Ctrl+D
    ]
};
        

The questions descriptions are the innerHTML of another element. This means you may include HTML of your own, e.g. like this:


var cat6 = {
    name: 'Kända skaldjur',
    answers: [
        '<table><tr><td>Hummern i Lilla sjöjungfrun</td><td><img src="sebastian.png" alt="lobster"></td></tr></table>', //Vem är Sebastian?
        '<table><tr><td>Restaurangägaren i Svampbob fyrkant</td><td><img src="mrcrab.jpg" alt="crab"></td></tr></table>',  //Vem är Mr. Crab/Crusty the Crab/Herr Krabba?
        '<table><tr><td>Snäckskalets pingelpärla</td><td><img src="venus.jpg" alt="painting"></td></tr></table>', //Vem är Venus?
        '<table><tr><td>Charles Darwins sköldpadda som dog 2006</td><td><img src="harriet.jpg" alt="darwin"></td></tr></table>', //Vem är Harriet? Född 1830. Död 2008.
        '<table><tr><td>Surfer-dude i Hitta Nemo</td><td><img src="flyt.jpg" alt="dude"></td></tr></table>' //Vem är Flyt/Crush?
    ]
}
        

Det kan vara värt att notera att själva svaren ligger som kodkommentarer. Dessa är relativt svåråtkomliga under en spelsession så spelledaren bör vara förberedd på att ha memorerat svaren eller ha dessa tillgängliga någon annanstans.

Det är normalt 5 kategorier per spelbräde. Ordningen som dessa kommer i bestäms av ett annat stycke i samma sektion av filen:


//Game board consists of these five categories. Each with five answers.
var gameboard1 = [
    cat1,
    cat2,
    cat6,
    cat4,
    cat5
];

var gameboard2 = [
    cat10,
    cat7,
    cat3,
    cat8,
    cat9
];

var boards = [gameboard1, gameboard2];
        

Man kan välja mellan att ha en eller två spelbräden innan finalen. Vilka bräden som används anges i variabeln boards. Varje spelbräde tar normalt 15-20 minuter att spela. Finalen tar ca. 10 minuter, inklusive avslöjandet av resultaten. Förberedelserna kan ta ca. 10 minuter innan alla har förstått reglerna och fått igång mobilklienten.

Själva finalfrågan ligger också som ren JSON:


var final = {
    category: 'Testnivåer',
    answer: 'Programmerarens tester av enskilda metoder' //Vad enhetstester?
};
        

Länkar

Huvudspelplan
Finalbräde
Spelarklienten
Admin-GUI

Övriga inställningar

Inifrån koden i själva huvudspelplanen kan man sätta några inställningar till:


                //**********************************************
                // S E T T I N G S
                // ------------------
                //The decreasing timer bar under the displayed playbox can be suppressed and the response time can be altered
                //
                let useTimer = true; //Set to false to not include the countdown timer
                let maxPlayerResponseTimeInSeconds = 15; //Alter this for a quicker or slower game, giving the players more time
                let startAmount = 100; //Lowest amount for board
                //
                //**********************************************
                //
                //Media used in this
                const ploppSound = new Audio('data:audio/mpeg;base64,//OEZAAAQU1F//MUZAQAAAEYAAAAAAAAAiwAAAAAqqqq');
                let jeopardyLogoTextScr = 'data:image/png;base64,iVBObsVUBMYAAAAAElFTkSuQmCC';
                let testardyLogoTextScr = 'data:image/png;base64,iVBORw0KGgoAAAANSU8khjXkAAAAASUVORK5CYII=';
                let zingtonLogo = 'z.png';
                var backgroundImageSrc = 'data:image/png;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/gQUtAgpaAClpAf//Z';
                //**********************************************
        
        

Architecture notes

The game client is built with plain HTML, CSS, and Javascript to work with as many devices as possible. It is polling the server side API:s at regular intervals, and pushing information to the API:s over REST.

The game board is also built with plain HTML, CSS, and Javascript. It should(tm) be able to cope with different categories count and question count, but it's not yet proven.

Server side is static content and API:s built with PHP and MySQL. The choice was given by the available services from the platform provider. All games use the same backend. This means only one game at the time can be played. There are no plans of introducing game id:s and storing results.