Created
February 18, 2016 19:22
-
-
Save DavidIAm/e535b2795e0cf7400cf1 to your computer and use it in GitHub Desktop.
Yatzy Kata for your review
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage; | |
// This enum represents the sides on a six sided die. | |
// A die face can only be one of these six values. | |
// Not five. | |
// Not seven. | |
// Eight is right out. | |
public enum Face { | |
ONE, TWO, THREE, FOUR, FIVE, SIX; | |
public Integer value() { | |
return this.ordinal() + 1; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage; | |
// This is a list of faces. It is very simple | |
// It is probably overkill but I was exploring how to create a type that looks externally less parameterized. | |
// This looks nicer from outside the class with less parameterizations | |
import java.util.ArrayList; | |
import java.util.List; | |
public class FaceList { | |
private List<Face> faceList = new ArrayList<>(); | |
public Face get(Integer index) { | |
return faceList.get(index); | |
} | |
public void add(Face index) { | |
faceList.add(index); | |
} | |
public Integer size() { | |
return faceList.size(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage; | |
// This enum is the limit of the types of scoring we are doing in this game. | |
// If its not on this list, you can't score it that way. | |
public enum Scoring { | |
YATZY, PAIR, TWOPAIR, THREEOFAKIND, FOUROFAKIND, SMALLSTRAIGHT, LARGESTRAIGHT, FULLHOUSE; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
// This represents a throw of five dice | |
// You must construct it with five <Face> parameters. | |
// Their order doesn't matter. | |
public class Throw { | |
public List<Face> faces = new ArrayList<>(); | |
Throw(Face a, Face b, Face c, Face d, Face e) { | |
this.faces.add(a); | |
this.faces.add(b); | |
this.faces.add(c); | |
this.faces.add(d); | |
this.faces.add(e); | |
} | |
// This provides a map of Face => count | |
// for the throw represented by this object | |
// as it is rather important to figure out the groupings and how large they are | |
public Map<Face, Integer> mapCounts() { | |
Map<Face, Integer> faceCounts = new HashMap<>();// <Face, Integer>(); | |
for (Face thisFace : this.faces) { | |
int count; | |
count = faceCounts.getOrDefault(thisFace, 0) + 1; | |
faceCounts.put(thisFace, count); | |
} | |
return faceCounts; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage; | |
import java.util.Map; | |
// The Yatzy class provides the answer method which scores the result. | |
public class Yatzy { | |
// This uses a case swi]tch to select the various elements of the throw | |
public static int answer(Throw dice, Scoring scoreType) { | |
Map<Face, Integer> faceCounts = dice.mapCounts(); | |
switch (scoreType) { | |
case YATZY: | |
if (faceCounts.keySet().size() == 1) { | |
return 50; | |
} | |
break; | |
case PAIR: | |
Face maxDie; | |
maxDie = Face.ONE; | |
boolean paired; | |
paired = false; | |
// I think the line below looks as bad as perl with all the < > and such. | |
for (Map.Entry<Face, Integer> countEntry : faceCounts.entrySet()) { | |
if (countEntry.getValue() == 2) { | |
paired = true; | |
if (countEntry.getKey().value() >= maxDie.value()) { | |
maxDie = countEntry.getKey(); | |
} | |
} | |
} | |
if (paired) { | |
return (maxDie.value()) * 2; // twice the plus one of the | |
// value? bleh. | |
} | |
break; | |
case TWOPAIR: | |
FaceList faceList = new FaceList(); | |
for (Map.Entry<Face, Integer> countEntry : faceCounts.entrySet()) { | |
if (countEntry.getValue() == 2) { | |
faceList.add(countEntry.getKey()); | |
} | |
} | |
if (faceList.size() == 2) { | |
return ((faceList.get(0).value()) * 2 + (faceList.get(1).value()) * 2); | |
} | |
break; | |
case THREEOFAKIND: | |
for (Map.Entry<Face, Integer> countEntry : faceCounts.entrySet()) { | |
if (countEntry.getValue() == 3) { | |
return ((countEntry.getKey().value()) * 3); | |
} | |
} | |
break; | |
case FOUROFAKIND: | |
for (Map.Entry<Face, Integer> countEntry : faceCounts.entrySet()) { | |
if (countEntry.getValue() == 4) { | |
return ((countEntry.getKey().value()) * 4); | |
} | |
} | |
break; | |
case SMALLSTRAIGHT: | |
if (faceCounts.containsKey(Face.TWO) && faceCounts.containsKey(Face.THREE) && faceCounts.containsKey( | |
Face.FOUR)) { | |
if (faceCounts.containsKey(Face.ONE)) { | |
return 15; | |
} else { | |
return 0; | |
} | |
} | |
break; | |
case LARGESTRAIGHT: | |
if (faceCounts.containsKey(Face.TWO) && faceCounts.containsKey(Face.THREE) && faceCounts.containsKey( | |
Face.FOUR)) { | |
if (faceCounts.containsKey(Face.SIX)) { | |
return 20; | |
} else { | |
return 0; | |
} | |
} | |
break; | |
case FULLHOUSE: | |
if (faceCounts.entrySet().size() == 2) { | |
for (Integer oneofthem : faceCounts.values()) { | |
if (oneofthem == 1 || oneofthem == 4) { | |
return 0; // shortcut! Must have been a 4/1 split. | |
} | |
} | |
// Streams are fun. It lets me map like perl. | |
// map-reduce is fun. sum is short for reduce(a+b) | |
return dice.faces.stream().mapToInt(b -> b.value()).sum(); | |
} | |
break; | |
} | |
return 0; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testpackage; | |
import org.junit.*; | |
import static org.junit.Assert.*; | |
public class YatzyTest { | |
@Test | |
public void yatzy_scoring_ones() { | |
assertEquals(50, Yatzy.answer(new Throw(Face.ONE, Face.ONE, Face.ONE, Face.ONE, Face.ONE), Scoring.YATZY)); | |
// 1,1,1,1,1 scores 50 as yatzy | |
} | |
@Test | |
public void yatzy_scoring_fives() { | |
assertEquals(50, Yatzy.answer(new Throw(Face.FIVE, Face.FIVE, Face.FIVE, Face.FIVE, Face.FIVE), Scoring.YATZY)); | |
// 5,5,5,5,5 scores 50 as yatzy | |
} | |
@Test | |
public void yatzy_scoring_four() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.FIVE, Face.FIVE, Face.FIVE, Face.FIVE, Face.ONE), Scoring.YATZY)); | |
// 5,5,5,5,1 scores 0 as yatzy | |
} | |
@Test | |
public void yatzy_scoring_full_house() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.THREE, Face.THREE, Face.THREE, Face.FOUR, Face.FOUR), | |
Scoring.YATZY)); | |
// 3,3,3,4,4 scores 8 (4+4) as yatzy | |
} | |
@Test | |
public void pair_scoring_two_pair() { | |
assertEquals(12, Yatzy.answer(new Throw(Face.ONE, Face.ONE, Face.SIX, Face.TWO, Face.SIX), Scoring.PAIR)); | |
// 1,1,6,2,6 scores 12 (6+6) as pair | |
} | |
@Test | |
public void pair_scoring_three() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.THREE, Face.THREE, Face.THREE, Face.FOUR, Face.ONE), Scoring.PAIR)); | |
// 3,3,3,4,1 scores 0 as pair | |
} | |
@Test | |
public void pair_scoring_four() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.THREE, Face.THREE, Face.THREE, Face.THREE, Face.ONE), | |
Scoring.PAIR)); | |
// 3,3,3,3,1 scores 0 as pair | |
} | |
@Test | |
public void two_pair_scoring_two_pair() { | |
assertEquals(8, Yatzy.answer(new Throw(Face.ONE, Face.ONE, Face.TWO, Face.THREE, Face.THREE), Scoring.TWOPAIR)); | |
// 1,1,2,3,3 scores 8 (1+1+3+3) as two pair | |
} | |
@Test | |
public void two_pair_scoring_one_pair() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.ONE, Face.ONE, Face.TWO, Face.THREE, Face.FOUR), Scoring.TWOPAIR)); | |
// 1,1,2,3,4 scores 0 as two pair | |
} | |
@Test | |
public void two_pair_scoring_full_hosue() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.ONE, Face.ONE, Face.TWO, Face.TWO, Face.TWO), Scoring.TWOPAIR)); | |
// 1,1,2,2,2 scores 0 as two pair | |
} | |
@Test | |
public void three_of_kind_scoring_three() { | |
assertEquals(9, Yatzy.answer(new Throw(Face.THREE, Face.THREE, Face.THREE, Face.FOUR, Face.FIVE), | |
Scoring.THREEOFAKIND)); | |
// 3,3,3,4,5 scores 9 (3+3+3) as three of a kind | |
} | |
@Test | |
public void three_of_kind_scoring_pair() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.THREE, Face.THREE, Face.FOUR, Face.FIVE, Face.SIX), | |
Scoring.THREEOFAKIND)); | |
// 3,3,4,5,6 scores 0 as three of a kind | |
} | |
@Test | |
public void three_of_kind_scoring_four() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.THREE, Face.THREE, Face.THREE, Face.THREE, Face.ONE), | |
Scoring.THREEOFAKIND)); | |
// 3,3,3,3,1 scores 0 as three of a kind | |
} | |
@Test | |
public void four_of_kind_scoring_four_twos() { | |
assertEquals(8, Yatzy.answer(new Throw(Face.TWO, Face.TWO, Face.TWO, Face.TWO, Face.FIVE), | |
Scoring.FOUROFAKIND)); | |
// 2,2,2,2,5 scores 8 (2+2+2+2) as four of a kind | |
} | |
@Test | |
public void four_of_kind_scoring_full_house() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.TWO, Face.TWO, Face.TWO, Face.FIVE, Face.FIVE), | |
Scoring.FOUROFAKIND)); | |
// 2,2,2,5,5 scores 0 as four of a kind | |
} | |
@Test | |
public void four_of_kind_scoring_five_twos() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.TWO, Face.TWO, Face.TWO, Face.TWO, Face.TWO), Scoring.FOUROFAKIND)); | |
// 2,2,2,2,2 scores 0 as four of a kind | |
} | |
@Test | |
public void small_straight_scoring_small() { | |
assertEquals(15, Yatzy.answer(new Throw(Face.ONE, Face.TWO, Face.THREE, Face.FOUR, Face.FIVE), | |
Scoring.SMALLSTRAIGHT)); | |
// 1,2,3,4,5 scores 15 as small straight | |
} | |
@Test | |
public void large_straight_scoring_large() { | |
assertEquals(20, Yatzy.answer(new Throw(Face.TWO, Face.THREE, Face.FOUR, Face.FIVE, Face.SIX), | |
Scoring.LARGESTRAIGHT)); | |
// 2,3,4,5,6 scores 20 as a large straight | |
} | |
@Test | |
public void full_house_scoring_full_house() { | |
assertEquals(8, Yatzy.answer(new Throw(Face.ONE, Face.ONE, Face.TWO, Face.TWO, Face.TWO), Scoring.FULLHOUSE)); | |
// 1,1,2,2,2 scores 8 (1+1+2+2+2) as a full house | |
} | |
@Test | |
public void full_house_scoring_two_pair() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.TWO, Face.TWO, Face.THREE, Face.THREE, Face.FOUR), | |
Scoring.FULLHOUSE)); | |
// 2,2,3,3,4 scores 0 as a full house | |
} | |
@Test | |
public void full_house_scoring_yatzy() { | |
assertEquals(0, Yatzy.answer(new Throw(Face.FOUR, Face.FOUR, Face.FOUR, Face.FOUR, Face.FOUR), | |
Scoring.FULLHOUSE)); | |
// 4,4,4,4,4 scores 0 as a full house | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To add on to Chris's polymorphism comments, you could have something like a ThrowFactory, that looks something like this (I'm leaving out visibility modifiers, etc):
Then implementations of
Throw
for each of your combinations:Pair, TwoPair, ThreeOfAKind
, etc. GuessingPair
would look something like this: