|
Laboration 3 - Sten, sax, påse
Ett grafiskt klientprogram där en användare spelar mot en server
På föreläsning 6 eller 7 visas ett serverprogram som spelar sten, sax,
påse med alla villiga klienter. Koden finns här:
Server4713.java. Uppgiften här är att skriva ett
grafiskt klientprogram som låter en användare spela sten, sax och påse
mot serverprogrammet.
Spelet är känt över hela världen. På webbsidan
Rock, paper, scissors,
kan man bland annat hitta tre gif-bilder att använda i sitt program.
Om servern skulle vara nere eller uppvisa något annat problem så går det
bra att som nödlösning kopiera server-programmet till den egna datorn och
köra det där. Instruktioner finns här:
lokalserver.html
En enkel klient
Börja med att testa en enkel klient utan grafik, som öppnar en förbindelse med
try {
Socket socket=new Socket("u3.csc.kth.se",4713);
BufferedReader in=new BufferedReader
(new InputStreamReader(socket.getInputStream()));
PrintWriter ut=new PrintWriter(socket.getOutputStream());
ut.println("Charlotta"); ut.flush();
System.out.println(in.readLine());
}
Klienten ska sända ett namn (här sänds Charlotta) till den server som
lyssnar på port 4713 och skriva ut det svar den får. Kom ihåg
ut.flush(); annars sänds inte namnet iväg.
Koden ovan behöver kompletteras en hel del för att gå att köra överhuvudtaget
men även för att testa servern.
Bland annat bör man skicka ytterligare några meddelanden till servern
och som svar få "STEN", "SAX" eller "PÅSE". För att avsluta förbindelsen
ska man skicka något som servern läser som null eller
tom sträng. Det fungerar t.ex. med tom sträng (""), Ctrl-D eller Ctrl-Z.
Se till att den enkla klienten fungerar innan ni går vidare och ägnar er
helt åt det grafiska gränssnittet.
Swingkomponenterna
Ditt program kan (men behöver inte) vara en
public class Klient extends JFrame implements ActionListener{
där vänstra halvan av fönstret är din spelplan och högra halvan är datorns
spelplan.
De två halvorna är tillräckligt lika för att kunna representeras av objekt
av samma klass, här kallad Spelplan.
Spelplanen ska innehålla många knappar och rutor så en
LayoutManager är nödvändig.
Det går definitivt att få en tillräckligt snygg layout genom att använda
JPanel med GridLayout i flera nivåer.
Ett alternativ är BoxLayout från swing-paketet, den är lite
svårare men också flexiblare. Med BoxLayout så bör varje
spelplan vara en vertikal Box. Oavsett layoutmanager
så bör varje spelplan innehålla följande:
- Rubrik, en
JLabel med texten Jag: eller Datorn:.
- Meddelande, en
JTextField där det som sänds från
dej och från datorn syns. Först visas hälsningen, därefter det senaste draget,
dvs STEN, SAX eller PÅSE.
- En knapp med en stenbild
- En knapp med en saxbild
- En knapp med en pappersbild
- Resultat, en
JLabel som efter ett tryck visar ETT...,
efter andra trycket TVÅ... och efter tredje VINNER,
OAVGJORT eller FÖRLORAR (förklaras mer i
stycket om Spelet).
- Poäng, en
JTextField som visar t.ex.
Poäng: 7
Det går att använda JLabel för alla de små textfälten ovan men i
vissa sammanhang är det lättare med JTextField när man
måste ha fält som är tomma från början.
En egen klass för Spelplan ska definieras.
Tips för Spelplan med Box och BoxLayout
Spelplan kan vara subklass till Box och i sin
konstruktor anropa super(BoxLayout.Y_AXIS); för att markera
att den är vertikal. Två objekt av den skapas och läggs bredvid varandra i
t.ex. en horisontell box. En av fördelarna med en box är att man kan lägga
in fasta mellanrum mellan komponenterna Om man deklarerat
Box box=Box.createHorizontalBox(); kan man göra så här.
Spelplan jag = new Spelplan("Jag:");
Spelplan du = new Spelplan("Datorn:");
box.add(jag);
box.add(Box.createHorizontalStrut(20)); //Ett mellanrum
box.add(du);
Box-objektet läggs därefter in i JFrame-objektet med metoden add.
Tips för Spelplan med JPanel och GridLayout
Om du är ovan vid Javas grafik kan det vara lika bra att använda
en JPanel med
GridLayout för spelplanerna.
Det går att få riktigt snyggt det också!
Varje spelplan kan delas in i 5 lika stora fält där knapparna
läggs i de tre mittersta. Översta och nedersta fälten får var sin
JPanel som i sin tur delas in
flera fält. Om man lägger in en tom
JPanel så fungerar det som ett
mellanrum. Inte fullt så flexibelt som i en
Box men helt OK.
Om du väljer detta alternativ för spelplanerna så använd även en
JPanel med
GridLayout för det omgivande fönstret,
alltså det fönster där "jag" och "du" läggs in i exemplet ovan.
Spelet
Spelet går till så att användaren trycker på sten, sax och
påse-knapparna och vid tredje trycket läser programmet
av vilken knapp som tryckts på och draget STEN, SAX eller PÅSE registreras.
Det spelar ingen roll vilka knappar man trycker på de två första gångerna
och de knapparna behöver inte markeras med färgskifte men texten "ETT..."
respektive "TVÅ..." ska visas i resultatrutan.
De verkningslösa tryckningarna ska efterlikna att man i det manuella
spelet slår med en knuten hand i luften två gånger (räknar ett, två)
och därefter (på tredje slaget) visar sitt drag.
I samband med användarens tredje tryck ger också datorn sitt drag
(dvs programmet läser av draget från servern).
Programmet
avgör om det är oavgjort eller vem som vunnit samt uppdaterar Resultat-rutan
och Poäng-rutan.
Några tips
- Bilderna kan tillverkas redan i deklarationen
ImageIcon sten=new ImageIcon("rock.gif") och samlas i en array
Icon[] bild={sten,sax,påse}.
- Man kan ha användning för en textarray
String[]text={"STEN","SAX","PÅSE"}.
- I spelplansklassen finns det nog en knapparray. Fastän
det inte står text på knapparna kan man anknyta en text med
knapp[i].setActionCommand(text[i]). Den kan man sedan
få fram i actionPerformed med e.getActionCommand()
(Trevligt, men inte absolut nödvändigt i labben).
- Avgivna drag ska markeras så att den valda knappen ändrar färg
(eller annat utseende). Då kan en metod
public void markera(...) i
spelplansklassen vara lämplig. Någon eller några parametrar behövs
i metoden men det beror ju på hur mycket metoden ska göra (bara markera
färg eller även uppdatera fälten).
- För varje gång användaren avger sitt drag tar programmet emot ett
servermeddelande som skickas till metoden
markera i datorfönstret.
-
Det behövs en global variabel som räknar till tre och sedan återgår till noll.
Varje spelare ska ha en poängvariabel. Var läggs den lämpligen?
- Varje klick som är ett drag skall föregås av två
verkningslösa klick. Klicken räknas och deras enda effekt är att
texterna "ETT..." respektive "TVÅ..." visas i resultatrutan.
- Här ställs inte kravet att hålla strikt på Model-View-Control
(som i förra labben) och göra en modell som kan köras fristående i
terminalfönstret. Skälet är att modellen korrekt representrad är så
försvinnande liten, det mesta handlar här om View och Control som hänger
intimt ihop. Det är dock inte alls fel att göra en egen modell,
särskilt om man tycker att den verkar lite krånglig.
- En knapp som kopplar ner förbindelsen med servern och avslutar
programmet är trevligt att ha men inget krav.
Redovisning och krav på programmet
- Demonstrera SSP-spelet som använder det givna serverprogrammet för
att få fram datorns drag. Spelplanerna ska se ut så som beskrivs ovan.
- Programmet måste bestå av minst två klasser och de två spelplanerna
ska vara objekt av samma klass.
- Vid varje drag skall det synas hur användaren respektive datorn har
spelat genom att knapparna ändrar färg (se tipsen!) och genom att
dragets text skrivs ut i meddelanderutan.
- Efter varje drag visas också vem som vunnit (eller om det är OAVGJORT)
samt aktuell poängställning.
- Ett drag utförs vid var tredje av användarens knapptryckningar.
Första trycket visar "ETT..." i resultatrutan, andra trycket
visar "TVÅ..." och tredje trycket ger draget.
- Logiken i programmet ska vara noga genomtänkt så att det inte blir
onödigt långt och krångligt. T.ex. att ta redo på vem som har vunnit
eller om det var oavgjort kan skrivas med 9 if-satser eller med
bara två. Lösningar utan if är också möjliga.
Kodupprepning skall undvikas!
- Uppdatering av spelplanerna ska ske genom anrop av ett fåtal metoder.
- Även punkterna 1 och 2 från
checklistan ska redovisas.
Som extrauppgift väljes en av följande
Extrauppgift, alternativ 1: Lägg till ljudeffekter!
Kan kräva hörlurar. Det bör vara minst tre olika ljud (spel, vinst, förlust).
Ljudet ska kunna slås av och på interaktivt medan man kör programmet.
Extrauppgift, alternativ 2: Bygg ut det grafiska gränssnittet så
att uppkopplingen till servern styrs därifrån. Låt användaren välja serverdator
och portnummer, antingen genom att det finns några explicita att välja på
eller skriva in namnet (t.ex. "u3.csc.kth.se") och portnumret i
inmatningsfält.
|