Denne oppgaven handler om klasser for kortspill: Card (kort), CardDeck (kortstokk) og CardHand (korthånd), hvorav de to siste inneholder én eller flere Card-objekter.

I mange sammenhenger vil objekter av en klasse inneholde eller "eie" objekter av andre klasser, og de underordnede objektene vil kunne flyttes/overføres mellom de overordnede. Når en klasse er assosiert med én instans av en (annen) klasse er dette en 1-1-assosiasjon og når en klasse er assosiert med flere instanser av en annen klasse er dette en 1-n-assosiasjon. Et eksempel er kortspill, hvor kortene starter i kortstokken, fordeles på korthender og til slutt ender i en kortbunke. Et kort kan bare være ett sted om gangen, og må overføres fra ett sted til et annet, f.eks. fra kortstokk til korthender i utdelingsfasen. I denne oppgaven skal du implementere logikk for kortstokk og korthender, både det å fylle opp kortstokken med kort i starten og overføring av kort til korthender. Nedenfor beskrives hver av klassene og metoden disse skal inneholde.

Card-klassen er en såkalt verdiklasse, som kodes slik at objektene ikke kan endres etter at de er opprettet. Et Card-objekt har en kortfarge, som er en av bokstavene 'S' (for spades), 'H' (for hearts), 'D' (for diamonds) og 'C' (for clubs), og tallverdi, som er et heltall mellom 1 (ess) og 13 (konge). Følgende metoder må implementeres:

  • Card(char, int) - konstruktøren initialiserer kortfarge og tallverdi med henholdsvis første og andre argument. Konstruktøren må utløse unntak av typen IllegalArgumentException hvis en (eller begge) av disse verdiene er ugyldige.
  • getSuit() - returnerer kortfargen som en char, en av 'S', 'H', 'D' eller 'C'.
  • getFace() - returnerer tallverdien som en int mellom 1 og 13 (inklusive)
  • toString() - returnerer en streng som består av <suit><face> e.g. for spar ess skal "S1" returneres.

CardDeck-objekter inneholder initielt et visst antall kort av de fire kortfargene S', 'H', 'D' og 'C'. Klassen inneholder standardmetoder for å lese hvor mange og hvilke kort og to metoder for endre tilstand.

Konstruktør:

  • CardDeck(int n) - fyller kortstokken med de n første kortene av hver kortfarge, totalt n * 4 kort, med spar 1 som første kort (indeks nr. 0), spar 2 som andre (nr. 1), spar 3 som tredje (nr. 2), spar 4 som fjerde (nr. 3), ..., hjerter 1 som fjortende (nr. 13), hjerter 2 som femtende (nr. 4) osv. i.e. først alle spar, så hjerter, så ruter og så kløver, alle i stigende rekkefølge. 

Lesemetoder:

  • getCardCount() - returnerer hvor mange Card-objekter som CardDeck-objektet inneholder
  • getCard(int n) - returnerer kort nr. n eller utløser et IllegalArgumentException hvis n ikke er gyldig

