diff --git a/out/production/sp21-cs242-assignment1/CardManager.class b/out/production/sp21-cs242-assignment1/CardManager.class
index 3b553b8e9cce60d30360c982042f9805d8b9eeae..684095064f264898370a598bceaec72487f22763 100644
Binary files a/out/production/sp21-cs242-assignment1/CardManager.class and b/out/production/sp21-cs242-assignment1/CardManager.class differ
diff --git a/out/production/sp21-cs242-assignment1/CardParser.class b/out/production/sp21-cs242-assignment1/CardParser.class
index 91bfe36bc32cfed6704cc7ea4288d3f3586384d5..6c9bc09a1dea0efd95dc1d18883109a6b2fa6a96 100644
Binary files a/out/production/sp21-cs242-assignment1/CardParser.class and b/out/production/sp21-cs242-assignment1/CardParser.class differ
diff --git a/out/production/sp21-cs242-assignment1/CmdUI.class b/out/production/sp21-cs242-assignment1/CmdUI.class
index 9e4a053d8df256d5f7e95477d0e4e5fc5397a49c..8a634436ce8e7364bbb853031ae91061a657f900 100644
Binary files a/out/production/sp21-cs242-assignment1/CmdUI.class and b/out/production/sp21-cs242-assignment1/CmdUI.class differ
diff --git a/out/production/sp21-cs242-assignment1/Game.class b/out/production/sp21-cs242-assignment1/Game.class
index d5c853fa460b7ce595a9af05c64a4e50bd7a828d..4058f84c7860f8f236114c72a56bd777e7b3ccd2 100644
Binary files a/out/production/sp21-cs242-assignment1/Game.class and b/out/production/sp21-cs242-assignment1/Game.class differ
diff --git a/out/production/sp21-cs242-assignment1/Player.class b/out/production/sp21-cs242-assignment1/Player.class
index d3baf62c663311ac8df80a26813c027b722e1778..a7f7f5cb0581e12e6fe2b2ac52b116e83a8c105c 100644
Binary files a/out/production/sp21-cs242-assignment1/Player.class and b/out/production/sp21-cs242-assignment1/Player.class differ
diff --git a/out/production/sp21-cs242-assignment1/RuleController.class b/out/production/sp21-cs242-assignment1/RuleController.class
index 4cd51c49ff5cbf5b60e2373a96937b5d4bb4fb78..176269a21e1de069cbaeeff448911a44caf29392 100644
Binary files a/out/production/sp21-cs242-assignment1/RuleController.class and b/out/production/sp21-cs242-assignment1/RuleController.class differ
diff --git a/out/test/sp21-cs242-assignment1/PlayerTest.class b/out/test/sp21-cs242-assignment1/PlayerTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..014a5f9933fb477faa6762523256715174095f82
Binary files /dev/null and b/out/test/sp21-cs242-assignment1/PlayerTest.class differ
diff --git a/out/test/sp21-cs242-assignment1/RuleControllerTest.class b/out/test/sp21-cs242-assignment1/RuleControllerTest.class
index 9999d71a7bba788c9c2c9c63cffae4034f977b94..793251c85707ab4b1dbfc5249475c7a9f8342b6a 100644
Binary files a/out/test/sp21-cs242-assignment1/RuleControllerTest.class and b/out/test/sp21-cs242-assignment1/RuleControllerTest.class differ
diff --git a/out/test/sp21-cs242-assignment1/cardDealTest.class b/out/test/sp21-cs242-assignment1/cardDealTest.class
index 33cd2ce1b1236cb0a8e86a00b7ae092483bc6674..5c5c2ef16a4255dd6527815e558eee16eaf2d000 100644
Binary files a/out/test/sp21-cs242-assignment1/cardDealTest.class and b/out/test/sp21-cs242-assignment1/cardDealTest.class differ
diff --git a/src/Test/PlayerTest.java b/src/Test/PlayerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..62be5d0539653e4524e7686a3ed377b37307bc4e
--- /dev/null
+++ b/src/Test/PlayerTest.java
@@ -0,0 +1,85 @@
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+/**
+ * The last part of test:
+ * Test the behavior of player when they ACTUALLY PLAY A CARD
+ * <p>
+ * Dependency: Game, ruleController (all test done), cardManager, CmdUI, GUI
+ * <p>
+ * Notice ruleController only judge validity & do update in game state
+ * and pass them as information for player. Thus whether player could behave
+ * correctly with given information should be tested.
+ */
+
+class PlayerTest {
+
+    @Test
+    /**
+     * Test when a card is played, it goes to the discard pile
+     * Run 100 times to cancel randomness
+     */
+    void TestUserPlayWillGoToDiscardPile() {
+        for (int i = 0; i < 100; i++) {
+            Game game = new Game(1);
+            Player player = game.players.get(0);
+            player.drawCards(50);
+
+            ArrayList<Integer> legalCards = player.findLegalCard();
+            int cardToPlay = legalCards.get(0);
+
+            // make sure this play is legal
+            assert (player.optionPlayOwnedCard(cardToPlay));
+
+            // make sure the top of discard of pile is the card just played
+            assert (game.gameCardManager.getDiscardPile().get(0) == cardToPlay);
+
+            //make sure the player does not own this card anymore
+            assert (!player.getCards().contains(cardToPlay));
+        }
+    }
+
+
+    /**
+     * Test the situation where player choose to draw a card
+     * Run 100 times to cancel randomness
+     */
+    @Test
+    void testOptionDrawAndPlay() {
+        for (int i = 0; i < 100; i++) {
+            Game game = new Game(1);
+            Player player = game.players.get(0);
+            int cardPlayerWillGet = game.gameCardManager.getCardPile().get(0);
+            boolean newCardIsValid = game.ruler.isValidPlay(player, cardPlayerWillGet, false);
+            boolean played = player.optionDrawCardAndPlay();
+
+            if (newCardIsValid) {
+                // player should immediately play the card
+                assert (played);
+                assert (game.gameCardManager.getDiscardPile().get(0) == cardPlayerWillGet);
+                assert (!player.getCards().contains(cardPlayerWillGet));
+
+            } else {
+                assert (!played);
+                assert (player.getCards().contains(cardPlayerWillGet));
+            }
+        }
+    }
+
+
+    @Test
+    /**
+     *  Test 3
+     *  Test game will end when a user wins
+     */
+    void testGameCloseWhenPlayerWin() {
+        Game game = new Game(1);
+        game.gameStart();
+        assert(game.rounds == 7);
+    }
+}
\ No newline at end of file
diff --git a/src/Test/RuleControllerTest.java b/src/Test/RuleControllerTest.java
index ddae6d42ab23f69c801c2ff4c408014be80eae33..27607137b19199a896baa06d1a40f0f8d30c4fff 100644
--- a/src/Test/RuleControllerTest.java
+++ b/src/Test/RuleControllerTest.java
@@ -255,16 +255,12 @@ class RuleControllerTest {
         RuleController ruler = new RuleController();
         Player player = playerAllCards(); // a player who owns all cards
 
-        setCurrentState(ruler, "red", "none", "8", 0);
-
-        ArrayList<Integer> validByRuler = getAllLegalCardsByRuler(ruler, player);
-        ArrayList<Integer> groundTruth = groundTruthGenerator(ruler, player,
-                ruler.getMatchableColor(), ruler.getMatchableNumber(), ruler.getMatchableSymbol());
-
         // current player plays red 0
+        setCurrentState(ruler, "red", "none", "8", 0);
         ruler.isValidPlay(player, 25, true);
         assert(checkStateUpdatedCorrectly(ruler, "red", "none", "0", 0));
 
+
         // current player plays red skip card
         setCurrentState(ruler, "red", "none", "8", 0);
         ruler.isValidPlay(player, 20,true);
@@ -356,6 +352,49 @@ class RuleControllerTest {
 
     }
 
+    /**
+     * 13. Test checkSkipAndDraw
+     * If a player should be skipped this round, he should then draw the cumulative penalty cards
+     * Behavior of card Manager is also checked in this test case
+     */
+    @Test
+    void testCheckSkipAndDraw() {
+        Game game = new Game(1);
+        Player player = player_AllColor_Y_WildDraw4_Y(); // he cannot play wildDraw4 anyway
+        player.playerID = 2;
+        player.gameController = game;
+        player.ruler = game.ruler;
+
+        // case 1: Red skip - player should not be skipped
+        int playerNumCheckPoint1 = player.getCards().size();
+        int pileNumCheckPoint1 = game.gameCardManager.numCardLeft();
+        setCurrentState(game.ruler, "red", "skip", "none", 3);
+        assert(game.ruler.checkSkipAndDraw(player));
+        assert(player.getCards().size() == playerNumCheckPoint1);
+        assert(game.gameCardManager.numCardLeft() == pileNumCheckPoint1);
+
+        // case2: Blue draw2 - player should be skipped and draw 2
+        int playerNumCheckPoint2 = player.getCards().size();
+        int pileNumCheckPoint2 = game.gameCardManager.numCardLeft();
+        setCurrentState(game.ruler, "blue", "draw2", "none", 1);
+        game.ruler.increasePenaltyDraw(2);
+        assert(game.ruler.checkSkipAndDraw(player));
+        assert(player.getCards().size() == playerNumCheckPoint2 + 2);
+        assert(game.gameCardManager.numCardLeft() == pileNumCheckPoint2 - 2);
+        game.ruler.resetPenaltyDraw();
+
+
+        // case3: wildDraw4 - player should be skipped and draw 4
+        int playerNumCheckPoint3 = player.getCards().size();
+        int pileNumCheckPoint3 = game.gameCardManager.numCardLeft();
+        setCurrentState(game.ruler, "blue", "draw2", "none", 2);
+        game.ruler.increasePenaltyDraw(4);
+        assert(game.ruler.checkSkipAndDraw(player));
+        assert(player.getCards().size() == playerNumCheckPoint3 + 4);
+        assert (game.gameCardManager.numCardLeft() == pileNumCheckPoint3 - 4);
+        game.ruler.resetPenaltyDraw();
+
+    }
 
 
 
@@ -433,7 +472,7 @@ class RuleControllerTest {
      * @return
      */
     private Player player_Red_N_WildDraw4_Y() {
-        Player player = new Player(0, null);
+        Player player = new Player(0, null, true);
         player.addOneCard(26); // green 1
         player.addOneCard(51); // blue 1
         player.addOneCard(76); // yellow 1
@@ -448,7 +487,7 @@ class RuleControllerTest {
      * @return
      */
     private Player player_AllColor_Y_WildDraw4_Y() {
-        Player player = new Player(0, null);
+        Player player = new Player(0, null, true);
         player.addOneCard(1); // red 1
         player.addOneCard(26); // green 1
         player.addOneCard(51); // blue 1
@@ -463,7 +502,7 @@ class RuleControllerTest {
      * This player should not be able to play wildDraw4 card
      */
     private Player playerAllCards() {
-        Player player = new Player(0, null);
+        Player player = new Player(0, null, true);
         for (int i = 1; i <= 108; i++) {
             player.addOneCard(i);
         }
@@ -485,6 +524,9 @@ class RuleControllerTest {
         ruler.setNextPlayerSkiplevel(level);
     }
 
+    /**
+     * check all game states are correct based on passed ground truth
+     */
     private boolean checkStateUpdatedCorrectly(RuleController ruler,
                                                String truthColor,
                                                String truthSymbol,
diff --git a/src/Test/cardDealTest.java b/src/Test/cardDealTest.java
index 130070a1c3f65a0eb7fc48b8fb8aed5ce92e7d11..ef4a56a95d377e2fea8134803295791234a300c6 100644
--- a/src/Test/cardDealTest.java
+++ b/src/Test/cardDealTest.java
@@ -15,7 +15,8 @@ class cardDealTest {
 
     @Test
     /**
-     * Test card manager can initialize 108 cards correctly
+     * Test 1
+     * make sure card manager can initialize 108 cards correctly
      */
     void testInitialization()  throws Exception {
         CardManager cardManager = new CardManager();
@@ -27,6 +28,7 @@ class cardDealTest {
 
     @Test
     /**
+     * Test 2
      * Given n players, test behavior of initial deal, as well as behavior of draw pile
      * dependencies: Player.drawCards, CardManager.*
      */
@@ -54,6 +56,7 @@ class cardDealTest {
 
     @Test
     /**
+     * Test 3
      * Test the behavior of Player.drawCards
      * under the condition where draw pile is not enough to draw, should draw from discard pile instead
      * case 1: completely draw from discard pile
@@ -80,6 +83,7 @@ class cardDealTest {
 
     @Test
     /**
+     * Test 4
      * Test the behavior of Player.drawCards
      * under the condition where draw pile is not enough to draw, should draw from discard pile instead
      * case 2: partially from draw pile, partially from discard pile
diff --git a/src/UNO/CardManager.java b/src/UNO/CardManager.java
index 949e5888392a6fd820b865342b24e17c5560cc27..5c8da460e3bdccfaf34f403586f117299f79fb01 100644
--- a/src/UNO/CardManager.java
+++ b/src/UNO/CardManager.java
@@ -87,9 +87,15 @@ public class CardManager {
     public int numLeftDiscardPile() { return discardPile.size(); }
 
     /**
-     * get all the cards currently in card pile as a Array list
+     * get all the cards currently in draw pile as a Array list
      */
     public ArrayList<Integer> getCardPile() { return cardPile; }
 
+    /**
+     * get all the cards currently in discard pile as a Array list
+     */
+    public ArrayList<Integer> getDiscardPile() { return discardPile; }
+
+
 }
 
diff --git a/src/UNO/CardParser.java b/src/UNO/CardParser.java
index b5d740b951d0f033a33791693856a328368dc21c..f43ce3a47d1e9b544ece8d1d8ba9ea5aab5a381f 100644
--- a/src/UNO/CardParser.java
+++ b/src/UNO/CardParser.java
@@ -110,7 +110,7 @@ class CardParser {
      * judge whether a card is a wild card - that is, whether user can decalre a color
      * @param cardID id of card
      */
-    public boolean isWildCard(int cardID) {
+    public boolean isNonColorCard(int cardID) {
         return cardID > COLORED_CARD_NUM;
     }
 }
\ No newline at end of file
diff --git a/src/UNO/CmdUI.java b/src/UNO/CmdUI.java
index 9da970239c7a9feddedc7a73aca19dbfc3815629..d73f23c6790bd177033c26abb2efeac8ca048d0e 100644
--- a/src/UNO/CmdUI.java
+++ b/src/UNO/CmdUI.java
@@ -1,5 +1,9 @@
 import java.util.Scanner;
 
+
+/**
+ * Prepared for assignment 1.1
+ */
 public class CmdUI {
     Player player;
     CardParser parser;
@@ -70,8 +74,7 @@ public class CmdUI {
             }
         }
 
-        if (parser.isWildCard(cardID)) {
-            // to implement
+        if (parser.isNonColorCard(cardID)) {
             int colorChosen = -1;
             while (colorChosen < 0) {
                 promptChooseColor();
@@ -90,7 +93,7 @@ public class CmdUI {
             player.getCards().remove(chosenCardIndex);
             gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
 
-            if (parser.isWildCard(cardID)) {
+            if (parser.isNonColorCard(cardID)) {
                 // to implement
                 int colorChosen = -1;
                 while (colorChosen < 0) {
diff --git a/src/UNO/Game.java b/src/UNO/Game.java
index 7d5ec00f0540eb62d3018d436273b86cdb28f726..b42773b4c659e6a051ed825a8eda79ab5fe5bd71 100644
--- a/src/UNO/Game.java
+++ b/src/UNO/Game.java
@@ -10,7 +10,7 @@ public class Game {
     private static CardParser parser = new CardParser();
     private static final int INIT_DRAW = 7; // every player get 7 cards at beginning
 
-    private int rounds = 1;
+    public int rounds = 1;
     public RuleController ruler;
     public CardManager gameCardManager;
     public ArrayList<Player> players;
@@ -31,7 +31,7 @@ public class Game {
 
         // playerID starts from 0 !!!!!
         for (int i = 0; i < playerNum; i++) {
-            Player player = new Player(i, this);
+            Player player = new Player(i, this, true);
             player.drawCards(INIT_DRAW);
             players.add(player);
         }
@@ -63,7 +63,7 @@ public class Game {
      *  Run one round of UNO
      *  very import function !
      */
-    private void runOneRound() {
+    public void runOneRound() {
         ruler.reportCurrentState(this);
         System.out.println("It's now Player " + (currentPlayerID + 1) + "'s turn...");
         Player currentPlayer = players.get(currentPlayerID);
@@ -72,9 +72,21 @@ public class Game {
     }
 
     public void gameStart() {
-        while (rounds <= 2) {
-            System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n<<<<<<<<<<<<<<<<<<<<<<<< Round" + rounds + " >>>>>>>>>>>>>>>>>>>>>>>>>\n\n");
-            runOneRound();
+
+        // left for assignment 1.1
+//        while (rounds <= 2) {
+//            System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n<<<<<<<<<<<<<<<<<<<<<<<< Round" + rounds + " >>>>>>>>>>>>>>>>>>>>>>>>>\n\n");
+//            runOneRound();
+//            updateNextPlayerID();
+//            rounds++;
+//        }
+
+        while (true) {
+            Player currentPlayer = players.get(currentPlayerID);
+            currentPlayer.runOneRoundForTesting();
+            if (currentPlayer.playerWin()) {
+                break;
+            }
             updateNextPlayerID();
             rounds++;
         }
diff --git a/src/UNO/Player.java b/src/UNO/Player.java
index cbf50ab50ec8a512853f5c4067a31c4593facc3f..4aa2296771bdfb3a9dad0ced6a79cf6373e27017 100644
--- a/src/UNO/Player.java
+++ b/src/UNO/Player.java
@@ -1,24 +1,24 @@
-import java.lang.reflect.Array;
+import javax.xml.stream.FactoryConfigurationError;
 import java.util.*;
 
 public class Player {
     public static CardParser parser;
     private final ArrayList<Integer> cards;
     public int playerID;
-    public static Game gameController;
-    public static RuleController ruler;
+    public Game gameController;
+    public RuleController ruler;
     public CmdUI prompterCmd;
     public GUI prompterGUI;
 
 
-    public Player(int ID, Game game) {
+    public Player(int ID, Game game, Boolean useCmdAsUI) {
         playerID = ID;
-        cards = new ArrayList<Integer>();
+        cards = new ArrayList<>();
         gameController = game;
         ruler = (game != null) ? game.ruler : null;  // for testing purpose
         parser = (game != null) ? RuleController.parser : null;
-        prompterCmd = new CmdUI(this);
-        prompterGUI = null;
+        prompterCmd = useCmdAsUI ? new CmdUI(this) : null;
+        prompterGUI = useCmdAsUI ? null : new GUI(this);
     }
 
     /**
@@ -37,7 +37,7 @@ public class Player {
             System.out.println("\n\n===================================================================");
             System.out.println("Currently have " + cards.size() + " cards:");
             for (int i = 0; i < cards.size(); i++) {
-                System.out.println("[" + (i + 1) +"]   " + parser.parseCardID(cards.get(i)));
+                System.out.println("[" + (i + 1) + "]   " + parser.parseCardID(cards.get(i)));
             }
             System.out.println("===================================================================\n\n");
 
@@ -48,7 +48,8 @@ public class Player {
     }
 
     /**
-     *  iterate through cards and see if any of the player's cards are playable
+     * iterate through cards and see if any of the player's cards are playable
+     *
      * @return an array list of legal cards
      */
     public ArrayList<Integer> findLegalCard() {
@@ -60,7 +61,8 @@ public class Player {
     }
 
     /**
-     *  iterate through cards and see if any of the player's cards are playable
+     * iterate through cards and see if any of the player's cards are playable
+     *
      * @return an array list of the **indices** of legal cards from all cards
      */
     public ArrayList<Integer> findLegalCardIndex() {
@@ -81,7 +83,7 @@ public class Player {
             System.out.println("\n\n===================================================================");
             System.out.println("The following cards are playable in current turn:");
             for (int i = 0; i < legals.size(); i++) {
-                System.out.println("[" + (i + 1) +"]   " + parser.parseCardID(legals.get(i)));
+                System.out.println("[" + (i + 1) + "]   " + parser.parseCardID(legals.get(i)));
             }
             System.out.println("===================================================================\n\n");
 
@@ -93,9 +95,9 @@ public class Player {
     }
 
 
-
     /**
      * getter for cards (private attribute for tracking all cards owned by a player)
+     *
      * @return the cards of the player
      */
     public ArrayList<Integer> getCards() {
@@ -104,6 +106,7 @@ public class Player {
 
 
     /**
+     * Prepared for assignment1.1
      * Caller for player to play one round
      * skip, draw, play ... all behavior will be handled by this function
      */
@@ -116,10 +119,11 @@ public class Player {
     }
 
     /**
-     *  Playing with cmd as UI
+     * Prepared for assignment1.1
+     * Playing with cmd as UI
      */
     public void playOneRoundCmd() {
-        if (ruler.checkSkipandDraw(this)) {
+        if (ruler.checkSkipAndDraw(this)) {
             prompterCmd.printForcedSkip();
         } else {
             prompterCmd.promptTakeAction();
@@ -128,10 +132,11 @@ public class Player {
     }
 
     /**
-     *  TO BE IMPLEMENTED...
+     * Prepared for assignment1.2
+     * TO BE IMPLEMENTED...
      */
     public void playOneRoundGUI() {
-//        if (ruler.shoudPlayerBeSkipped(this)) {
+//        if (ruler.shouldPlayerBeSkipped(this)) {
 //            prompterGUI
 //        } else {}
 
@@ -144,4 +149,69 @@ public class Player {
         cards.add(cardID);
     }
 
+    /**
+     * For Assignment1.0 only
+     * Implement the logic of player playing a card.
+     *
+     * @Return whether this player successfully played the indicated card
+     */
+    public boolean optionPlayOwnedCard(int cardID) {
+        if (ruler.checkSkipAndDraw(this)) {
+            return false;
+        } else {
+
+            if (ruler.isValidPlay(this, cardID, true)) {
+                // maintain list-cards and discardPile
+                cards.remove(cards.indexOf(cardID));
+                gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
+
+                if (parser.isNonColorCard(cardID)) {
+                    // instead of choose colors
+                    // we will forcefully set it to red for assignment 0 to make testing easier
+                    ruler.setMatchableColor(parser.colorDict.get(1));
+                }
+
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * For Assignment1.0 only
+     * Implement the logic when player choose to draw a card
+     *
+     * @Return whether this player successfully played the newly drawn card
+     */
+    public boolean optionDrawCardAndPlay() {
+        if (ruler.checkSkipAndDraw(this)) {
+            return false;
+        }
+        drawCards(1);
+        int chosenCardIndex = getCards().size() - 1;
+        int newCard = cards.get(chosenCardIndex);
+
+        if(ruler.isValidPlay(this, newCard, true)) {
+            cards.remove(chosenCardIndex);
+            gameController.gameCardManager.insertOneCardToDiscardPile(newCard);
+
+            if (parser.isNonColorCard(newCard)) {
+                // instead of choose colors
+                // we will forcefully set it to red for assignment 0 to make testing easier
+                ruler.setMatchableColor(parser.colorDict.get(1));
+            }
+
+            return true;
+        }
+        return false; // played will be skipped
+    }
+
+    public boolean playerWin() {
+        return cards.isEmpty();
+    }
+
+    public void runOneRoundForTesting() {
+        cards.remove(0);
+    }
+
 }
\ No newline at end of file
diff --git a/src/UNO/RuleController.java b/src/UNO/RuleController.java
index c84d31004da333242e078a7e09b4684617de1241..7113e49ac8d0cfe977e687227772eaaa2bcc1bbd 100644
--- a/src/UNO/RuleController.java
+++ b/src/UNO/RuleController.java
@@ -39,7 +39,7 @@ public class RuleController {
      * @param player the pending player
      * @return bool
      */
-    public boolean checkSkipandDraw(Player player) {
+    public boolean checkSkipAndDraw(Player player) {
         if (nextPlayerSkipLevel == 3) {
             assert cumulativePenaltyDraw == 0;
             nextPlayerSkipLevel = 0; // the next player should no longer be skipped