diff --git a/src/Card.java b/src/Card.java old mode 100755 new mode 100644 index 9eed9a5..50a0a11 --- a/src/Card.java +++ b/src/Card.java @@ -1,5 +1,80 @@ public class Card { - // Create the rest of this class yourself + private int quantity; + private int color; + private int shading; + private int shape; + + Card(int quantity, int color, int shading, int shape) { + this.quantity = fixValue(quantity); + this.color = fixValue(color); + this.shading = fixValue(shading); + this.shape = fixValue(shape); + } + + public int getQuantity() { + return quantity; + } + + public int getColor() { + return color; + } + + public int getShading() { + return shading; + } + + public int getShape() { + return shape; + } + + public boolean isSet(Card card2, Card card3) { + boolean set = true; + int qMod = (quantity + card2.getQuantity() + card3.getQuantity()) % 3; + int cMod = (color + card2.getColor() + card3.getColor()) % 3; + int tMod = (shading + card2.getShading() + card3.getShading()) % 3; + int sMod = (shape + card2.getShape() + card3.getShape()) % 3; + + if (qMod+cMod+tMod+sMod != 0) + return false; + return set; + } + + public String toString() { + String string = ""; + String c = ""; + String t = ""; + String s = ""; + + if (color == 1) + c = "R"; + else if (color == 2) + c = "G"; + else + c = "P"; + + if (shading == 1) + t= "O"; + else if (shading == 2) + t = "T"; + else + t = "S"; + + if (shape == 1) + s = "O"; + else if (shape == 2) + s = "D"; + else + s = "S"; + + return string = quantity + c + t + s; + } + + private int fixValue(int valueToFix) { + if (valueToFix < 1 || valueToFix > 3) + return (((valueToFix % 3) + 3) % 3) + 1; + else + return valueToFix; + } public boolean equals(Object obj) { Card that = (Card)obj; diff --git a/src/CardTest.java b/src/CardTest.java new file mode 100644 index 0000000..78f9b89 --- /dev/null +++ b/src/CardTest.java @@ -0,0 +1,25 @@ +import junit.framework.TestCase; + +public class CardTest extends TestCase { + + public void testIsSet() { + Card c1 = new Card(1, 1, 2, 7); + Card c2 = new Card(1, 2, 2, 2); + Card c3 = new Card(1, -1, 2, 2); + assertEquals(true, c1.isSet(c2, c3)); + } + + public void testIsntSet() { + Card c1 = new Card(2, 1, 1, 2); + Card c2 = new Card(1, 2, 2, 2); + Card c3 = new Card(1, 3, 3, 2); + assertEquals(false, c1.isSet(c2, c3)); + } + + public void testToString() { + Card c1 = new Card(2, 1, 2, 3); + Card c2 = new Card(1, 2, 3, -4); + assertEquals("2RTS", c1.toString()); + assertEquals("1GSS", c2.toString()); + } +} diff --git a/src/Deck.java b/src/Deck.java old mode 100755 new mode 100644 index ab3a2a3..b089353 --- a/src/Deck.java +++ b/src/Deck.java @@ -2,9 +2,13 @@ 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 + // Instance variables must be cards and nextCardIndex for the + // provided constructor to work + ArrayList cards; + int nextCardIndex = 0; public Deck(String filename) { cards = new ArrayList(81); @@ -42,4 +46,39 @@ public Deck(String filename) { throw new RuntimeException("Error while reading file: " + e.toString()); } } + + public Deck() { + // Creates a deck with all standard 81 set cards, shuffled. + // Usage (in test mode, and in the later code): + // Deck d = new Deck() + cards = new ArrayList(81); + + for (int quantity = 1; quantity < 4; quantity++) { + for (int color = 1; color < 4; color++) { + for (int shading = 1; shading < 4; shading++) { + for (int shape = 1; shape < 4; shape++) { + cards.add(new Card(quantity, color, shading, shape)); + } + } + } + } + Collections.shuffle(cards); + } + + public boolean hasNext() { + if (nextCardIndex <= cards.size()-1) + return true; + return false; + } + + public Card getNext() { + // Returns the next card in the deck if there is one, + // and null, otherwise + // You can call hasNext within this method to see if you + // should return a card or return null + if (hasNext() == false) + return null; + nextCardIndex++; + return cards.get(nextCardIndex-1); + } } diff --git a/src/DeckTest.java b/src/DeckTest.java new file mode 100644 index 0000000..632ad63 --- /dev/null +++ b/src/DeckTest.java @@ -0,0 +1,9 @@ +import junit.framework.TestCase; + +public class DeckTest extends TestCase { + + public void testDeckSize() { + Deck deck = new Deck(); + assertEquals(81, deck.cards.size()); + } +} diff --git a/src/Game.java b/src/Game.java new file mode 100644 index 0000000..8eb8cd2 --- /dev/null +++ b/src/Game.java @@ -0,0 +1,115 @@ +public class Game { + + private Table table; + private Deck deck; + + public Game() { + table = new Table(); + deck = new Deck(); + for (int i = 0; i < 12; i++) { + table.add(deck.getNext()); + } + } + + public Game(String filename) { + table = new Table(); + deck = new Deck(filename); + while (deck.hasNext()) { + table.add(deck.getNext()); + if (table.numCards() == 12) + return; + } + } + + public int numSets() { + return table.numSets(); + } + + public int numCards() { + return table.numCards(); + } + + public void playRound() { + //no sets on table but still cards in deck. add three cards + if (numSets() == 0 && deck.hasNext()) { + for (int i = 0; i < 3; i++) { + if (deck.hasNext()) + table.add(deck.getNext()); + } + return; + } + + //there are 12 cards on the table containing 1+ sets. + //remove one set and add three cards to the table + if (table.numCards() > 0 && table.numSets() > 0) { + for (int i=0; i < table.numCards()-2; i++) { + for (int j = i + 1; j < table.numCards()-1; j++) { + for (int k = j + 1; k < table.numCards(); k++) { + + Card c1 = table.getCard(i); + Card c2 = table.getCard(j); + Card c3 = table.getCard(k); + + if (c1.isSet(c2, c3)) { + table.removeSet(c1, c2, c3); + for (int x = 0; x < 3; x++) { + if (deck.hasNext()) { + table.add(deck.getNext()); + } + } + return; + } + } + } + } + } + //round starts with more that 12 cards because no sets in prev round + //remove cards but do not add more + else if (table.numCards() > 12 && table.numSets() > 0) { + for (int i= 0; i < table.numCards()-2; i++) { + for (int j = i + 1; j < table.numCards()-1; j++) { + for (int k = j + 1; k < table.numCards(); k++) { + + Card c1 = table.getCard(i); + Card c2 = table.getCard(j); + Card c3 = table.getCard(k); + + if (c1.isSet(c2, c3)) { + table.removeSet(c1, c2, c3); + return; + } + } + } + } + } + //there is 1+ set on the table but no cards in the deck + //remove cards from the table + else if (deck.hasNext() == false && table.numSets() >= 1) { + for (int i=0; i < table.numCards()-2; i++) { + for (int j = i + 1; j < table.numCards()-1; j++) { + for (int k = j + 1; k < table.numCards(); k++) { + + Card c1 = table.getCard(i); + Card c2 = table.getCard(j); + Card c3 = table.getCard(k); + + if (c1.isSet(c2, c3)) + table.removeSet(c1, c2, c3); + return; + } + } + } + } + //there are no cards in the deck and no sets on the table + //game is over. + else if (deck.hasNext() == false && table.numSets() == 0) { + return; + } + } + + + public boolean isGameOver() { + return (table.numSets() == 0 && deck.hasNext() == false); + } +} + \ No newline at end of file diff --git a/src/GameTest.java b/src/GameTest.java new file mode 100644 index 0000000..be581f1 --- /dev/null +++ b/src/GameTest.java @@ -0,0 +1,23 @@ +import junit.framework.TestCase; + + +public class GameTest extends TestCase { + + + public void testGame() { + Game game = new Game(); + assertEquals(12, game.numCards()); + } + + public void testGameFromFile() { + Game game = new Game("3cards1setMilestone.dat"); + assertEquals(3, game.numCards()); + game.playRound(); + assertEquals(0, game.numCards()); + } + + //public void testGameFullDeck() { + //Game game = new Game(" + + +} diff --git a/src/Simulation.java b/src/Simulation.java new file mode 100644 index 0000000..9f6c9db --- /dev/null +++ b/src/Simulation.java @@ -0,0 +1,28 @@ +public class Simulation { + public static void main(String[] args) { + + int numSets = 0; + int numEndingCards = 0; + int numGames = 0; + + while (numGames < 1000001) { + + Game game = new Game(); + numSets += game.numSets(); + while(game.isGameOver() == false) { + game.playRound(); + } + numEndingCards += game.numCards(); + numGames++; + + } + + System.out.println("the average number of sets in a random collection of 12 cards is: " + numSets/numGames); + System.out.println("The average number of cards left at the end of a game is: " + numEndingCards/numGames); + } +} + + + + + \ No newline at end of file diff --git a/src/Table.java b/src/Table.java new file mode 100644 index 0000000..d14dbbc --- /dev/null +++ b/src/Table.java @@ -0,0 +1,114 @@ + +public class Table { + + private TableNode head; + + Table() { + head = null; + } + + public void add(Card card) { + TableNode newTableNode = new TableNode(card); + if (head == null) { + head = newTableNode; + } + else { + newTableNode.setNext(head); + head = newTableNode; + } + } + + private boolean cardInList(Card card) { + TableNode tableNode = head; + boolean foundCard = false; + while (tableNode != null && !foundCard) { + if (tableNode.getCard().equals(card)) + foundCard = true; + else { + tableNode = tableNode.getNext(); + } + } + return foundCard; + } + + private void removeCard(Card card) { + TableNode curr = head; + TableNode prev = null; + while (!card.equals(curr.getCard())) { + prev = curr; + curr = curr.getNext(); + } + if (curr == head) { + head = head.getNext(); + } + else { + prev.setNext(curr.getNext()); + } + } + + + public void removeSet(Card c1, Card c2, Card c3) { + boolean isSet = c1.isSet(c2, c3); + boolean c1InList = cardInList(c1); + boolean c2InList = cardInList(c2); + boolean c3InList = cardInList(c3); + + if (isSet && c1InList && c2InList && c3InList) { + removeCard(c1); + removeCard(c2); + removeCard(c3); + + } + } + + public int numCards() { + int numCards = 0; + TableNode tableNode = head; + if (head == null) + return 0; + + while (tableNode != null) { + tableNode = tableNode.getNext(); + numCards++; + } + return numCards; + } + + public Card getCard(int stopIndex) { + TableNode tableNode = head; + if (tableNode == null) + return null; + + else if (stopIndex == 0) { + return tableNode.getCard(); + } + + for (int currIndex = 0; currIndex < stopIndex; currIndex++) { + tableNode = tableNode.getNext(); + } + return tableNode.getCard(); + } + + + public int numSets() { + int numSets = 0; + int numCards = numCards(); + + for (int i = 0; i < numCards-2; i++) { + for (int j = i + 1; j < numCards-1; j++) { + for (int k = j + 1; k < numCards; k++) { + Card c1 = getCard(i); + Card c2 = getCard(j); + Card c3 = getCard(k); + + if (c1.isSet(c2, c3)) + numSets++; + + } + } + } + return numSets; + } + +} + \ No newline at end of file diff --git a/src/TableNode.java b/src/TableNode.java new file mode 100644 index 0000000..5cd0404 --- /dev/null +++ b/src/TableNode.java @@ -0,0 +1,26 @@ +public class TableNode { + + private Card card; + private TableNode next; + + TableNode(Card card) { + this.card = card; + 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..08caec1 --- /dev/null +++ b/src/TableTest.java @@ -0,0 +1,31 @@ +import junit.framework.TestCase; + + +public class TableTest extends TestCase { + + public void testTablewWithCards() { + Table t = new Table(); + + t.add(new Card(1, 1, 1, 1)); + assertEquals(1, t.numCards()); + + t.add(new Card(2, 1, 1, 1)); + assertEquals(2, t.numCards()); + + t.add(new Card(3, 1, 1, 1)); + assertEquals(3, t.numCards()); + + + t.add(new Card(2, 2, 2, 2)); + assertEquals(4, t.numCards()); + + assertEquals(1, t.numSets()); + assertEquals(new Card(1, 1, 1, 1), t.getCard(0)); + } + + public void testTableWithoutCards() { + Table t = new Table(); + assertEquals(0, t.numCards()); + assertEquals(0, t.numSets()); + } +}