Endringsmetoder:

  • deal(CardHand, int n) - flytter n kort fra kortstokken (CardDeck-objektet) til korthånda (CardHand-objektet, som er første argument), ved å ta ett og ett kort med høyeste gyldige indeks, fjerne det fra CardDeck-objektet og legge det til CardHand-objektet
  • shufflePerfectly() - stokker kortstokken ved å dele den i to like store deler og flette de to delene perfekt, slik at kortet på toppen forblir på toppen og kortet på bunnen forblir på bunnen (se http://en.wikipedia.org/wiki/Out_shuffle)

CardHand-objekter inneholder initielt ingen kort, og klassen inneholder de samme standardmetodene som CardDeck, altså getCardCount() og getCard(int), for å lese hvor mange og hvilke kort den inneholder. I tillegg har den to metoder for å endre tilstand:

  • addCard(Card) - legger argumentet til dette CardHand-objektet
  • play(int n) - returnerer og fjerner kort nr. n (første kort har nr. 0) fra dette CardHand-objektet (som om det ble spilt ut)

 

JExercise-testkode for denne oppgaven finner du her: objectstructures/CardTest.java, objectstructures/CardDeckTest.java og objectstructures/CardHandTest.java. jextest-koden finner du her: objectstructures/Card.jextest, objectstructures/CardDeck.jextest og objectstructures/CardHand.jextest.

.ex for bruk med Exercise-panelet finner du her: Card.ex.


JExercise lar deg sjekke din egen kode vha. forhåndslagde JUnit-tester og JExercise-panelet

Bruk av JExercise:

  1. Sørg for at jexercise-standalone.jar er lagt til i ditt prosjekts Build Path. Dette må gjøres hver gang du oppretter et nytt prosjekt, og det er derfor lurt å gjenbruke samme prosjekt til alle oppgaver.
  2. JExercise-tillegget må være installert. Installer tillegget fra følgende oppdateringsadresse: http://folk.ntnu.no/hal/dev/updatesite.
  3. Åpne JExercise-panelet via Window -> Show View -> Other, og navigere deg fram til JExercise i vinduet som kommer opp, velge det og klikke OK.
  4. Klikke og dra oppgavens testklasse, <oppgavenavn>Test.java fra pakkeoversikten og slippe den i JExercise panelet. 
  5. Testene kan så kjøres ved å dobbeltklikke på testen som ønskes kjørt.

Ved trøbbel, se først om du finner løsningen i Løsninger på trøbbel med JExercise.

Unknown macro: {html}

Twitre gjerne om oppgaven når du er ferdig: <a href="https://twitter.com/share" class="twitter-share-button" data-hashtags="jexercise">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>

  • No labels

10 Comments

  1. Unknown User (magneskj)

    Lignende problem her som i Partner oppgaven. Hverken com.google.common.base.Objects eller org.eclipse.xtext.xbase.lib.Pair lar seg importeres.

  2. Unknown User (tobiaas)

    Hos meg hjalp det å fjerne forrige versjon av JExercise stand-alonen, og kun ha den på 3.5 mb liggende

  3. Unknown User (hal)

    Ja, man trenger nyeste jexercise-standalone.jar

    Den er litt stor, fordi den inneholder hele guava-biblioteket fra Google, som nok kan trimmes kraftig, men det har jeg ikke hatt tid til... Greia er at jeg nå skriver testene i et hjemmesnekret test-språk (såvidt vist på forelesning) og det bygger på et system som igjen bruker guava, og da må det være med.

    1. Unknown User (magneskj)

      Et stort problem er at enhets-testene nå er... kryptiske.

      Hvordan skal man kunne vite hva som har gått feil når alt koden sier er ""it == null -> null -> #[]; failed"", og at dette da er et resultat av hva enn som har skjedd i:

      Pair<Pair<? extends Object,? extends Object>,List<? extends Object>> _mappedTo_1 = Pair.<Pair<? extends Object,? extends Object>, List<? extends Object>>of(_mappedTo, Collections.<Object>unmodifiableList(Lists.<Object>newArrayList()));

  4. Unknown User (hal)

    Nå i begynnelsen prøver jeg meg litt frem, og bruker ulike "features" i det underliggende språket. Kanskje overdriver jeg litt, men målet er en forbedring på tre måter:

    1) Originalkoden for testene er ment å ligne på objekttilstandsdiagrammene, og skal være lettere å lese enn junit-tester, selv om notasjonen vil være uvant. Denne har jeg tenkt å publisere med oppgavene, så en ser hvilke sekvenser av kall som testes. Du kan godt ta en titt, sjekk i repoet i tests-mappa, jextest-koden for Account.java heter Account.jextest.

    2) Selv om den genererte koden er vanskelig å lese, så skal meldingene som kommer ved feil, altså String-argumentet til assert-kallene, gi mer informasjon. Men når jeg overdriver bruken av spesialnotasjonen -> og ==, så blir det nok forvirrende.

    3) Det skal være lettere og raskere å skrive tester, så vi får lager flere og bedre oppgaver.

    Til nå har fokuset vært å få definert språket og prøve det ut, men fra nå og utover blir det å gjøre testene enklere å skrive for assistentene og lese for studentene.

    1. Unknown User (magneskj)

      Så lenge det blir mer leselig så er jeg godt fornøyd.

      For øyeblikket er jeg relativt sikker på at det er noe feil med testene til Person, siden den melder at konstruktøren ikke fungerer som den skal, selv om den i mine tester funker knirkefritt. Men siden jeg ikke får til å lese koden, er det desverre ikke noe jeg kan bekrefte.

      Skal ta å se på originalkoden.

    2. Unknown User (magneskj)

      Det ser ut som koden er oppdatert, så nå sier den konstruktøren funker. Vet ikke hva du forandra, men takk (smile)

  5. Unknown User (kasperr)

    Synes verden burde innse at Hjerte, Spar, Kløver og Ruter ikke er en farge men en type. 

    1. Unknown User (magneskj)

      Koden innser ihvertfall det, siden den bruker order "suit".

  6. Unknown User (njordb)