From ced8101cdb6542ed8a7c2386047859bd22fc4f86 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Wed, 1 Apr 2015 10:05:09 -0400 Subject: [PATCH 1/9] First commit of the Card Class and its test. --- src/Card.java | 81 ++++++++++++++++++++++++++++++++++++++++++++++- src/CardTest.java | 66 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 1 deletion(-) mode change 100755 => 100644 src/Card.java create mode 100644 src/CardTest.java diff --git a/src/Card.java b/src/Card.java old mode 100755 new mode 100644 index 9eed9a5..efe2d86 --- a/src/Card.java +++ b/src/Card.java @@ -1,5 +1,84 @@ public class Card { - // Create the rest of this class yourself + private int quantity; + private int color; + private int shading; + private int shape; + + public Card(int q, int c, int shd, int shp){ + quantity = fixValue(q); + color = fixValue(c); + shading = fixValue(shd); + shape = fixValue(shp); + } + + public int getQuantity() { + return quantity; + } + + public int getColor() { + return color; + } + + public int getShading() { + return shading; + } + + public int getShape() { + return shape; + } + + public boolean isSet(Card c1, Card c2) { + if((c1.getQuantity() + c2.getQuantity() + quantity) % 3 == 0 && + (c1.getColor() + c2.getColor() + color) % 3 == 0 && + (c1.getShading() + c2.getShading() + shading) % 3 == 0 && + (c1.getShape() + c2.getShape() + shape) % 3 == 0) + return true; + + else + return false; + } + + public String toString() { + String str = ""; + str += quantity; + if(color == 1) { + str += "R"; + } + if(color == 2) { + str += "G"; + } + if(color == 3) { + str += "P"; + } + if(shading == 1) { + str += "O"; + } + if(shading == 2) { + str += "T"; + } + if(shading == 3) { + str += "S"; + } + if(shape == 1) { + str += "O"; + } + if(shape == 2) { + str += "D"; + } + if(shape == 3) { + str += "S"; + } + return str; + } + + + + 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..9b5e0b7 --- /dev/null +++ b/src/CardTest.java @@ -0,0 +1,66 @@ +import junit.framework.TestCase; + +/** + * A JUnit test case class. + * Every method starting with the word "test" will be called when running + * the test with JUnit. + */ +public class CardTest extends TestCase { + + /** + * A test method. + * (Replace "X" with a name describing the test. You may write as + * many "testSomething" methods in this class as you wish, and each + * one will be called when running JUnit over this class.) + */ + public void testAllOnes() { + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(1, 1, 1, 1); + + assertEquals(c1, c2); + } + + public void testThreeCards() { + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(1, 1, 1, 1); + Card c3 = new Card(1, 1, 1, 1); + + assertEquals(c1, c2); + assertEquals(c1, c3); + assertEquals(c2, c3); + } + public void testIsSet() { + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(1, 1, 1, 1); + Card c3 = new Card(1, 1, 1, 1); + + assertTrue(c1.isSet(c2,c3)); + } + public void testNotSet() { + Card c1 = new Card(1, 2, 3, 1); + Card c2 = new Card(2, 3, 3, 1); + Card c3 = new Card(2, 3, 3, 3); + + assertFalse(c1.isSet(c2,c3)); + } + public void testToString() { + Card c1 = new Card(1, 2, 3, 1); + + assertEquals("1GSO", c1.toString()); + } + public void testInvalidNumbers() { + Card c1 = new Card(8, 7, 6, 4); + + assertEquals("3GOD", c1.toString()); + } + public void testNegativeNumbers() { + Card c1 = new Card(-8, -7, -6, -4); + + assertEquals("2POS", c1.toString()); + } + public void testNegativeAndPositiveNumbers() { + Card c1 = new Card(-8, 3, -6, 4); + + assertEquals("2POD", c1.toString()); + } +} From 888fe9b2bf77530d78a2efac2b6ead2900e16550 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Wed, 8 Apr 2015 09:14:11 -0400 Subject: [PATCH 2/9] Added finnished Deck class and the test. --- src/Deck.java | 46 ++++++++++++++++++++++++++++++++++- src/DeckTest.java | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) mode change 100755 => 100644 src/Deck.java create mode 100644 src/DeckTest.java diff --git a/src/Deck.java b/src/Deck.java old mode 100755 new mode 100644 index ab3a2a3..b26557f --- a/src/Deck.java +++ b/src/Deck.java @@ -2,9 +2,53 @@ 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 ArrayList cards; + private int nextCardIndex; + + public Deck() { + // Creates a deck with all standard 81 set cards, shuffled. + cards = new ArrayList(81); + for(int i = 0; i < 81; i++) { + for (int quantity =1; quantity <= 3; quantity ++) { + for (int color =1; color <= 3; color++) { + for (int shading =1; shading <= 3; shading++) { + for (int shape =1; shape <= 3; shape++) { + Card c = new Card(quantity, color, shading, shape); + cards.add(c); + } + } + } + } + } + Collections.shuffle(cards); + } + +// public Deck(String filename) { +// Creates a pre-defined deck from a file named filename, and does not shuffle it. +// Usage (in test code, and in the later code): +// Deck d = new Deck("example.dat"); +// } + + public boolean hasNext() { + // Returns true if any cards left, false otherwise. + if(nextCardIndex < cards.size()) + return true; + else + return false; + } + + public Card getNext() { + // Returns the next card in the deck if there is one, null otherwise. + if (hasNext() == true) { + nextCardIndex += 1; + return cards.get(nextCardIndex -1); + } + else + return null; + } public Deck(String filename) { cards = new ArrayList(81); diff --git a/src/DeckTest.java b/src/DeckTest.java new file mode 100644 index 0000000..59c231c --- /dev/null +++ b/src/DeckTest.java @@ -0,0 +1,62 @@ +import junit.framework.TestCase; + +/** + * A JUnit test case class. + * Every method starting with the word "test" will be called when running + * the test with JUnit. + */ +public class DeckTest extends TestCase { + + /** + * A test method. + * (Replace "X" with a name describing the test. You may write as + * many "testSomething" methods in this class as you wish, and each + * one will be called when running JUnit over this class.) + */ + public void testOneCard() { + Deck d = new Deck("oneCard.dat"); + + assertTrue(d.hasNext()); + assertEquals("1GSO", d.getNext().toString()); + assertFalse(d.hasNext()); + } + public void testOneSet() { + Deck d = new Deck("oneSet.dat"); + + assertTrue(d.hasNext()); + assertEquals("1ROO", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("1GTD", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("1PSS", d.getNext().toString()); + assertFalse(d.hasNext()); + } + public void testNoSet() { + Deck d = new Deck("noSet.dat"); + + assertTrue(d.hasNext()); + assertEquals("1GSO", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("1GOO", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("1ROO", d.getNext().toString()); + assertFalse(d.hasNext()); + } + public void testSixCardsWithOneSet() { + Deck d = new Deck("sixCards.dat"); + + assertTrue(d.hasNext()); + assertEquals("1ROO", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("2GTD", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("3PSS", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("1GSO", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("1RTD", d.getNext().toString()); + assertTrue(d.hasNext()); + assertEquals("3GOD", d.getNext().toString()); + assertFalse(d.hasNext()); + } +} From db62e933771e007acada24aec6ae9af8b6a29c26 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Wed, 8 Apr 2015 10:45:40 -0400 Subject: [PATCH 3/9] Fixed error- Too many for loops --- src/Deck.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Deck.java b/src/Deck.java index b26557f..86744c6 100644 --- a/src/Deck.java +++ b/src/Deck.java @@ -11,7 +11,7 @@ public class Deck { public Deck() { // Creates a deck with all standard 81 set cards, shuffled. cards = new ArrayList(81); - for(int i = 0; i < 81; i++) { + for (int quantity =1; quantity <= 3; quantity ++) { for (int color =1; color <= 3; color++) { for (int shading =1; shading <= 3; shading++) { @@ -22,8 +22,7 @@ public Deck() { } } } - } - Collections.shuffle(cards); + Collections.shuffle(cards); } // public Deck(String filename) { From 774a37a130ea04512f8788cccd49184cdf5fc4a8 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Wed, 15 Apr 2015 10:11:44 -0400 Subject: [PATCH 4/9] Table, TableNode, TableTest, TableNodeTest --- src/Table.java | 125 +++++++++++++++++++++++++++++++++++++++++ src/TableNode.java | 21 +++++++ src/TableNodeTest.java | 22 ++++++++ src/TableTest.java | 56 ++++++++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 src/Table.java create mode 100644 src/TableNode.java create mode 100644 src/TableNodeTest.java create mode 100644 src/TableTest.java diff --git a/src/Table.java b/src/Table.java new file mode 100644 index 0000000..9757005 --- /dev/null +++ b/src/Table.java @@ -0,0 +1,125 @@ +public class Table { + private TableNode head; + + public Table() { + //initialize head + head = null; + } + + public void add(Card card) { + TableNode newTableNode = new TableNode(card); + newTableNode.setNext(head); + head = newTableNode; + } + + private boolean onTable(Card c) { + TableNode curr = head; + + while (curr != null) { + if (curr.getCard().toString().equals(c)) { + return true; + } + curr = curr.getNext(); + } + return false; + } + + private void removeCard(Card c) { + TableNode prev = findPrev(c); + TableNode curr = prev.getNext(); + + if (prev == null) // head remove + head = head.getNext(); + else // middle or tail remove + prev.setNext(curr.getNext()); + } + + private TableNode findPrev(Card c) { + TableNode curr = head; + TableNode prev = null; + + while (curr != null) { + if (c.equals(curr.getCard())) { + return prev; + } + else { + curr = curr.getNext(); + } + } + return null; + } + + public void removeSet(Card c1, Card c2, Card c3) { + //if 3 cards dont form a set or if any of the cards are not on the table, + // return. + //otherwise: + // remove c1, c2, and c3 preserving the relative order of the rest of the cards. + + 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() { + //if we havent stored the length of the list, we have to iterate through the + //list and count the cards. + + TableNode curr = head; + int count = 0; + + while (curr != null) { + count += 1; + curr = curr.getNext(); + } + return count; + } + + public Card getCard(int index) { + //if index is out of bounds, return null. + //otherwise: + // iterate through the list index number of times, + // return the node there + + 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() { + //get all triples of cards on the table, and check isSet(). Create a counter and + //everytime isSet() == true, update the counter by 1. + int count = 0; + int length = numCards(); + + for (int i = 0; i < length - 2; i++) { + for (int t = i + 1; t < length -1; t++) { + for (int h = t + 1; h < length; h++) { + + Card c1 = getCard(i); + Card c2 = getCard(t); + Card c3 = getCard(h); + + if (c1.isSet(c2, c3)) + count +=1; + } + } + } + return count; + } +} \ No newline at end of file diff --git a/src/TableNode.java b/src/TableNode.java new file mode 100644 index 0000000..33d8431 --- /dev/null +++ b/src/TableNode.java @@ -0,0 +1,21 @@ +public class TableNode { + private Card card; + private TableNode next; + + public TableNode(Card c) { + card = c; + next = null; + } + + public void setNext(TableNode node) { + next = node; + } + + public TableNode getNext() { + return next; + } + + public Card getCard() { + return card; + } +} \ No newline at end of file diff --git a/src/TableNodeTest.java b/src/TableNodeTest.java new file mode 100644 index 0000000..39699e0 --- /dev/null +++ b/src/TableNodeTest.java @@ -0,0 +1,22 @@ +import junit.framework.TestCase; + +public class TableNodeTest extends TestCase { + public void testTableNode() { + + Card card1 = new Card(2, 3, 3, 1); + TableNode n1 = new TableNode(card1); + assertEquals(null, n1.getNext()); + assertEquals(card1, n1.getCard()); + + Card card2 = new Card(1, 2, 3, 1); + TableNode n2 = new TableNode(card2); + assertEquals(null, n1.getNext()); + assertEquals(card2, n2.getCard()); + + Card card3 = new Card(1, 2, 2, 2); + TableNode n3 = new TableNode(card3); + assertEquals(null, n1.getNext()); + assertEquals(card3, n3.getCard()); + } + +} diff --git a/src/TableTest.java b/src/TableTest.java new file mode 100644 index 0000000..0e9fdc3 --- /dev/null +++ b/src/TableTest.java @@ -0,0 +1,56 @@ +import junit.framework.TestCase; + + +public class TableTest extends TestCase { + public void testNumCards() { + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(2, 2, 2, 2); + Card c3 = new Card(3, 3, 3, 3); + + Table t = new Table(); + + t.add(c1); + t.add(c2); + t.add(c3); + + assertEquals(3, t.numCards()); + } + + public void testRemoveSet() { + Table t = new Table(); + + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(2, 2, 2, 2); + Card c3 = new Card(3, 3, 3, 3); + Card c4 = new Card(1, 2, 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()); + } + + public void testGetCard() { + Card c1 = new Card(1, 1, 1, 1); + Card c2 = new Card(2, 2, 2, 2); + Card c3 = new Card(3, 3, 3, 3); + + Table t = new Table(); + + t.add(c1); + t.add(c2); + t.add(c3); + + assertEquals("1ROO", t.getCard(0).toString()); + assertEquals("2GTD", t.getCard(1).toString()); + assertEquals("3PSS", t.getCard(2).toString()); + } +} From 1dcea90432f70c58360aab2fac15f8d737b096f0 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Wed, 22 Apr 2015 12:06:26 -0400 Subject: [PATCH 5/9] Made some changes to Table but it still is not complete. --- src/Table.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Table.java b/src/Table.java index 9757005..b4b0963 100644 --- a/src/Table.java +++ b/src/Table.java @@ -16,7 +16,7 @@ private boolean onTable(Card c) { TableNode curr = head; while (curr != null) { - if (curr.getCard().toString().equals(c)) { + if (curr.getCard().equals(c)) { return true; } curr = curr.getNext(); @@ -43,6 +43,7 @@ private TableNode findPrev(Card c) { return prev; } else { + prev = curr; curr = curr.getNext(); } } From 2b3879b78cda86c857ed50fdc59cb56095725b55 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Thu, 23 Apr 2015 14:42:53 -0400 Subject: [PATCH 6/9] Table now works. --- src/Table.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Table.java b/src/Table.java index b4b0963..7243203 100644 --- a/src/Table.java +++ b/src/Table.java @@ -26,12 +26,13 @@ private boolean onTable(Card c) { private void removeCard(Card c) { TableNode prev = findPrev(c); - TableNode curr = prev.getNext(); if (prev == null) // head remove head = head.getNext(); - else // middle or tail remove + else {// middle or tail remove + TableNode curr = prev.getNext(); prev.setNext(curr.getNext()); + } } private TableNode findPrev(Card c) { From 91af11cdd8edb26bfc6f35b06dc0bba161b1e337 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Fri, 24 Apr 2015 09:36:14 -0400 Subject: [PATCH 7/9] Finished Game. --- src/Game.java | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/Game.java diff --git a/src/Game.java b/src/Game.java new file mode 100644 index 0000000..a873363 --- /dev/null +++ b/src/Game.java @@ -0,0 +1,80 @@ +public class Game { + private Deck d; + private Table t; + + public Game() { + d = new Deck(); + t = new Table(); + + for (int i = 0; i < 12; i++) { + t.add(d.getNext()); + } + } + + public Game(String filename) { + // uses a preset deck + d = new Deck(filename); + t = new Table(); + + while (d.hasNext() == true) { + t.add(d.getNext()); + + if (t.numCards() == 12) { + return; + } + } + } + + public int numSets() { + return t.numSets(); + } + + public int numCards() { + return t.numCards(); + } + + public void playRound() { + if (t.numSets() == 0 && d.hasNext() == true) { + for (int i = 0; i < 3; i++) { + if (d.hasNext() == false) { + return; + } + t.add(d.getNext()); + } + return; + } + + if (t.numSets() > 0 && d.hasNext() == true) { + for (int i = 0; i < t.numCards() - 2; i++) { + for (int j = i + 1; j < t.numCards() - 1; j++) { + for (int h = j + 1; h < t.numCards(); h++) { + + Card c1 = t.getCard(i); + Card c2 = t.getCard(j); + Card c3 = t.getCard(h); + + if (c1.isSet(c2,c3)) { + t.removeSet(c1,c2,c3); + } + + if (numCards() < 12 && d.hasNext() == true) { + for (int e = 0; e < 3; e++) { + t.add(d.getNext()); + } + return; + } + } + } + } + } + } + + public boolean isGameOver() { + if (d.hasNext() == false && t.numSets() == 0) { + return true; + } + else { + return false; + } + } +} \ No newline at end of file From c2980511debf73a6d9acd4987f4fd3cdda088eb8 Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Wed, 29 Apr 2015 10:27:36 -0400 Subject: [PATCH 8/9] Fixed Game --- src/Game.java | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Game.java b/src/Game.java index a873363..f51082f 100644 --- a/src/Game.java +++ b/src/Game.java @@ -44,7 +44,7 @@ public void playRound() { return; } - if (t.numSets() > 0 && d.hasNext() == true) { + else if (t.numSets() > 0 && d.hasNext() == true) { for (int i = 0; i < t.numCards() - 2; i++) { for (int j = i + 1; j < t.numCards() - 1; j++) { for (int h = j + 1; h < t.numCards(); h++) { @@ -58,7 +58,12 @@ public void playRound() { } if (numCards() < 12 && d.hasNext() == true) { - for (int e = 0; e < 3; e++) { + + while ( t.numCards() < 12) { + + if (d.hasNext() == false) { + return; + } t.add(d.getNext()); } return; @@ -67,6 +72,25 @@ public void playRound() { } } } + + else if (t.numSets() != 0 && d.hasNext() == false) { + for (int i = 0; i < t.numCards() - 2; i++) { + for (int j = i + 1; j < t.numCards() - 1; j++) { + for (int h = j + 1; h < t.numCards(); h++) { + + Card c1 = t.getCard(i); + Card c2 = t.getCard(j); + Card c3 = t.getCard(h); + + if (c1.isSet(c2,c3)) { + t.removeSet(c1,c2,c3); + return; + } + } + } + } + } + return; } public boolean isGameOver() { From 698a67c9d428a47b7e2f045b276a9bfbccd5d1bd Mon Sep 17 00:00:00 2001 From: Ryan Omdahl Date: Fri, 1 May 2015 10:00:28 -0400 Subject: [PATCH 9/9] The Mote Carlo simulation (main method) complete. --- src/GameAverage.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/GameAverage.java diff --git a/src/GameAverage.java b/src/GameAverage.java new file mode 100644 index 0000000..895f37a --- /dev/null +++ b/src/GameAverage.java @@ -0,0 +1,19 @@ +public class GameAverage { + public static void main(String[] args) { + + float setSum = 0; + float cardSum = 0; + + for (int i = 0; i < 1000000; i++) { + Game g = new Game(); + setSum += g.numSets(); + + while (g.isGameOver() == false) { + g.playRound(); + } + cardSum += g.numCards(); + } + System.out.println ("Average number of sets from 12 cards: " + setSum/1000000); + System.out.println ("Average number of remaining cards at the end of a game: " + cardSum/1000000); + } +} \ No newline at end of file