Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Expand
titleDel 2 - Håndtering av poeng med DiceScore-klassen og DiceScorer-grensesnittet
Expand
titleIntroduksjon til del 2

Denne deloppgaven handler om representasjon av poeng og poengberegning basert på et sett terningverdier. Felles for mange terningspill er at man kaster terninger og så finner ut hvor mange poeng en får basert på terningverdiene. Visse kombinasjoner gir mer eller mindre poeng, og noen gir ingen. I Yatzy har en mange poenggivende kombinasjoner, f.eks. ett par (to like), to par, tre og fire like, liten (1-5) og stor (2-6) straight, hus (ett par og tre like) og Yatzy (fem like), og poengene en får er stort sett summen av terningverdiene som inngår i kombinasjonen. I Farkle er det andre regler, og her begrenser vi oss til å implementere tre regler (se nedenfor).

DiceScore-klassen innføres (se kode nedenfor) for å knytte poeng til et sett poenggivende terninger. Et DiceScore-objekt har data om:

  • Dice-objektet med de poenggivende terningverdiene
  • Poengene selv

Eksempel:

Et Dice-objekt representerer terningverdiene 1, 2, 2, 2, 3, og en får 200 poeng for de tre toerne. Dette representeres av et DiceScore-objekt med:

  • et (nytt) Dice-objekt som representerer 2, 2, 2, (altså de som gir poeng) og
  • tallet 200 (poengene selv)

 

Code Block
/**
* Represents the score given to a set of die values
*/
public class DiceScore {
 
    ??? fields
 
    /**
    * Initialises a DiceScore object with the provided data
    * @param scoringDice the Dice object containing
    * only the die values contibuting to the score
    * @param score the score itself
    */
    public DiceScore(Dice scoringDice, int score) {
        ???
    }
 
    ??? methods
}

Selve beregningen av poeng, og dermed opprettelsen av DiceScore-objekter, gjøres av implementasjoner av DiceScorer-grensesnittet. DiceScorer-grensesnittet representerer altså en poengregel generelt, og det er én implementasjonsklasse for hver (type) regel. DiceScorer-grensesnittet har kun én metode, getScore, som tar inn et Dice-objekt med alle terningverdiene som skal vurderes samlet og returnerer et nytt DiceScore-objekt med poengene en får og de av terningene som ga poeng, som beskrevet over.

Code Block
/**
* Interface for scoring rules, i.e.
* logic for computing a score for a subset of dice in a Dice
*/
public interface DiceScorer {
 
    /**
    * Computes a score for (a subset of) the dice in the Dice argument.
    * The returned DiceScore object stores a Dice object
    * with those die values that contributed to the score and
    * of course the score itself.
    * @param dice
    * @return The result of applying the rule to the provided Dice, or
    * null of the rule doesn't apply.
    */
    DiceScore getScore(Dice dice);
}

Vi begrenser oss som nevnt til tre poengregler, representert ved tre DiceScorer-implementasjoner:

  • SingleValue - gir poeng for enkeltvise enere og -femmere
  • Straight- gir poeng når alle terningverdiene utgjør en serie
  • Nothing- gir poeng når en slår minst et visst antall terninger og de andre reglene ikke gir poeng!
Oppgave a) - DiceScore-klassen (6 poeng)

Skriv ferdig DiceScore-klassen, med egnede felt, konstruktørkode og tilgangsmetoder, med utgangspunkt at DiceScore-objekter ikke skal kunne endres etter at de er opprettet.

Expand
titleLF

Rett frem koding av verdi-klasse.

Code Block
public class DiceScore {

	private final Dice dice;
	private final int score;

	public DiceScore(Dice dice, int score) {
		this.dice = dice;
		this.score = score;
	}

	public Dice getDice() {
		return dice;
	}

	public int getScore() {
		return score;
	}
}

Vanlige feil/svakheter:

 

Oppgave b) - SingleValue-klassen (6 poeng)

Skriv kode for klassen SingleValue(enkeltverdi), som implementerer DiceScorermed følgende logikk:

For et Dice-argument som ikke inneholder den spesifikke verdien returneres null. Ellers returneres et (nytt) DiceScore-objekt med riktige verdier satt. 

Merk at klassen bare gir poeng for én av den angitte verdien, selv om Dice-objektet inneholder flere av denne verdien.

Eksempel:

Et SingleValue-objekt opprettet med new SingleValue(5, 50), vil gi 50 poeng for et Diceobjekt med én eller flere femmere. DiceScore-objektet som returneres skal inneholde et Dice-objekt med bare én femmer og (poeng)tallet 50.

Code Block
/**
* Implementation of DiceScorer that gives a specific score til a specific die value.
* In Farkle it is used for giving 50 to fives and 100 to ones.
*/
public class SingleValue implements DiceScorer {
 
    ???
 
    /**
    * Initializes this SingleValue object with the (die) value and the corresponding score.
    * In Farkle you will typically create two of these, with
    * new SingleValue(5, 50) and new SingleValue(1, 100)
    * @param value
    * @param score
    */
    public SingleValue(int value, int score) {
        ???
    }
 
    /**
    * Looks for at least one of the specific value and
    * if found, returns a DiceScore object with a Dice object
    * with the value contributing to the score and
    * the corresponding score.
    */
    @Override
    public DiceScore getScore(Dice dice) {
        ???
    }
}
Expand
titleLF

Her skal det bare sjekkes om Dice-argumentet har minst én av den aktuelle verdien. I så fall returneres et DiceScore-objekt med et Dice-objekt med denne ene verdien og de aktuelle poengene. Det er strengt tatt galt å regne med alle terningene av den aktuelle verdien og gange opp poengene, men det er vi ikke så nøye på. Men da må selvsagt også Dice-objektet ha tilsvarende mange av den verdien.

Code Block
public class SingleValue implements DiceScorer {


	private final int score;
	private final int value;

	public SingleValue(final int value, final int score) {
		this.score = score;
		this.value = value;
	}

	@Override
	public DiceScore getScore(final Dice dice) {
		if (dice.getValueCount(value) > 0) {
			return new DiceScore(new Dice(Arrays.asList(value)), score);
		}
		return null;
	}
}

Vanlige feil/svakheter:

 

Oppgave c) - Straight-klassen (8 poeng)

Skriv kode for klassen Straight(alle terningene utgjør en serie), som implementerer DiceScorermed følgende logikk:

For et Dice-argument uten straightreturneres null. Ellers returneres et (nytt) DiceScore-objekt med riktige verdier satt. Poengene som gis er en spesifikk verdi (konstant) som settes når Straight-objektet opprettes.

Merk at koden skal virke selv om det er (mange) færre eller flere terninger enn mulige terningverdier (1-6). Et Dice-objekt med bare én terningverdi vil f.eks. alltid gi straight, mens et Dice-objekt med flere enn 6 terningverdier aldri kan gi straight.

Code Block
/**
* Implementation of DiceScorer that gives a specific score til a so-called straight,
* which is when all values give a series of consecutive values, e.g. 1, 2, 3.
* All the die values must be used, so with six dice, the only possibility is 1, 2, 3, 4, 5, 6.
* With five dice, there are two possibilities, 1, 2, 3, 4, 5 and 2, 3, 4, 5, 6.
*/
public class Straight implements DiceScorer {
 
    ???
 
    /**
    * Initializes this Straight object with the specific score.
    * @param score
    */
    public Straight(int score) {
        ???
    }
 
    /**
    * Checks that all die values in the provided Dice form a series of consecutive values.
    * If this is the case returns a DiceScore object with a Dice with
    * the die values contributing to the score (necessarily all of them) and
    * the corresponding score.
    */
    @Override
    public DiceScore getScore(Dice dice) {
        ???
    }
}
Expand
titleLF

Denne er nok litt kinkig, en må skjønne at en straight er en sammenhengende serie 1-er-tellere av lengde tilsvarende antall terninger i Dice-argumentet. Det kan altså være 0-ere før og etter 1-erne, så en må spole seg over evt. 0-ere og frem til den første 1-ern og så over 1-erne og frem til en 0. Hvis antall 1-ere man har avgrenset tilsvarer antall terninger i Dice-argumentet, så har man en straight. Her har vi brukt getValueCount-metoden, siden valueCounters-feltet ikke nødvendigvis er synlig.

