diff --git a/src/3cards.dat b/src/3cards.dat new file mode 100644 index 0000000..cbbb321 --- /dev/null +++ b/src/3cards.dat @@ -0,0 +1,3 @@ +1 2 3 1 +2 1 3 2 +3 3 1 2 \ No newline at end of file diff --git a/src/Card.java b/src/Card.java old mode 100755 new mode 100644 index 9eed9a5..7820530 --- a/src/Card.java +++ b/src/Card.java @@ -1,6 +1,129 @@ public class Card { - // Create the rest of this class yourself + private int quantity; + private int color; + private int shading; + private int shape; + private int value; + private String quantString; + private String colorString; + private String shadingString; + private String shapeString; + + public Card(int theQuantity, int theColor, int theShading, int theShape) { + if (theQuantity < 1 || theQuantity > 3) { + quantity = (((theQuantity % 3) + 3) % 3) + 1; + } + else { + quantity = theQuantity; + } + + if (theColor < 1 || theColor > 3) { + color = (((theColor % 3) + 3) % 3) + 1; + } + else { + color = theColor; + } + + if (theShading < 1 || theShading > 3) { + shading = (((theShading % 3) + 3) % 3) + 1; + } + else { + shading = theShading; + } + + if (theShape < 1 || theShape > 3) { + shape = (((theShape % 3) + 3) % 3) + 1; + } + else { + shape = theShape; + } + + + + } + //Got the valueToFix from class// + private int the(int valueToFix) { + if (valueToFix < 1 || valueToFix > 3) + return (((valueToFix % 3) + 3) % 3) + 1; + else + return valueToFix; + } + + //getValue() goes with valueToFix above// + public int getValue() { + return value; + } + + + + public int getQuantity() { + return quantity; + } + + public int getColor() { + return color; + } + + public int getShading() { + return shading; + } + + public int getShape() { + return shape; + } + + public boolean isSet(Card card1, Card card2) { + boolean isSet = true; + return (quantity + card1.getQuantity() + card2.getQuantity()) % 3 == 0 && + (color + card1.getColor() + card2.getColor()) % 3 == 0 && + (shading + card1.getShading() + card2.getShading()) % 3 == 0 && + (shape + card1.getShape() + card2.getShape()) % 3 == 0; + + + } + + public String toString() { + String string = ""; + String quantString = ""; + String colorString = ""; + String shadingString = ""; + String shapeString = ""; + + if (quantity == 1) + quantString = "1"; + if (quantity == 2) + quantString = "2"; + if (quantity == 3) + quantString = "3"; + + + if (color == 1) + colorString = "R"; + if (color == 2) + colorString = "G"; + if (color == 3) + colorString = "P"; + + if (shading == 1) + shadingString = "O"; + if (shading == 2) + shadingString = "T"; + if (shading == 3) + shadingString = "S"; + + if (shape == 1) + shapeString = "O"; + if (shape == 2) + shapeString = "D"; + if (shape == 3) + shapeString = "S"; + + return string = quantString + colorString + shadingString + shapeString; + + } + + 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..56a53c1 --- /dev/null +++ b/src/CardTest.java @@ -0,0 +1,77 @@ +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 testTheSetValues() { + Card card1 = new Card(1, 1, 1, 1); + assertEquals(1, card1.getQuantity()); + assertEquals(1, card1.getColor()); + assertEquals(1, card1.getShading()); + assertEquals(1, card1.getShape()); + assertEquals("1ROO", card1.toString()); + } + + public void testNegativeSetValues() { + Card card1 = new Card(-4, -4, -4, -4); + assertEquals("3PSS", card1.toString()); + } + + public void testSetIsLegal() { + Card card1 = new Card(2, 2, 1, 1); + Card card2 = new Card(2, 2, 2, 2); + Card card3 = new Card(2, 2, 3, 3); + assertEquals(true, card1.isSet(card2, card3)); + + } + + public void testSetIsNotLegal() { + Card card1 = new Card(1, 1, 2, 2); + Card card2 = new Card(2, 1, 2, 2); + Card card3 = new Card(2, 2, 2, 2); + assertEquals(false, card2.isSet(card1, card3)); + } + + public void testAllCardsSame() { + Card card1 = new Card(3, 2, 1, 3); + Card card2 = new Card(3, 2, 1, 3); + Card card3 = new Card(3, 2, 1, 3); + assertEquals(true, card3.isSet(card1, card2)); + } + + public void testSameColor() { + Card card1 = new Card(1, 1, 2, 3); + Card card2 = new Card(2, 1, 1, 2); + Card card3 = new Card(3, 1, 3, 1); + assertEquals(true, card1.isSet(card2, card3)); + } + + public void testAllRandomCards() { + Card card1 = new Card(1, 2, 3, 1); + Card card2 = new Card(2, 3, 1, 2); + Card card3 = new Card(3, 1, 2, 3); + assertEquals(true, card2.isSet(card1, card3)); + } + + public void testSameShade() { + Card card1 = new Card(1, 3, 3, 2); + Card card2 = new Card(2, 2, 3, 2); + Card card3 = new Card(2, 3, 3, 2); + assertEquals(false, card3.isSet(card2, card1)); + } + + + + +} diff --git a/src/Deck.java b/src/Deck.java old mode 100755 new mode 100644 index ab3a2a3..916fa1f --- a/src/Deck.java +++ b/src/Deck.java @@ -2,9 +2,59 @@ 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 + public ArrayList cards = new ArrayList(81); + public int nextCardIndex; + + public Deck() { + //Deck d = new Deck()// + //while(d.hasNext())// + cards = new ArrayList(81); + for (int cardA = 1; cardA < 4; cardA++) { + for (int cardB = 1; cardB < 4; cardB++) { + for (int cardC = 1; cardC < 4; cardC++) { + for (int cardD = 1; cardD < 4; cardD++) { + cards.add(new Card(cardA, cardB, cardC, cardD)); + } + } + } + } + nextCardIndex = 0; + Collections.shuffle(cards); + + } + + public boolean hasNext() { + //False when nextCardIndex is out of bounds, so when it is the same as the length// + //True if nextCardIndex is valid// + if (nextCardIndex >= cards.size()) { + return false; + } + else { + return true; + } + + + } + + public Card getNext() { + //Got from notes taken in class :if hasNext() returns false, then it wil return null but if not increment index first then return one less than index// + //so then we would return (nextCardIndex - 1) if hasNext() is true// + if (hasNext() == true) { + nextCardIndex++; + 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..fe0702c --- /dev/null +++ b/src/DeckTest.java @@ -0,0 +1,44 @@ +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 testDeckWorks() { + Deck d = new Deck(); + assertEquals(81, d.cards.size()); + + } + + public void testHasNext() { + Deck d = new Deck(); + assertEquals(true, d.hasNext()); + } + + public void testEachCardsPosition() { + Deck d = new Deck("3cards.dat"); + + Card card1 = new Card(1, 2, 3, 1); + assertEquals(true, d.hasNext()); + assertEquals(true, card1.equals(d.getNext())); + + Card card2 = new Card(2, 1, 3, 2); + assertEquals(true, d.hasNext()); + assertEquals(true, card2.equals(d.getNext())); + + Card card3 = new Card(3, 3, 1, 2); + assertEquals(true, d.hasNext()); + assertEquals(true, card3.equals(d.getNext())); + + } + +} diff --git a/src/Game.java b/src/Game.java new file mode 100644 index 0000000..b9ea11d --- /dev/null +++ b/src/Game.java @@ -0,0 +1,98 @@ +public class Game { + private Table t; + private Deck d; + + public Game() { + //12 cards on the table, randomly generated deck// + t = new Table(); + d = new Deck(); + + for (int i = 0; i < 12; i++) { + t.add(d.getNext()); + } + } + + public Game(String theString) { + //Starts with 12 cards on the table// + //Number of cards on table is either 12 or the number of cards in the deck, whatever one is smaller// + t = new Table(); + d = new Deck(theString); + + int i = 0; + while (d.hasNext() == true) { + t.add(d.getNext()); + i += 1; + + if (t.numCards() == 12) { + return; + } + } + } + + public int numSets() { + //This method would return the number of sets in the table// + return t.numSets(); + } + + public int numCards() { + //This method would return number of cards in the table// + return t.numCards(); + } + + public void playRound() { + //Worked with John Ferguson in lab 4/23// + //When no sets on table, but still cards in deck, add three cards to move to next round// + if (t.numSets() == 0 && d.hasNext() == true) { + for (int i = 0; i < 3; i++) { + if (d.hasNext() == true) { + t.add(d.getNext()); + } + } + return; + } + //12 cards on table and cards in deck, move to next round by removing one set then adding three cards// + //If starts with more than 12 cards then we remove a set but don't add any more cards// + //At least one set on the table but no cards left in deck, move to next round by removing a set// + if (t.numSets() > 0) { + + for (int m = 0; m < t.numCards() - 2; m++) { + for (int n = m + 1; n < t.numCards() - 1; n++) { + for (int p = n + 1; p < t.numCards(); p++) { + + Card card1 = t.getCard(m); + Card card2 = t.getCard(n); + Card card3 = t.getCard(p); + + if (card1.isSet(card2, card3)) { + t.removeSet(card1, card2, card3); + + if (t.numCards() < 12 && d.hasNext() == true) { + for (int i = 0; i < 3; i++) { + if (d.hasNext() == true) { + t.add(d.getNext()); + } + return; + } + } + } + } + } + } + } + } + + + public boolean isGameOver() { + //True when no sets on table and no cards in the deck, then the game is over// + //Otherwise false, game is still on// + if (d.hasNext() == false && t.numSets() == 0) { + return true; + + } + else { + return false; + } + + + } +} \ No newline at end of file diff --git a/src/GameTest.java b/src/GameTest.java new file mode 100644 index 0000000..5a06dcc --- /dev/null +++ b/src/GameTest.java @@ -0,0 +1,187 @@ +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 GameTest 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 testGameWorks() { + Game theGame = new Game(); + + assertEquals(theGame.numCards(), 12); + theGame.playRound(); + + } + 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(10, g.numCards()); + } + + public void testDeckLessThanTwelve() + { + Game g = new Game("7cardsMilestone.dat.txt"); + + assertEquals(7, g.numCards()); + g.playRound(); + + assertEquals(1, g.numCards()); + } + + public void testGameOverEmptyTable() + { + Game g = new Game("12cards4setsMilestone.dat.txt"); + + assertEquals(12, g.numCards()); + assertEquals(4, 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()); + assertEquals(0, 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(6, g.numCards()); + assertFalse(g.isGameOver()); + + g.playRound(); + assertEquals(3, g.numCards()); + assertTrue(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(10, g.numCards()); + assertEquals(3, g.numSets()); + assertFalse(g.isGameOver()); + + g.playRound(); + assertEquals(8, 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/Main.java b/src/Main.java new file mode 100644 index 0000000..37e120e --- /dev/null +++ b/src/Main.java @@ -0,0 +1,33 @@ +public class Main { + public static void main(String[] args) { + //Number of games played in order to find the average, I used 100,000// + int numGames = 100000; + + //Tried these as an int and a float, the float gave a more accurate number.// + //randomCollection is the sum for the average number of sets in random collection.// + //cardsLeft is the sum for the average number of cards left at end of game.// + float randomCollection = 0; + float cardsLeft = 0; + + //For loop in order to state how many rounds to play (100,000).// + for (int i = 0; i < 100000; i++) { + Game setGame = new Game(); + randomCollection += setGame.numSets(); + + + //need the while loop to check to make sure game is not over, that playRound can play for 100,000 games.// + while (setGame.isGameOver() == false) { + setGame.playRound(); + } + + cardsLeft += setGame.numCards(); + } + + //Printing out each average for the sum divided by the number of games played.// + System.out.println("Average number of sets in a random collection of 12 cards is:" + randomCollection/100000); + + System.out.println("Average number of cards left at the end of the game are:" + cardsLeft/100000); + } +} + + \ No newline at end of file diff --git a/src/Table.java b/src/Table.java new file mode 100644 index 0000000..0ef0147 --- /dev/null +++ b/src/Table.java @@ -0,0 +1,162 @@ +public class Table { + private TableNode head; + private int theLength; + + public Table() { + //intialize head// + //intialized the length as well// + head = null; + theLength = 0; + + } + + public void add(Card theCard) { + //head insert card// + TableNode theNode = new TableNode(theCard); + theLength += 1; + if (head == null) { + head = theNode; + } + else { + theNode.setNext(head); + head = theNode; + } + + } + + private boolean theTable(Card theCard) { + //Got a pointer from a friend in class// + TableNode nerf = head; + while (nerf != null) { + if (nerf.getCard().equals(theCard)) { + return true; + } + nerf = nerf.getNext(); + } + return false; + } + + private void removeCard(Card theCard) { + //removeCard helps to set up for removeSet// + TableNode nerf= findNerf(theCard); + theLength -= 1; + if (nerf == null) { + head = head.getNext(); + } + else { + TableNode buff = nerf.getNext(); + nerf.setNext(buff.getNext()); + } + } + + private TableNode findNerf(Card theCard){ + //in order for removeCard to work had to make a method of findNerf, which I used in removeCard// + TableNode nerf = null; + TableNode buff = head; + + while (buff != null) { + Card buffCard = buff.getCard(); + if (buffCard.equals(theCard)) { + return nerf; + } + nerf = buff; + buff = buff.getNext(); + } + return null; + } + + + + public void removeSet(Card card1, Card card2, Card card3) { + //Worked with John Ferguson in lab 4/23 to fix Table// + //If 3 cards don't form a set or if any of the cards are not on the table, return// + //Otherwise: remove card1, card2, card3 preserving the relative order of the rest of the cards// + //since I made a removeCard method, I was able to use it in the removeSet method to help remove the cards from the set// + TableNode nerf = head; + TableNode buff = null; + + if (!card1.isSet(card2, card3)) { + return; + } + + if (!theTable(card1)) { + return; + } + + if (!theTable(card2)) { + return; + } + + if (!theTable(card3)) { + return; + } + + removeCard(card1); + removeCard(card2); + removeCard(card3); + + } + + public int numCards() { + //If we haven't stored the length of the list, we have to iterate through the list and count the cards (while loop)// + TableNode nerf = head; + int theCards = 0; + if (nerf == null) { + return 0; + } + while (nerf != null) { + theCards += 1; + nerf = nerf.getNext(); + } + return theCards; + } + + + public Card getCard(int index) { + //Iterate through the list index number of times, return the node there// + //If index is out of bounds, return null// + TableNode buff = head; + if (index >= theLength || buff == null) { + return null; + } + + if (index == 0) { + return buff.getCard(); + } + + else { + for (int i = 0; i < index; i++) { + buff = buff.getNext(); + } + return buff.getCard(); + } + + } + + + public int numSets() { + //Get all triples of cards on the table and check isSet on each one (3 deep nested loop)// + + int theSetIs = 0; + + for (int m = 0; m < theLength - 2; m++) { + for (int n = m + 1; n < theLength - 1; n++) { + for (int p = n + 1; p < theLength; p++) { + + Card cardA = getCard(m); + Card cardB = getCard(n); + Card cardC = getCard(p); + if (cardA.isSet(cardB, cardC)) { + theSetIs += 1; + } + + } + } + } + return theSetIs; + } + +} + + + \ No newline at end of file diff --git a/src/TableNode.java b/src/TableNode.java new file mode 100644 index 0000000..73f237e --- /dev/null +++ b/src/TableNode.java @@ -0,0 +1,27 @@ +public class TableNode { + private Card card; + private TableNode next; + + public TableNode(Card superFantasticCard) { + card = superFantasticCard; + next = null; + } + + public void setNext(TableNode theNext) { + next = theNext; + + } + + 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..3986115 --- /dev/null +++ b/src/TableNodeTest.java @@ -0,0 +1,60 @@ +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 TableNodeTest 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 testNodeWithMultipleCards() { + Card card1 = new Card(1, 2, 1, 2); + TableNode tipTopNode1 = new TableNode(card1); + assertEquals(card1, tipTopNode1.getCard()); + assertEquals(true, tipTopNode1.getCard().equals(card1)); + + Card card2 = new Card(2, 3, 2, 3); + TableNode tipTopNode2 = new TableNode(card2); + assertEquals(card2, tipTopNode2.getCard()); + assertEquals(true, tipTopNode2.getCard().equals(card2)); + + Card card3 = new Card(1, 3, 1, 3); + TableNode tipTopNode3 = new TableNode(card3); + assertEquals(card3, tipTopNode3.getCard()); + assertEquals(true, tipTopNode3.getCard().equals(card3)); + + Card card4 = new Card(1, 2, 3, 1); + TableNode tipTopNode4 = new TableNode(card4); + assertEquals(card4, tipTopNode4.getCard()); + assertEquals(true, tipTopNode4.getCard().equals(card4)); + + Card card5 = new Card(2, 3, 1, 2); + TableNode tipTopNode5 = new TableNode(card5); + assertEquals(card5, tipTopNode5.getCard()); + assertEquals(true, tipTopNode5.getCard().equals(card5)); + + Card card6 = new Card(1, 1, 1, 1); + TableNode tipTopNode6 = new TableNode(card6); + assertEquals(card6, tipTopNode6.getCard()); + assertEquals(true, tipTopNode6.getCard().equals(card6)); + + } + + + public void testNewNodeWithOneCard() { + Card superCard = new Card(1, 2, 3, 1); + TableNode tipTopNode = new TableNode(superCard); + + assertEquals(null, tipTopNode.getNext()); + assertEquals(superCard, tipTopNode.getCard()); + assertEquals(true, tipTopNode.getCard().equals(superCard)); + + } +} diff --git a/src/TableTest.java b/src/TableTest.java new file mode 100644 index 0000000..683ba8a --- /dev/null +++ b/src/TableTest.java @@ -0,0 +1,61 @@ +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 TableTest 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 testNumSet() { + Table tipTop = new Table(); + Card card1 = new Card(1, 2, 1, 2); + tipTop.add(card1); + assertEquals(0, tipTop.numSets()); + + Card card2 = new Card(3, 1, 3, 1); + tipTop.add(card2); + assertEquals(0, tipTop.numSets()); + + Card card3 = new Card(2, 2, 2, 2); + tipTop.add(card3); + assertEquals(0, tipTop.numSets()); + } + + + public void testNewTableThatIsEmpty() { + Table tipTop = new Table(); + + Card card1 = new Card(1, 2, 3, 1); + Card card2 = new Card(2, 3, 1, 2); + Card card3 = new Card(3, 1, 2, 3); + + assertEquals(null, tipTop.getCard(0)); + assertEquals(0, tipTop.numCards()); + assertEquals(tipTop.numCards(), 0); + + } + + public void testACardInTable() { + Table tipTop = new Table(); + Card card = new Card(1, 2, 3, 1); + tipTop.add(card); + + assertEquals(true, tipTop.getCard(0).equals(card)); + assertEquals(null, tipTop.getCard(1)); + assertEquals(null, tipTop.getCard(4)); + + assertEquals(1, tipTop.numCards()); + } + + + + + +}