diff --git a/src/Card.java b/src/Card.java old mode 100755 new mode 100644 index 9eed9a5..6d99a9e --- a/src/Card.java +++ b/src/Card.java @@ -1,12 +1,111 @@ public class Card { - // Create the rest of this class yourself + private int Q; + private int C; + private int S; + private int Sh; + private String str; + + public Card(int Quantity, int Color, int Shading, int Shape) { + Q = Fixer(Quantity); + C = Fixer(Color); + S = Fixer(Shading); + Sh = Fixer(Shape); + } + + private int Fixer(int value) { + if (value < 1 || value > 3) { + return ((((value % 3) + 3) % 3) + 1); + } + else { + return value; + } + } + + + public int getQuantity() { + return Q; + } + + public int getColor() { + return C; + } + + public int getShading() { + return S; + } + + public int getShape() { + return Sh; + } + + public boolean isSet(Card card2, Card card3) + { + if(((Q + card2.getQuantity() + card3.getQuantity()) % 3 == 0) && + ((C + card2.getColor() + card3.getColor()) % 3 == 0) && + ((S + card2.getShading() + card3.getShading()) % 3 == 0) && + ((Sh + card2.getShape() + card3.getShape()) % 3 == 0)) + { + return true; + } + + else { + return false; + } + } + + public String toString() { + String str = ""; + + if (Q == 1) { + str += 1; + } + else if (Q == 2) { + str += 2; + } + else if (Q == 3) { + str += 3; + } + + if (C == 1) { + str += 'R'; + } + else if (C == 2) { + str += 'G'; + } + else if (C == 3) { + str += 'P'; + } + + if (S == 1) { + str += 'O'; + } + else if (S == 2) { + str +='T'; + } + else if (S == 3) { + str += 'S'; + } + + if (Sh == 1) { + str += 'O'; + } + else if (Sh == 2) { + str += 'D'; + } + else if (Sh == 3) { + str += 'S'; + } + + return str; + } public boolean equals(Object obj) { Card that = (Card)obj; - return quantity == that.getQuantity() && - color == that.getColor() && - shading == that.getShading() && - shape == that.getShape(); + return Q == that.getQuantity() && + C == that.getColor() && + S == that.getShading() && + Sh == that.getShape(); } } + \ No newline at end of file diff --git a/src/CardTest.java b/src/CardTest.java new file mode 100644 index 0000000..84418ba --- /dev/null +++ b/src/CardTest.java @@ -0,0 +1,116 @@ +import junit.framework.TestCase; + +public class CardTest extends TestCase { + public void testNewCardAllSame() { + Card a = new Card(1, 1, 1, 1); + Card b = new Card(2, 2, 2, 2); + Card c = new Card(3, 3, 3, 3); + + assertEquals(1, a.getQuantity()); + assertEquals(1, a.getColor()); + assertEquals(1, a.getShading()); + assertEquals(1, a.getShape()); + + assertEquals(2, b.getQuantity()); + assertEquals(2, b.getColor()); + assertEquals(2, b.getShading()); + assertEquals(2, b.getShape()); + + assertEquals(3, c.getQuantity()); + assertEquals(3, c.getColor()); + assertEquals(3, c.getShading()); + assertEquals(3, c.getShape()); + } + + public void testNewCardFix1() { + Card a = new Card(4, 1, 1, 1); + Card b = new Card(1, 4, 1, 1); + Card c = new Card(1, 1, 4, 1); + Card d = new Card(1, 1, 1, 4); + + assertEquals(2, a.getQuantity()); + assertEquals(1, a.getColor()); + assertEquals(1, a.getShading()); + assertEquals(1, a.getShape()); + + assertEquals(1, b.getQuantity()); + assertEquals(2, b.getColor()); + assertEquals(1, b.getShading()); + assertEquals(1, b.getShape()); + + assertEquals(1, c.getQuantity()); + assertEquals(1, c.getColor()); + assertEquals(2, c.getShading()); + assertEquals(1, c.getShape()); + + assertEquals(1, d.getQuantity()); + assertEquals(1, d.getColor()); + assertEquals(1, d.getShading()); + assertEquals(2, d.getShape()); + } + + public void testNewCardFixNegative() { + Card a = new Card(-3, 1, 1, 1); + Card b = new Card(1, -3, 1, 1); + Card c = new Card(1, 1, -3, 1); + Card d = new Card(1, 1, 1, -3); + + assertEquals(1, a.getQuantity()); + assertEquals(1, a.getColor()); + assertEquals(1, a.getShading()); + assertEquals(1, a.getShape()); + + assertEquals(1, b.getQuantity()); + assertEquals(1, b.getColor()); + assertEquals(1, b.getShading()); + assertEquals(1, b.getShape()); + + assertEquals(1, c.getQuantity()); + assertEquals(1, c.getColor()); + assertEquals(1, c.getShading()); + assertEquals(1, c.getShape()); + + assertEquals(1, d.getQuantity()); + assertEquals(1, d.getColor()); + assertEquals(1, d.getShading()); + assertEquals(1, d.getShape()); + } + + public void testNewCardFixAll() { + Card a = new Card(-3, 4, 7, 6); + + assertEquals(1, a.getQuantity()); + assertEquals(2, a.getColor()); + assertEquals(2, a.getShading()); + assertEquals(1, a.getShape()); + } + + public void testNewCardisSetTrue() { + Card a = new Card(1, 1, 1, 1); + Card b = new Card(1, 2, 1, 1); + Card c = new Card(1, 3, 1, 1); + + assertTrue(a.isSet(b, c)); + } + + public void testNewCardisSetFalse() { + Card a = new Card(1, 1, 1, 1); + Card b = new Card(2, 2, 2, 2); + Card c = new Card(3, 3, 3, 3); + + assertTrue(a.isSet(b, c)); + } + + + public void testNewCardtoString() { + Card a = new Card(-1, 1, 1, 3); + Card b = new Card(1, 2, 3, 2); + Card c = new Card(2, 5, 10, -6); + + assertEquals("3ROS", a.toString()); + assertEquals("1GSD", b.toString()); + assertEquals("2PTO", c.toString()); + } + + +} diff --git a/src/Deck.java b/src/Deck.java old mode 100755 new mode 100644 index ab3a2a3..71c0fe8 --- a/src/Deck.java +++ b/src/Deck.java @@ -2,9 +2,29 @@ import java.io.FileReader; import java.util.StringTokenizer; import java.util.ArrayList; +import java.util.Collections; public class Deck { - // Implement the rest of this class yourself + private int nextCardIndex; + private ArrayList cards; + + public Deck() { + cards = new ArrayList(81); + + for (int Q = 1; Q <= 3; Q++) { + for (int C = 1; C <= 3; C++) { + for (int S = 1; S <= 3; S++) { + for (int Sh = 1; Sh <= 3; Sh++) { + Card c = new Card(Q, C, S, Sh); + cards.add(c); + } + } + } + } + Collections.shuffle(cards); + } + + public Deck(String filename) { cards = new ArrayList(81); @@ -42,4 +62,23 @@ public Deck(String filename) { throw new RuntimeException("Error while reading file: " + e.toString()); } } + + public boolean hasNext() { + if (nextCardIndex < cards.size()) { + return true; + } + else { + return false; + } + } + + public Card getNext() { + if (hasNext() != false) { + nextCardIndex += 1; + return cards.get(nextCardIndex - 1); + } + else { + return null; + } + } } diff --git a/src/DeckTest.java b/src/DeckTest.java new file mode 100644 index 0000000..cba7a86 --- /dev/null +++ b/src/DeckTest.java @@ -0,0 +1,46 @@ +import junit.framework.TestCase; + +public class DeckTest extends TestCase { + public void testoneCard() { + Deck d = new Deck("oneCard.dat"); + + assertTrue(d.hasNext()); + assertEquals("1GSO", d.getNext().toString()); + assertFalse(d.hasNext()); + } + + public void testoneSetTrue() { + Deck d = new Deck("oneSetTrue.dat"); + Card c = d.getNext(); + assertTrue(d.hasNext()); + Card c2 = d.getNext(); + assertTrue(d.hasNext()); + Card c3 = d.getNext(); + assertFalse(d.hasNext()); + + assertEquals("1ROO", c.toString()); + assertEquals("1GOO", c2.toString()); + assertEquals("1POO", c3.toString()); + + assertTrue(c.isSet(c2, c3)); + + } + + public void testoneSetFalse() { + Deck d = new Deck("oneSetFalse.dat"); + Card c = d.getNext(); + assertTrue(d.hasNext()); + Card c2 = d.getNext(); + assertTrue(d.hasNext()); + Card c3 = d.getNext(); + assertFalse(d.hasNext()); + + + assertEquals("1ROO", c.toString()); + assertEquals("2GTD", c2.toString()); + assertEquals("3PSO", c3.toString()); + + assertFalse(c.isSet(c2, c3)); + } + +} diff --git a/src/Game.java b/src/Game.java new file mode 100644 index 0000000..6863c3a --- /dev/null +++ b/src/Game.java @@ -0,0 +1,83 @@ +public class Game { + private Table t; + private Deck d; + + public Game() { + d = new Deck(); + t = new Table(); + + for (int i = 0; i < 12; i++) { + t.add(d.getNext()); + } + } + + public Game(String filename) { + d = new Deck(filename); + t = new Table(); + + for (int i = 0; i <= 12; i++) { + if (d.hasNext() == true) { + t.add(d.getNext()); + } + + if (t.numCards() == 12) { + return; + } + } + } + + public void playRound() { + boolean foundSet = false; + if(t.numSets() == 0 && d.hasNext() != false) { + for (int i = 0; i < 3; i++) { + t.add(d.getNext()); + } + return; + } + for (int i = 0; i < numCards() - 2; i++) { + if (foundSet) + break; + for (int j = i + 1; j < numCards() - 1; j++) { + if (foundSet) + break; + for (int k = j + 1; k < numCards(); k++) { + Card c1 = t.getCard(i); + Card c2 = t.getCard(j); + Card c3 = t.getCard(k); + + if (c1.isSet(c2, c3)) { + t.removeSet(c1, c2, c3); + foundSet = true; + break; + } + } + } + } + if(t.numCards() < 12 && d.hasNext() == true) { + for (int l = 0; l < 3; l++) { + if (d.hasNext() == true) + t.add(d.getNext()); + } + } + } + + + + + public int numSets() { + return t.numSets(); + } + + public int numCards() { + return t.numCards(); + } + + public boolean isGameOver() { + if (t.numSets() == 0 && d.hasNext() == false) { + return true; + } + else { + return false; + } + } +} diff --git a/src/GameTest.java b/src/GameTest.java new file mode 100644 index 0000000..3657164 --- /dev/null +++ b/src/GameTest.java @@ -0,0 +1,162 @@ +import junit.framework.TestCase; + +public class GameTest extends TestCase { + public void testNewGame() + { + // When a game is created from a random deck, + // there are 12 cards on the table and the game + // is not over. Can't say much more... + Game g = new Game(); + + assertEquals(12, g.numCards()); + assertFalse(g.isGameOver()); + } + + public void testNoSetsFirstTwelve() + { + Game g = new Game("15cards0setsin12Milestone.dat.txt"); + + assertEquals(0, g.numSets()); + assertEquals(12, g.numCards()); + + g.playRound(); + + assertEquals(15, g.numCards()); + } + + public void testNoSetsFirstFifteen() + { + Game g = new Game("18cards0setsin15Milestone.dat.txt"); + + assertEquals(0, g.numSets()); + assertEquals(12, g.numCards()); + + g.playRound(); + + assertEquals(0, g.numSets()); + assertEquals(15, g.numCards()); + + g.playRound(); + + assertEquals(9, g.numSets()); + assertEquals(18, g.numCards()); + } + + public void testBackToTwelveAfterFifteen() + { + Game g = new Game("15cards0setsin12Milestone.dat.txt"); + // this takes us to 15 + g.playRound(); + + assertEquals(15, g.numCards()); + + // When we play another round, we wont' add more cards. + g.playRound(); + assertEquals(12, g.numCards()); + } + + public void testBackToFifteenAfterEighteen() + { + Game g = new Game("18cards0setsin15Milestone.dat.txt"); + g.playRound(); + g.playRound(); + + // now we have 18 cards on the table. + assertEquals(18, g.numCards()); + + // When we play another round, we won't add more cards. + g.playRound(); + assertEquals(15, g.numCards()); + } + + public void testDeckNotMultipleOfThree() + { + Game g = new Game("14cardsMilestone.dat.txt"); + assertEquals(12, g.numCards()); + // when we play a round, there is a set, but there are + // only 2 more cards available. + g.playRound(); + + assertEquals(11, g.numCards()); + } + + public void testDeckLessThanTwelve() + { + Game g = new Game("7cardsMilestone.dat.txt"); + + assertEquals(7, g.numCards()); + g.playRound(); + + assertEquals(4, g.numCards()); + } + + public void testGameOverEmptyTable() + { + Game g = new Game("12cards4setsMilestone.dat.txt"); + + assertEquals(12, g.numCards()); + assertEquals(4, g.numSets()); + + g.playRound(); + assertEquals(9, g.numCards()); + assertEquals(3, g.numSets()); + + g.playRound(); + assertEquals(6, g.numCards()); + assertEquals(2, g.numSets()); + + g.playRound(); + assertEquals(3, g.numCards()); + assertEquals(1, g.numSets()); + + g.playRound(); + assertEquals(0, g.numCards()); + assertTrue(g.isGameOver()); + } + + public void test14Sets() + { + Game g = new Game("14in12Milestone.dat.txt"); + + assertEquals(12, g.numCards()); + assertEquals(14, g.numSets()); + assertFalse(g.isGameOver()); + + g.playRound(); + assertEquals(9, g.numCards()); + assertFalse(g.isGameOver()); + + g.playRound(); + assertEquals(6, g.numCards()); + assertFalse(g.isGameOver()); + + g.playRound(); + assertEquals(3, g.numCards()); + assertTrue(g.isGameOver()); + } + + public void testRemoveAdd() + { + Game g = new Game("15cardsMilestone.dat.txt"); + + assertEquals(12, g.numCards()); + assertEquals(3, g.numSets()); + assertFalse(g.isGameOver()); + + g.playRound(); + + assertEquals(12, g.numCards()); + assertEquals(3, g.numSets()); + assertFalse(g.isGameOver()); + + g.playRound(); + assertEquals(9, g.numCards()); + assertEquals(1, g.numSets()); + assertFalse(g.isGameOver()); + + g.playRound(); + assertEquals(6, g.numCards()); + assertEquals(0, g.numSets()); + assertTrue(g.isGameOver()); + } +} diff --git a/src/MonteCarlo.java b/src/MonteCarlo.java new file mode 100644 index 0000000..ef8e9b3 --- /dev/null +++ b/src/MonteCarlo.java @@ -0,0 +1,17 @@ +public class MonteCarlo { + public static void main (String[] args) { + float setSum = 0; + float gameSum = 0; + + for (int i = 0; i < 10000; i++ ) { + Game g = new Game(); + setSum += g.numSets(); + while (!g.isGameOver()) { + g.playRound(); + } + gameSum += g.numCards(); + } + System.out.println(setSum/10000); + System.out.println(gameSum/10000); + } +} diff --git a/src/Table.java b/src/Table.java new file mode 100644 index 0000000..33dbe38 --- /dev/null +++ b/src/Table.java @@ -0,0 +1,132 @@ +public class Table { + private TableNode head; + + public Table() { + head = null; + } + + public void add(Card newCard) { + TableNode newTableNode = new TableNode(newCard); + newTableNode.setNext(head); + head = newTableNode; + } + + private boolean onTable(Card c) { + TableNode curr = head; + while (curr != null) { + if (curr.getCard().equals(c)) { + return true; + } + curr = curr.getNext(); + } + return false; + } + + private void removeCard(Card c1) { + TableNode prev = findPrev(c1); + // remove from beginning + if (prev == null) { + head = head.getNext(); + } + // remove from middle or end + else { + TableNode curr = prev.getNext(); + prev.setNext(curr.getNext()); + } + } + + + + private TableNode findPrev(Card c1) { + TableNode curr = head; + TableNode prev = null; + + while (curr != null) { + if (c1.equals(curr.getCard())) { + return prev; + } + else { + prev = curr; + curr = curr.getNext(); + } + } + return null; + } + + public void removeSet(Card c1, Card c2, Card c3) { + TableNode curr = head; + TableNode prev = null; + + if (!c1.isSet(c2, c3)) { + return; + } + + if (!onTable(c1)) { + return; + } + + if (!onTable(c2)) { + return; + } + + if (!onTable(c3)) { + return; + } + + removeCard(c1); + removeCard(c2); + removeCard(c3); + } + + + + public int numCards() { + TableNode curr = head; + int count = 0; + + while (curr != null) { + count += 1; + curr = curr.getNext(); + } + return count; + } + + public Card getCard(int index) { + TableNode temp = head; + if (temp == null) { + return null; + } + + for (int i = 0; i < index; i++) { + temp = temp.getNext(); + + if (temp == null) { + return null; + } + } + return temp.getCard(); + } + + public int numSets() { + int count = 0; + int length = numCards(); + + for (int i = 0; i < length - 2; i++) { + for (int j = i + 1; j < length - 1; j++) { + for (int k = j + 1; k < length; k++) { + + Card c1 = getCard(i); + Card c2 = getCard(j); + Card c3 = getCard(k); + + if (c1.isSet(c2, c3)) { + count += 1; + } + } + } + } + return count; + } +} + + diff --git a/src/TableNode.java b/src/TableNode.java new file mode 100644 index 0000000..64e2db5 --- /dev/null +++ b/src/TableNode.java @@ -0,0 +1,22 @@ +public class TableNode { + private Card card; + private TableNode next; + + + public TableNode(Card c) { + card = c; + next = null; + } + + public void setNext(TableNode newNext) { + next = newNext; + } + + public TableNode getNext() { + return next; + } + + public Card getCard() { + return card; + } +} \ No newline at end of file diff --git a/src/TableTest.java b/src/TableTest.java new file mode 100644 index 0000000..43a7e34 --- /dev/null +++ b/src/TableTest.java @@ -0,0 +1,65 @@ +import junit.framework.TestCase; + +public class TableTest extends TestCase { + public void testAddCards() { + Table t = new Table(); + + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(1, 2, 1, 1); + Card c3 = new Card(1, 3, 1, 1); + + t.add(c1); + assertEquals(1, t.numCards()); + t.add(c2); + assertEquals(2, t.numCards()); + t.add(c3); + assertEquals(3, t.numCards()); + } + + public void testOneSet() { + Table t = new Table(); + + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(1, 2, 1, 1); + Card c3 = new Card(1, 3, 1, 1); + + t.add(c1); + assertEquals(1, t.numCards()); + t.add(c2); + assertEquals(2, t.numCards()); + t.add(c3); + assertEquals(3, t.numCards()); + + assertEquals(c3, t.getCard(0)); + assertEquals(c2, t.getCard(1)); + assertEquals(c1, t.getCard(2)); + + assertEquals("1ROO", t.getCard(2).toString()); + + assertEquals(t.numSets(), 1); + + assertTrue(c1.isSet(c2, c3)); + } + + public void testRemoveOneSet() { + Table t = new Table(); + + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(1, 2, 1, 1); + Card c3 = new Card(1, 3, 1, 1); + Card c4 = new Card(3, 1, 3, 1); + + t.add(c1); + t.add(c2); + t.add(c3); + t.add(c4); + + assertEquals(1, t.numSets()); + assertEquals(4, t.numCards()); + assertTrue(c1.isSet(c2, c3)); + + t.removeSet(c1, c2, c3); + assertEquals(1, t.numCards()); + } + +}