Code Block
 public class Straight implements DiceScorer {

	private final int score;
	public Straight(int score) {
		this.score = score;
	}

	@Override
	public DiceScore getScore(final Dice dice) {
		int dieCount = dice.getDieCount();
		int start = 1;
		// find start of series
		while (start <= 6) {
			int count = dice.getValueCount(start);
			if (count > 1) {
				return null;
			} else if (count == 1) {
				break;
			}
			start = start + 1;
		}

		// find end of series
		int end = start + 1;
		while (end <= 6) {
			int count = dice.getValueCount(end);
			if (count > 1) {
				return null;
			} else if (count == 0) {
				break;
			}
			end = end + 1;
		}
        // check if the number of ones is wrong
		if (end - start != dieCount) {
			return null;
		}
		return new DiceScore(dice, score);
	}
}
Oppgave d) - Nothing-klassen (8 poeng)

Skriv kode for klassen Nothing, som implementerer DiceScorer med følgende logikk:

Et spesifikt antall poeng gis hvis ingen (andre) poengregler gir poeng. De andre reglene representeres av et sett DiceScore-objekter som gis inn når Nothing-objektet opprettes. Dette gjør at Nothing-klassen ikke trenger å duplisere logikk som er spesifikke for andre regler. Bestem selv typen til diceScorers-argumentet som gis inn.

Merk at denne regelen bare gjelder hvis Dice-argumentet til getScore-metoden inneholder minst et visst antall terninger, typisk like mange som brukes i spillet. Dette minsteantallet gis også inn ved opprettelse av Nothing-objektet.

Code Block
/**
* Implementation of DiceScorer that gives a specific score
* when no other DiceScore object applies.
* Requires that a certain number of dice have been thrown.
*/
public class Nothing implements DiceScorer {
 
    ??? fields
 
    /**
    * Initializes this Nothing object with the minimum required number of dice,
     * the specific score given and the other DiceScorer objects.
    * @param numDice the min. number of dice required for this rule to apply
    * @param score the specific score to give
    * @param diceScorers the (other) rules to check
    */
    public Nothing(int numDice, int score, ??? diceScorers) {
        ???
   }
 
    /**
    * Checks that no (other) DiceScore object apply,
    * in case a specific score is given.
    */
    @Override
    public DiceScore getScore(Dice dice) {
        ???
    }
}
Expand
titleLF

Her må en skjønne hvordan Nothing skal bruke (andre) instanser av DiceScorer til å gjøre sin jobb. Her bruker vi ...-notasjonen, altså varargs som tilsvarer DiceScorer[], men det er greit å bruke andre typer som en kan iterere over, f.eks. Collection eller List.

Code Block
public class Nothing implements DiceScorer {

	private final int score;
	private final int numDice;
	private final DiceScorer[] scorers;

	public NothingScorer(final int numDice, final int score, final DiceScorer... diceScorers) {
		this.score = score;
		this.numDice = numDice;
		this.scorers = diceScorers;
	}

	@Override
	public DiceScore getScore(final Dice dice) {
		if (dice.getDieCount() >= numDice) {
			for (DiceScorer diceScorer : scorers) {
				if (diceScorer.getScore(dice) != null) {
					return null;
				}
			}
		}
		return new DiceScore(dice, getScore());
	}
}
Oppgave e) - Mer om Nothing-klassen (4 poeng)

Hva kalles implementasjonsteknikken som det legges opp til at Nothingskal bruke? Begrunn svaret, f.eks. ved å forklare (kort) hva som er karakteristisk for denne teknikken.

Expand
titleLF

Dette er delegeringsteknikken i praksis, hvor en instans av (en implementasjon av) et grensesnitt bruker en eller flere andre instanser av (implementasjoner av) samme grensesnitt, til å gjøre jobben.

Oppgave f) - DiceScorer-deklarasjon (4 poeng)

