Initial commit
This commit is contained in:
33
oppgavetekster/oving3/Card.md
Normal file
33
oppgavetekster/oving3/Card.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Innkapsling - Card-oppgave
|
||||
|
||||
Denne oppgaven handler om to klasser for kortspill: `Card` (kort) og `CardDeck` (kortstokk), der den siste inneholder ett eller flere `Card`-objekter.
|
||||
|
||||
I mange sammenhenger vil objekter av en klasse inneholde eller "eie" objekter av andre klasser. Når en klasse er assosiert med én instans av en (annen) klasse er dette en [1-1-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-1-assosiasjoner) og når en klasse er assosiert med flere instanser av en annen klasse er dette en [1-n-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-n-assosiasjoner). I denne oppgaven skal du implementere logikk for en kortstokk som inneholder kort. Nedenfor beskrives begge klassene og metodene 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 en metode 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. Kort nr. 0 er det første kortet i kortstokken.
|
||||
|
||||
Endringsmetode:
|
||||
|
||||
- `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](http://en.wikipedia.org/wiki/Out_shuffle)).
|
||||
|
||||
## Oppgave: Java-kode
|
||||
|
||||
Skriv `Card`- og `CardDeck`-klassene, slik at de har ønsket oppførsel og er skikkelig innkapslet.
|
||||
|
||||
Testkode for denne oppgaven finner du i [encapsulation/CardDeckTest.java](../../src/test/java/encapsulation/CardDeckTest.java) og [encapsulation/CardTest.java](../../src/test/java/encapsulation/CardTest.java).
|
||||
37
oppgavetekster/oving3/CoffeeCup.md
Normal file
37
oppgavetekster/oving3/CoffeeCup.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Debugging - CoffeeCup-oppgave
|
||||
|
||||
Oppgaven handler om feilsøking i en **CoffeeCup**- og en **CoffeeCupProgram**-klasse ved bruk av [debuggeren](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) i Eclipse.
|
||||
|
||||
Et **CoffeeCup**-objekt inneholder kapasitet og nåværende volum av kaffe.
|
||||
|
||||
- Kapasitet må være et ikke-negativt flyttall, som til enhver tid må være større enn nåværende volum av kaffe.
|
||||
- Nåværende volum av kaffe er et ikke-negativt flyttall som til enhver tid må være mindre enn kapasiteten til koppen.
|
||||
|
||||
**CoffeeCup**-klassen har følgende metoder og konstruktører:
|
||||
|
||||
- `void drinkCoffee(double)` og `void fillCoffee(double)`, hvor man henholdsvis drikker og fyller koppen med kaffe. Om man prøver å drikke mer enn det finnes i koppen, eller fyller for mye i koppen blir en `IllegalArgumentException` utløst.
|
||||
- `void increaseCupSize(double)`, som øker størrelsen på koppen. Om man prøver å gjøre koppen mindre skjer ingenting.
|
||||
- `CoffeeCup()`, en konstruktør som setter standard initialverdier til 0.0 kapasitet og 0.0 nåværende kaffe i koppen.
|
||||
- `CoffeeCup(double, double)`, en konstruktør som setter initialverdier til de oppgitte verdiene.
|
||||
- I tillegg har klassen noen private hjelpefunksjoner som man kan identifisere selv.
|
||||
|
||||
**CoffeeCupProgram**-klassen er en hovedprogramklasse som oppretter en instans av **CoffeeCup**, og utfører en sekvens av kall til koppens ulike metoder.
|
||||
|
||||
I denne oppgaven blir en implementasjon av **CoffeeCup** sammen med et hovedprogram utdelt, men i implementasjonen av hovedprogrammet har vi plantet noen feil. Det er to oppgaver som må løses.
|
||||
|
||||
CoffeeCup-koden finner du i [debugging/CoffeeCup.Java](../../src/main/java/debugging/CoffeeCup.java). CoffeeCupProgram finner du i [debugging/CoffeeCupProgram.java](../../src/main/java/debugging/CoffeeCupProgram.java).
|
||||
|
||||
### Leseliste
|
||||
- [Debugging i Eclipse](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) - Debuggeren er et verktøy som brukes til å analysere kjørende kode, noe som kan være svært nyttig når man vil forstå og evt. rette feil i et program.
|
||||
- [Hovedprogramklasser](https://www.ntnu.no/wiki/display/tdt4100/Hovedprogramklasser) - Hovedprogramklasser er klasser som aktiveres når programmer starter opp og som initialiserer og kontrollerer/koordinerer de andre objekter i applikasjonen.
|
||||
- [java.util.Random](https://docs.oracle.com/javase/8/docs/api/java/util/Random.html) - En pseudotilfeldig nummergenerator i Java.
|
||||
|
||||
### Oppgave 1
|
||||
Målet for oppgaven er å finne en feil i funksjonen `part1()` ved hjelp av debuggeren i Eclipse. Kjør hovedprogrammet i debug-modus, og bruk dette til å finne hva kapasiteten og nåværende volum av kaffe er like før programmet utløser et unntak.
|
||||
|
||||
Finn også ut hvilken metode i **CoffeeCup** som utløser unntaket.
|
||||
|
||||
### Oppgave 2
|
||||
Du fant feilen i oppgave 1, bra! Kommentér ut kallet til `part1()` i hovedprogrammet, så slipper vi å ha mer med det å gjøre.
|
||||
|
||||
Du skal nå finne ut hvordan nåverende volum av kaffe endrer seg i `part2()`, før programmet utløser et unntak. Lag en liste over hvilke verdier nivået har. Hvilken metode i **CoffeeCup** utløser et unntak denne gangen? Hvilken type unntak blir utløst?
|
||||
25
oppgavetekster/oving3/Nim.md
Normal file
25
oppgavetekster/oving3/Nim.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Innkapsling - Nim-oppgave
|
||||
|
||||
Denne oppgaven handler om en `Nim`-klasse, som implementerer en variant av spillet [Nim](https://en.wikipedia.org/wiki/Nim).
|
||||
|
||||
Spillet Nim består av **tre** hauger med brikker. To spillere velger på tur én av haugene, og fjerner så mange brikker som ønskelig, men minimum én brikke. Spillet er over når en av haugene er helt tom for brikker.
|
||||
|
||||
`Nim`-klassen har enkel tilstand: En spillomgang består av tre hauger med et antall brikker. `Nim`-klassen må dermed kunne representere hvor mange brikker som er i hver haug, og oppdatere dette ettersom det fjernes brikker. Hvordan dette gjøres er åpent, så lenge det er tilstrekkelig for å oppfylle oppførselen definert for klassen.
|
||||
|
||||
`Nim`-klassen har følgende metoder:
|
||||
|
||||
- `void removePieces(int number, int targetPile)` - fjerner `number` (>= 1) antall brikker fra haugen `targetPile`. `IllegalArgumentException` utløses hvis targetPile eller number er ugyldig. Siden man ikke kan gjøre trekk etter at spillet er over, må `IllegalStateException` utløses dersom metoden kalles etter det.
|
||||
- `boolean isValidMove(int number, int targetPile)` - returnerer `true` dersom argumentene representerer et lovlig trekk, og `false` dersom argumentene ikke ville ført til et lovlig trekk. Her skal man kun sjekke om et trekk er lovlig å utføre, ikke faktisk endre på tilstanden. **PS**: Husk at å flytte når et spill er over ikke er et lovlig trekk.
|
||||
- `boolean isGameOver()` - returnerer `true` dersom en av haugene har 0 brikker.
|
||||
- `int getPile(int targetPile)` - returnerer antall brikker i haugen targetPile.
|
||||
- `String toString()` - returnerer en tekststreng som oppsummerer spillets tilstand
|
||||
|
||||
Haugene skal identifiseres ved tall, altså at gyldige verdier for `targetPile` er 0, 1 og 2.
|
||||
|
||||
`Nim`-klassen skal ha en [konstruktør](https://www.ntnu.no/wiki/display/tdt4100/Klasser+i+java#Klasserijava-constructor) `Nim(int pileSize)` som lar en bestemme hvor mange brikker som skal være i hver haug, og i tillegg en tom konstruktør som initialiserer `Nim`-objektet til å ha 10 brikker i hver haug.
|
||||
|
||||
## Oppgave: Java-kode
|
||||
|
||||
Skriv `Nim`-klassen, slik at den har ønsket oppførsel og er skikkelig innkapslet.
|
||||
|
||||
Testkode for denne oppgaven finner du i [encapsulation/NimTest.java](../../src/test/java/encapsulation/NimTest.java).
|
||||
43
oppgavetekster/oving3/README.md
Normal file
43
oppgavetekster/oving3/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Øving 3: Klasser og testing
|
||||
|
||||
__Øvingsmål__:
|
||||
|
||||
- Lære å lage enkle Java-klasser og -programmer
|
||||
- Lære å bruke debuggeren i Eclipse
|
||||
|
||||
__Øvingskrav__:
|
||||
|
||||
- Kunne tegne enkle klassediagrammer
|
||||
- Kunne deklarere klasser og metoder ihht. oppgavespesifikasjon
|
||||
|
||||
## Dette må du gjøre
|
||||
|
||||
__Del 1: Programmering__
|
||||
|
||||
Velg minst én av oppgavene under. Merk at *Card*-oppgaven bygges videre på i både øving 5 og 6, og kan derfor være lur å gjøre, slik at man har flere oppgaver å velge mellom senere.
|
||||
|
||||
- [Nim](./Nim.md) (Lett)
|
||||
- [Card-oppgave](./Card.md) (Medium)
|
||||
- [RPN-kalkulator](./RPN.md) (Vanskelig)
|
||||
|
||||
Oppgavene for denne øvingen skal du lagre i `ovinger/src/main/java/encapsulation`. Test-filene ligger i `ovinger/src/test/java/encapsulation`.
|
||||
|
||||
__Del 2: Klassediagram__
|
||||
|
||||
Tegn et [klassediagram](https://www.ntnu.no/wiki/display/tdt4100/Klassediagrammer) for oppgaven du velger i del 1. Klassediagrammet kan for eksempel skrives på papir eller tegnes i et valgfritt program. Diagrammet skal demonstrerer på sal, men det er ikke nødvendig å levere det på Blackboard.
|
||||
|
||||
__Del 3: Debugger__
|
||||
|
||||
I tillegg skal en kort oppgave som omhandler bruk av [debuggeren i Eclipse](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) løses. Oppgaven skal demonstreres for en læringsassistent på sal:
|
||||
|
||||
- [CoffeeCup](./CoffeeCup.md) (Lett/Medium)
|
||||
|
||||
Oppgavene er merket med en vanskelighetsgrad relativt til hverandre. Det er en god idè å begynne med de lettere oppgavene dersom du ikke er komfortabel med pensum så langt, men det er anbefalt å prøve seg på de vanskeligere oppgavene om du synes de første oppgavene er uproblematiske. Dersom du allerede føler deg trygg på punktene i øvingskravene kan du forsøke å gå rett på de vanskeligere oppgavene. Du er selvfølgelig velkommen til å løse flere oppgaver enn minstekravet, noe som er lurt med tanke på eksamen og et langt liv som programmerer.
|
||||
|
||||
### Hjelp / mistanke om bugs
|
||||
|
||||
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på Piazza.
|
||||
|
||||
### Godkjenning
|
||||
|
||||
Last opp kildekode på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for en læringsassistent innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.
|
||||
70
oppgavetekster/oving3/RPN.md
Normal file
70
oppgavetekster/oving3/RPN.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Innkapsling - RPN-kalkulator-oppgave
|
||||
|
||||
Oppgaven handler om å lage en RPN-kalkulator (RPN = Reverse Polish Notation). I denne oppgaven kommer du til å ta i bruk en *stack*, og utføre matematiske operasjoner.
|
||||
|
||||
Her er en forklaring av hvordan en RPN-kalkulator fungerer:
|
||||
|
||||
> The RPN calculator differs from a normal calculator in that its syntax is completely different: It uses postfix notation instead of infix notation.
|
||||
>
|
||||
> Reverse polish notation, or postfix notation, is a notation where the operators (+, -, \*, /, ...) appear after the operands (1.0, 3.14, 2.187, 42, …). As an example, consider the expressions `2 – 1` and `9 + 3*4`. In RPN, this would be `2 1 -` and `9 3 4 * +`, as the operator shall appear after the operands. If the last example is confusing, think of it as `9 (3 4 *) +` instead.
|
||||
>
|
||||
> The main advantage of this is notation is that we can avoid parentheses and avoid determining which calculation to perform first. In infix, operator precedence is a problem: In the expression `9 + 3*4`, we first have to multiply, even though the plus operator appears first. In RPN, we simply take the first operator we see and apply it on the last two numbers we've seen, and replace the operator and operands with the result. For the multiplication and addition example:
|
||||
>
|
||||
> `9 3 4 * +` - the first operator we see is *, so we apply that to the two last seen values, 3 and 4, and replace those elements with the result, 12
|
||||
>
|
||||
> `9 12 +` - the next operator we see is +, so we apply that to 9 and 12
|
||||
>
|
||||
> `21` - We are finished, as there are no more operators in the expression
|
||||
>
|
||||
>For the more complex expression `(9 + 7) / (5 – 3)`, this will be written as `9 7 + 5 3 - /` in RPN. Notice how we can avoid parentheses and still calculate what we want without any issues:
|
||||
>
|
||||
> `9 7 + 5 3 - /` - the first operator is +, so we perform `9 + 7` and replace those elements with the result
|
||||
>
|
||||
> `16 5 3 - /` - the next operator is -, so we perform the operation `5 – 3`, as those are the last two elements
|
||||
>
|
||||
> `16 2 /` - we perform the last operation, division:
|
||||
>
|
||||
> `8` - We are done, as there are no more operators left.
|
||||
>
|
||||
> Most RPN calculators have a stack of numbers, giving them control over which numbers to do operations on when they see the next operand. Whenever they see an operand, they push it on the stack. If they see an operator, they pop off the numbers required, perform the operation, and push the result on top of the stack again.
|
||||
>
|
||||
> As an example of how this will work, consider the example `9 3 4 * +` once more. Here, an RPN calculator will first push 9, 3 and 4 on the stack. The stack will now look like this: [9, 3, 4], where 4 is the top of the stack. Then, when the calculator see the operator *, it then pops 4 off the stack, pops 3 off the stack, and pushes 3 * 4 on top of the stack. The stack which now contains [9, 12]. Then, when the RPN calculator sees the operator *, it pops off 12 and 9 off the stack, and performs the operation 9 + 12, and pushes it back on top of the (now empty) stack. The stack will now contain [21].
|
||||
|
||||
Tilstanden i `RPNCalc`-objekter velger du selv, men det er naturlig å bruke en `Stack` eller `ArrayList` med `Double`-objekter.
|
||||
|
||||
`RPNCalc`-klassen skal ha følgende metoder:
|
||||
|
||||
- `void push(double)` - legg argumentet på toppen av stacken.
|
||||
- `double pop()` - returner verdien på toppen av stacken. Verdien skal også fjernes fra stacken. Dersom stacken er tom, så skal `Double.NaN` returneres.
|
||||
- `double peek(int)` - returner verdien i stacken som står på plassen gitt i argumentet, telt fra toppen. Det vil si, `peek(0)` skal returnere verdien på toppen av stacken, `peek(1)` skal returnere verdien nest øverst i stacken osv. Verdien skal ikke fjernes av stacken. Dersom det er for få elementer på stacken, så skal `Double.NaN` returneres.
|
||||
- `int getSize()` - returner antallet elementer i stacken.
|
||||
- `void performOperation(char)` - utfør den angitte operasjonen på de to øverste verdiene i stacken. De to verdiene skal fjernes fra stacken og resultatet skal legges øverst. Bruk eksisterende metoder for å utføre dette der det er mulig. Metoden må støtte '+' (pluss), '-' (minus), '*' (multiplikasjon) og '/' (divisjon), men kan også støtte andre operatorer, f.eks. '~' (swap) for å bytte de to øverste operandene, 'p' eller 'π' (pi) for å legge pi på stacken (bruker ingen operander), '|' (absolutt-verdi, bruker én operand). Prøv å håndtere manglende operander på en måte som gir mening for operasjonen.
|
||||
|
||||
__Del 1 - Tilstandsdiagram__
|
||||
|
||||
Tegn [objekttilstandsdiagram](https://www.ntnu.no/wiki/display/tdt4100/Objekttilstandsdiagrammer) for en tenkt bruk av `RPNCalc`-klassen. Velg selv passende start-tilstand og sekvens av kall.
|
||||
|
||||
__Del 2 - Java-kode__
|
||||
|
||||
Skriv Java-kode for `RPNCalc`-klassen med oppførsel som er beskrevet over. Du skal bruke synlighetsmodifikatorer på metoder og felt for å gjøre innkapslingen "vanntett".
|
||||
|
||||
Lag en [main-metode](https://www.ntnu.no/wiki/display/tdt4100/Main-metoden), hvor du tester sekvenser av operander og operatorer, og kaller henholdsvis `push` og `performOperation`-metodene på et `RPNCalc`-objekt og skriver ut stacken. Test `RPNCalc`-klassen og sjekk at oppførselen stemmer med tilstandsdiagrammet.
|
||||
|
||||
__Del 3 - Teori__
|
||||
|
||||
Til nå har det blitt spesifisert at `peek()` og `pop()`-metodene skal returnere `Double.NaN` hvis stacken er tom. Alternativet er å utløse et unntak.
|
||||
|
||||
Svar på følgende:
|
||||
|
||||
- Hvilken type unntak vil det være naturlig å bruke?
|
||||
- Hvilke fordeler og ulemper ser du for dette alternativet?
|
||||
|
||||
Det er også spesifisert at en skal "håndtere manglende operander på en måte som gir mening for operasjonen". Hvis `+`-operasjonen ble utført på kun én operand, så kan en f.eks. velge å la den manglende operanden være 0.
|
||||
|
||||
Svar på følgende:
|
||||
|
||||
- Hva vil tilsvarende verdi for manglende operand for `*`-operasjonen (multiplikasjon) være? Hva med for `/` (divisjon)?
|
||||
- Hvordan kan du endre (evt. har du endret) grensesnittet for stack-operasjonene for å gjøre implementasjonen av disse enklere?
|
||||
- Også her er et alternativ å utløse unntak. Hva tror du om det?
|
||||
|
||||
Testkode for denne oppgaven finner du i [encapsulation/RPNCalcTest.java](../../src/test/java/encapsulation/RPNCalcTest.java).
|
||||
Reference in New Issue
Block a user