Når en lager en instans av et DiceScorer-objekt og lagrer (referansen til) det i en variabel, så kreves det at variablen er deklarert med en egnet type. Anta at en har følgende deklarasjon med initialisering:

??? aSingleValueObject = new SingleValue(1, 100);

Hvilke (tre) mulige typer er det lov å skrive der det står ???, hva er avgjørende for valget og hva vil man typisk bruke?

Expand
titleLF

Regelen er at typen på venstre side på være lik eller en supertype av typen på høyre side. Dermed kan en bruke SingleValue selv, DiceScorer-grensesnittet som den implementerer, og Object, som er superklassen til alle klasser.

Det som avgjør valget er hvilke metoder man ønsker å (kunne) bruke. Dersom man ikke trenger metodene som er spesifikke for en subtype, så velger man supertypen. Her er det naturlig å velge DiceScorer, siden SingleValue uansett ikke har andre metoder som kan være relevante å (ønske å) bruke. Hvis en bare skal bruke Object-metoder, som toString og equals, så kan en velge Object, men det er sjeldent bare Object-metodene er relevante.

Oppgave g) - Arv med AbstractScorer (6 poeng)

De tre implementasjonene av DiceScorer(SingleValueStraight og Nothing) har én ting felles. Forklar med tekst og/eller kode hvordan du vil utforme en felles superklasse (f.eks. kalt AbstractScorer) for disse tre, og hvordan de tre implementasjonene vil måtte endres for å fungere som subklasser.

Expand
titleLF

Det disse tre implementasjonene har felles er score-verdien, så denne kan legges i den abstrakte AbstractScorer-klassen, initialiseres ved å kalle super(score) øverst i subklasse-konstruktørene og leses med getScore():

Code Block
public abstract class AbstractScorer implements DiceScorer {

	private final int score;

	protected AbstractScorer(int score) {
		this.score = score;
	}

	protected int getScore() {
		return score;
	}
}
 
public class SingleValue extends AbstractScorer {

	private final int value;

	public SingleValue(int value, int score) {
		super(score);
		this.value = value;
	}
}


Expand
titleDel 3 - Diverse
Oppgave a) - Iterasjon (6 poeng)

Du ønsker å skrive ut (med System.out.print(...)) alle terningverdiene som et Dice-objekt representerer, men oppdager at den ikke har en egen toString()-metode som kan brukes. Skriv vanlig iterativ løkkekode som skriver ut alle terningverdiene til et Dice-objekt med mellomrom mellom (det gjør ikke noe om det kommer et ekstra mellomrom bakerst):

Dice dice = new Dice(...);

??? Hva skal stå her for å få skrevet ut alle terningverdiene i dice?

 

Skriv kode som har samme effekt, men som utnytter et funksjonelt grensesnitt (se ressurs med Java-API) og Java 8 sin lambda-syntaks:

dice. ??? Hva skal stå her for å få skrevet ut alle terningverdiene i dice?

 

Expand
titleLF

Siden Dice implementerer Iterable kan en bruke en vanlig foreach-løkke:

Code Block
Dice dice = new Dice(...);
for (int dieValue : dice) {
	System.out.println(dieValue + " ");
}
 
// eller med funksjonell stil:

Iterable har også en forEach-metode som tar inn en Consumer, og da kan en gjøre det samme med en én-linjer.

Code Block
Dice dice = new Dice(...);
dice.forEach(dieValue -> { System.out.println(dieValue + " "); });
Oppgave b) - Testing av Dice-klassen (6 poeng)

Skriv en eller flere test-metoder for Dice sin contains-metode. Tenk spesielt på å teste grensetilfeller, som det kan tenkes ikke håndteres riktig! 

code
Expand
titleLF

 

Vanlige feil/svakheter:

 

Oppgave c) - Diagramtyper (4 poeng)

Hva er forskjellen (hensikt og innhold) mellom objektdiagrammer og objekttilstandsdiagrammer?

Expand
titleLF

 

Vanlige feil/svakheter:

 

Oppgave d) - Observerbarhet (6 poeng)

Hva er hensikten med observert-observatør-teknikken? Hva vil det si at et objekt er observerbart?

Du blir bedt om å gjøre Dice-objekter observerbare. Forklar med tekst og evt. kode hva du vil gjøre for å møte dette kravet.

Expand
titleLF

 

Vanlige feil/svakheter:

 

Det kan være flere typer grensetilfeller, men her er det mest relevant å sjekke med like Dice-objekter og med tomme Dice-objekter, i tillegg til mer "vanlige" tilfeller. Her testes det bl.a. at alle Dice-objekter, inkl. et tomt Dice-objekt, inneholder et likt Dice-objekt og et tomt Dice-objekt.

Code Block
@Test
public void testContains() {
	assertFalse(new Dice(Arrays.asList(1, 2)).contains(new Dice(Arrays.asList(1, 2, 3))));
	assertTrue(new Dice(Arrays.asList(1, 2)).contains(new Dice(Arrays.asList(1, 2))));
	assertTrue(new Dice(Arrays.asList(1, 2)).contains(new Dice(Arrays.asList(1))));
	assertTrue(new Dice(Arrays.asList(1, 2)).contains(new Dice(Arrays.asList())));
 
	assertFalse(new Dice(Arrays.asList(1)).contains(new Dice(Arrays.asList(1, 2))));
	assertTrue(new Dice(Arrays.asList(1)).contains(new Dice(Arrays.asList(1))));
	assertTrue(new Dice(Arrays.asList(1)).contains(new Dice(Arrays.asList())));
	assertTrue(new Dice(Arrays.asList()).contains(new Dice(Arrays.asList())));

	assertFalse(new Dice(Arrays.asList()).contains(new Dice(Arrays.asList(1))));
}

Vanlige feil/svakheter:

 

Oppgave c) - Diagramtyper (4 poeng)

Hva er forskjellen (hensikt og innhold) mellom objektdiagrammer og objekttilstandsdiagrammer?

Expand
titleLF

Et objektdiagram viser oppbygning av og koblinger mellom objekter/instanser, og brukes for å illustrere tilstanden til (eller en mulig tilstand til) et program. Et objekttilstandsdiagram viser hvordan slike strukturer endres over tid, ved kall av metoder (typisk endringsmetoder), og brukes til å illustrere (mulig) objektoppførsel og utviklingen av tilstanden til et program.

Vanlige feil/svakheter:

 

Oppgave d) - Observerbarhet (6 poeng)

Hva er hensikten med observert-observatør-teknikken? Hva vil det si at et objekt er observerbart?

Du blir bedt om å gjøre Dice-objekter observerbare. Forklar med tekst og evt. kode hva du vil gjøre for å møte dette kravet.

Expand
titleLF

Observert-observatør-teknikken brukes til å følge med på hvordan tilstanden til objekter endres over tid, typisk for å sikre konsistens med andre objekter, f.eks. et GUI med "indre" objekter. Et objekt er observerbart dersom en kan lese ut alle relevant tilstand og en kan få beskjed (lytte på hendelser) om når og hvordan denne tilstanden endres.

Det siste spørsmålet er et lurespørsmål: Dice er allerede observerbar! Siden tilstanden ikke kan endres, så trenger en ikke å støtte lyttere. Hvis tilstanden kunne endres, så måtte man 1) definert et lyttergrensesnitt, 2) hatt metoder for å administrere (registrere og avregistrere) lyttere, 3) hatt metode(r) for å sende ut varsler om tilstandsendringer og 4) kalt disse metodene i alle metoder som faktisk endrer tilstanden.

Vanlige feil/svakheter:

 

Expand
titleDel 4 - JavaFX og FXML

Du skal lage en liten JavaFX-app for å teste DiceScorer-implementasjonene dine, altså SingleValue-, Straight- og Nothing-klassene. Følgende oppførsel skal støttes:

  • Brukeren skal kunne fylle inn et sett terningverdier i et tekstfelt (TextField). Mellomrom brukes som skilletegn.
  • For hver DiceScorer-implementasjon er det en knapp og når den trykkes, kjøres getScore-metoden til en tilsvarende DiceScorer-instans, med de angitt terningverdiene som argument.
  • Innholdet i DiceScorer-objektet som returneres, skal vises som tekst (Label). Hvis null returneres skal begge tekstene settes til en tom String.

Illustrasjonen for oppgaven viser resultatet etter at knappen tilsvarende Straight er trykket.

Image Added

Følgende FXML er skrevet for appen:

Code Block
<VBoxxmlns:fx="http://javafx.com/fxml/1"
    fx:controller="kont2018.farkle.fx.DiceScorerController">
    <HBox>
        <Labeltext="Die values: "/>
        <!--  text field for inputing the die values -->
        <TextFieldfx:id="dieValuesInput"/>
    </HBox>
    <HBox>
        <ButtononAction="#testSingleValue" text="Test SingleValue"/>
        <ButtononAction="#testStraight" text="Test Straight"/>
        <ButtononAction="#testNothing" text="Test Nothing"/>
    </HBox>
    <HBox>
        <Labeltext="Points: "/>
        <!--  label for outputing the score -->
        <Labelfx:id="scoreOutput" text=""/>
    </HBox>
    
Expand
titleDel 4 - JavaFX og FXML

Du skal lage en liten JavaFX-app for å teste DiceScorer-implementasjonene dine, altså SingleValue-, Straight- og Nothing-klassene. Følgende oppførsel skal støttes:

  • Brukeren skal kunne fylle inn et sett terningverdier i et tekstfelt (TextField). Mellomrom brukes som skilletegn.
  • For hver DiceScorer-implementasjon er det en knapp og når den trykkes, kjøres getScore-metoden til en tilsvarende DiceScorer-instans, med de angitt terningverdiene som argument.
  • Innholdet i DiceScorer-objektet som returneres, skal vises som tekst (Label). Hvis null returneres skal begge tekstene settes til en tom String.

Illustrasjonen for oppgaven viser resultatet etter at knappen tilsvarende Straight er trykket.

Image Removed

Følgende FXML er skrevet for appen:

Code Block
<VBoxxmlns:fx="http://javafx.com/fxml/1"
    fx:controller="kont2018.farkle.fx.DiceScorerController">
    <HBox>
        <Labeltext="DieFor values: "/>
        <!--  text fieldlabel for inputingoutputing the scoring die values -->
        <TextFieldfx<Labelfx:id="dieValuesInput"diceOutput" text=""/>
    </HBox>
    <HBox>
        <ButtononAction="#testSingleValue" text="Test SingleValue"/></VBox>

Skriv en JavaFX-kontroller som implementerer ønsket oppførsel, basert på kodeskjelettet nedenfor. Den skal passe til den oppgitte FXML-en og bruke klasser og metoder beskrevet tidligere i oppgavesettet. Du kan anta at Dice har en passende toString()-metode.

Code Block
public class DiceScorerController {
 
    private DiceScorer singleValue,  <ButtononAction="#testStraight" text="Test Straight"/>straight, nothing;
 
    @FXML
    <ButtononAction="#testNothing" text="Test Nothing"/>
    </HBox>public void initialize() {
    <HBox>
    ??? initialize   <Labeltext="Points: "/>DiceScorer instances
        <!--}
 
  label for outputing@FXML theprivate score -->TextField dieValuesInput;
    @FXML private Label  <Labelfx:id="scoreOutput" text=""/>scoreOutput;
    </HBox>
@FXML private Label diceOutput;
 <HBox>
    // helper method for parsing <Labeltext="Fordie values: "/>input
    private Dice getDiceInput()  <!--{
     label for outputing theCollection<Integer> scoringdieValues die= values -->new ArrayList<>();
        <Labelfx:id="diceOutput" text=""/>
    </HBox>
</VBox>

Skriv en JavaFX-kontroller som implementerer ønsket oppførsel, basert på kodeskjelettet nedenfor. Den skal passe til den oppgitte FXML-en og bruke klasser og metoder beskrevet tidligere i oppgavesettet. Du kan anta at Dice har en passende toString()-metode.

Code Block
public class DiceScorerController {
 
    private DiceScorer singleValue, straight, nothing;
 
    @FXMLfor (String dieValue : dieValuesInput.getText().split(" ")) {
            ??? parse and add die value
    public void initialize()  {}
        ??? initializereturn new DiceScorerDice instances
    }
 
    @FXML private TextField dieValuesInput;
// helper method for 
    private @FXMLvoid private Label scoreOutput;
runDiceScorer(DiceScorer scorer) {
     @FXML  private Label diceOutput;
 
    // helper method for parsing die values input
    private Dice getDiceInput() {
??? get DiceScore object by calling scorer's getScore method
        if (score != null) {
          Collection<Integer> dieValues = new ArrayList<>();  ??? show output
        } else {
        for (String dieValue : dieValuesInput.getText().split(" ")) { ??? show output
        }
    ??? parse and add die value}
 
    @FXML
    public void testSingleValue()  }{
        ??? returnuse newSingleValue Dice instancesimplementation
    }
 
    // helper method for @FXML
    privatepublic void runDiceScorertestStraight(DiceScorer scorer) {
        ??? get DiceScore object by calling scorer's getScore method
 use Straight implementation
    }
 
    @FXML
    public void testNothing() {
        ??? use Nothing ifimplementation
 (score != null) {
            ??? show output
        } else {
            ??? show output
        }
    }
 
    @FXML
    public void testSingleValue() {
        ??? use SingleValue implementation
    }
 
    @FXML
    public void testStraight() {
        ??? use Straight implementation
    }
 
    @FXML
    public void testNothing() {
        ??? use Nothing implementation
    }
}

Hvis det er detaljer du er usikker på, så forklar med tekstkommentarer i koden.

}
}

Hvis det er detaljer du er usikker på, så forklar med tekstkommentarer i koden.

Expand
titleLF

Vesentlig poeng her er:

  • opprettelse av de tre typene DiceScorer i initialize-metoden, Nothing med de to andre som argument(er)
  • bruk av getDiceInput for å beregne DiceScore-objektet
  • setting av teksten til Label-objektene som brukes til feedback til brukeren
  • bruk av runDiceScorer i metodene som kalles ved trykke av knappene

 

Code Block
public class DiceScorerController {

	private DiceScorer singleValue, straight, nothing;

	@FXML
	public void initialize() {
		singleValue = new SingleValue(1, 100);
		straight = new Straight(500);
		nothing = new Nothing(5, 1000, singleValue, straight);
	}

	@FXML
	private TextField dieValuesInput;

	@FXML
	private Label scoreOutput;

	@FXML
	private Label diceOutput;

	private Dice getDiceInput() {
		Collection<Integer> dieValues = new ArrayList<>();
		for (String dieValue : dieValuesInput.getText().split(" ")) {
			dieValues.add(Integer.valueOf(dieValue));
		}
		return new Dice(dieValues);
	}

	private void runDiceScorer(final DiceScorer scorer) {
		DiceScore score = scorer.getScore(getDiceInput());
		if (score != null) {
			scoreOutput.setText(String.valueOf(score.getScore()));
			String dieValues = "";
			for (final int dieValue : score.getDice()) {
				dieValues += dieValue + " ";
			}
			diceOutput.setText(dieValues);
		} else {
			scoreOutput.setText("");
			diceOutput.setText("");
		}
	}

	@FXML
	public void testSingleValue() {
		runDiceScorer(singleValue);
	}

	@FXML
	public void testStraight() {
		runDiceScorer(straight);
	}

	@FXML
	public void testNothing() {
		runDiceScorer(nothing);
	}
}
Expand
titleLF

 

 

Code Block
public class DiceController {
 
   @FXML
   private TextField dieCountInput;
 
   @FXML
   private Label diceOutput;
 
   @FXML
   public void handleThrowDice() {
      Dice dice = new Dice(Integer.valueOf(dieCountInput.getText()));
      computeFarkleScore(dice); // var jo oppgitt
      diceOutput.setText(dice.toString());
   }
}