Skip to content
Snippets Groups Projects
Commit 959a678e authored by FrederickPi1969's avatar FrederickPi1969
Browse files

Ready for test

parent 0db73af2
No related branches found
No related tags found
No related merge requests found
import java.lang.reflect.Array;
import java.util.*;
import java.util.Scanner;
public class Player {
private static CardParser parser = new CardParser();
private ArrayList<Integer> cards;
public int playerID;
public class CmdUI {
Player player;
CardParser parser;
public static Game gameController;
public static RuleController ruler;
public CmdUI(Player p) {
player = p;
parser = player.parser;
gameController = player.gameController;
ruler = gameController.ruler;
public Player(int ID) {
playerID = ID;
cards = new ArrayList<Integer>();
}
/**
......@@ -17,7 +19,7 @@ public class Player {
* When it's this player's turn, the player must pick one card to play
* @return the ** cardID ** of the chosen card
*/
public int playCardWithCmd(Game gameController) {
public int promptTakeAction() {
// instruct player to take a move
Scanner inputScanner = new Scanner(System.in);
boolean receivedValidInput = false;
......@@ -37,30 +39,31 @@ public class Player {
}
if (action == 1) {
return actionOneCmd(gameController);
return actionOne();
} else if (action == 2){
return actionTwoCmd(gameController);
return actionTwo();
}
return -1; // user did not play valid card
}
private int actionOneCmd(Game gameController) {
private int actionOne() {
int cardID = -1;
while (true) {
printCardsInHand();
player.printCardsInHand();
player.printLegalCards();
System.out.println("Which card would you like to play? Please input the corresponding card number...");
int chosenCardIndex = -1;
while (chosenCardIndex < 0) {
chosenCardIndex = getInputtedCardIndex();
chosenCardIndex = getInputCardIndex();
}
cardID = cards.get(chosenCardIndex);
if(gameController.ruler.isValidPlay(this, cardID, true)) {
cardID = player.getCards().get(chosenCardIndex);
if(gameController.ruler.isValidPlay(player, cardID, true)) {
// maintain list-cards and discardPile
cards.remove(chosenCardIndex);
player.getCards().remove(chosenCardIndex);
gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
break;
}
......@@ -68,21 +71,34 @@ public class Player {
if (parser.isWildCard(cardID)) {
// to implement
int colorChosen = -1;
while (colorChosen < 0) {
promptChooseColor();
colorChosen = getInputColor();
}
ruler.setAllowedColor(parser.colorDict.get(colorChosen));
}
return cardID;
}
private int actionTwoCmd (Game gameController) {
drawCards(gameController.gameCardManager, 1); // draw new card and add it to cards in hand
int chosenCardIndex = cards.size() - 1;
int cardID = cards.get(chosenCardIndex);
if(gameController.ruler.isValidPlay(this, cardID, true)) {
cards.remove(chosenCardIndex);
private int actionTwo () {
player.drawCards( 1); // draw new card and add it to cards in hand
int chosenCardIndex = player.getCards().size() - 1;
int cardID = player.getCards().get(chosenCardIndex);
if(ruler.isValidPlay(player, cardID, true)) {
player.getCards().remove(chosenCardIndex);
gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
if (parser.isWildCard(cardID)) {
// to implement
int colorChosen = -1;
while (colorChosen < 0) {
promptChooseColor();
colorChosen = getInputColor();
}
gameController.ruler.setAllowedColor(parser.colorDict.get(colorChosen));
}
return cardID;
} else {
System.out.println("Sorry, the newly drawn card is not playable :(");
......@@ -96,7 +112,7 @@ public class Player {
* parse the integer inputted by the player
* @return the ** INDEX ** of card in list cards that user chooses
*/
public int getInputtedCardIndex() {
private int getInputCardIndex() {
Scanner inputScanner = new Scanner(System.in);
String input = inputScanner.nextLine();
int decision;
......@@ -107,68 +123,63 @@ public class Player {
return -1;
}
if (decision < 0 || decision >= cards.size()) {
if (decision < 0 || decision >= player.getCards().size()) {
System.out.println("The card you chose does not exist!");
return -1;
}
return decision;
}
/**
* FOR real playing scenarios with GUI
* When it's this player's turn, the player must pick one card to play
*/
public int playCardWithGUI() {
// not implemented yet.
return 0;
}
/**
*
* @param dealer a cardManager object that is responsible to deal cards
* @param numToDraw number of cards to draw
*/
public void drawCards(CardManager dealer, int numToDraw) {
ArrayList<Integer> newCards = dealer.drawCards(numToDraw); // Initial draw
cards.addAll(newCards);
}
/**
* print all cards that this user has
* helper function for playCardWithCommandLine
* parse the integer inputted by the player
* @return the ** INDEX ** of card in list cards that user chooses
*/
public void printCardsInHand() {
if (!cards.isEmpty()) {
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("===================================================================\n\n");
} else {
System.out.println("============================================================");
System.out.println("You got not cards in hands! Congrats, you are the winner!");
private int getInputColor() {
Scanner inputScanner = new Scanner(System.in);
String input = inputScanner.nextLine();
int decision;
try {
decision = Integer.parseInt(input);
} catch (Exception e) {
System.out.println("Please input the number corresponding the card you choose!");
return -1;
}
}
/**
* getter for cards (private attribute for tracking all cards owned by a player)
* @return
*/
public ArrayList<Integer> getCards() {
return cards;
if (decision != 1 && decision != 2 && decision != 3 && decision != 4) {
System.out.println("Please choose a valid color (represented by number)!");
return -1;
}
return decision;
}
/**
* prompt player to take action current round
*/
private void promptChooseAction() {
printCardsInHand();
player.printCardsInHand();
System.out.println("The following are playable:");
player.printLegalCards();
System.out.println("Please choose you action this round:");
System.out.println("[1] Play a owned card");
System.out.println("[2] Draw a card and play it if possible");
System.out.println("Please input 1 or 2 : ");
}
private void promptChooseColor() {
player.printCardsInHand();
System.out.println("Please pick a color for the next rounds:");
System.out.println("[1] Red");
System.out.println("[2] Green");
System.out.println("[3] Blue");
System.out.println("[4] Yellow");
System.out.println("Please choose one from above: ");
}
}
\ No newline at end of file
public void printForcedSkip() {
System.out.println("Sorry, you lost this turn and was forcefully skipped.");
}
}
public class GUI {
Player player;
public GUI(Player player) {
player = player;
}
/**
* FOR real playing scenarios with GUI
* When it's this player's turn, the player must pick one card to play
*/
public int playCardWithGUI() {
// not implemented yet.
return 0;
}
}
......@@ -10,12 +10,11 @@ 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 RuleController ruler;
public CardManager gameCardManager;
public ArrayList<Player> players;
private int currentPlayerID; // playerID starts from 0 !!!!!
private boolean isClockWise = true; // if clockwise, next player will be the element in player list
/**
* Default constructor for Game object
......@@ -31,8 +30,8 @@ public class Game {
// playerID starts from 0 !!!!!
for (int i = 0; i < playerNum; i++) {
Player player = new Player(i);
player.drawCards(gameCardManager, INIT_DRAW);
Player player = new Player(i, this);
player.drawCards(INIT_DRAW);
players.add(player);
}
}
......@@ -44,19 +43,20 @@ public class Game {
*/
private void decideFirstPlayerID(int playerNum) {
Random rand = new Random();
currentPlayerID = rand.nextInt(playerNum + 1);
currentPlayerID = rand.nextInt(playerNum); // -1 to convert to index
}
/**
* decide the ID of next player
* @return ID of next player
* find the next player in the sequence, regardless whether he or not should be skipped
*/
private int decideNextPlayerID() {
if (isClockWise) {
return (currentPlayerID + 1) % players.size();
private void updateNextPlayerID() {
if (ruler.getIsClockwise()) {
currentPlayerID = (currentPlayerID + 1) % players.size();
} else {
return (currentPlayerID - 1 + players.size()) % players.size();
currentPlayerID = (currentPlayerID - 1 + players.size()) % players.size();
}
}
/**
......@@ -64,37 +64,19 @@ public class Game {
* very import function !
*/
private void runOneRound() {
System.out.println("Player " + currentPlayerID + 1 + ", It's your turn!");
System.out.println("Please choose one card to play...");
ruler.reportCurrentState(this);
System.out.println("It's now Player " + (currentPlayerID + 1) + "'s turn...");
Player currentPlayer = players.get(currentPlayerID);
int chosenCardID = currentPlayer.playCardWithCmd(this);
currentPlayerID = decideNextPlayerID(); // update the player for next round
currentPlayer.playOneRound();
}
private void changeGameState(String color, String function) {
// change color
if (color.equals("none")) {
// currentAllowedColor = "all";
}
// handle function
if (function.equals("skip")) {
currentPlayerID = decideNextPlayerID();
} else if (function.equals("draw2")) {
Player nextPlayer = players.get(decideNextPlayerID());
nextPlayer.drawCards(gameCardManager, 2);
} else if (function.equals("wildDraw4")) {
} else if (function.equals("reverse")) {
isClockWise = !isClockWise; // flip
} else if (function.equals("wild")) {
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();
updateNextPlayerID();
rounds++;
}
}
}
public class Main {
public static void main(String[] args) {
// CardParser parser = new CardParser();
// String desc = parser.parseCardID(60);
// System.out.println(parser.parseCardDescription(desc)[0]);
System.out.println("--------------------------------------------------- Game Start ---------------------------------------------------");
Game uno = new Game(6);
uno.gameStart();
}
}
\ No newline at end of file
import java.lang.reflect.Array;
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 CmdUI prompterCmd;
public GUI prompterGUI;
public Player(int ID, Game game) {
playerID = ID;
cards = new ArrayList<Integer>();
gameController = game;
ruler = game.ruler;
parser = RuleController.parser;
prompterCmd = new CmdUI(this);
prompterGUI = null;
}
/**
* @param numToDraw number of cards to draw
*/
public void drawCards(int numToDraw) {
ArrayList<Integer> newCards = gameController.gameCardManager.drawCards(numToDraw); // Initial draw
cards.addAll(newCards);
}
/**
* print all cards that this user has
*/
public void printCardsInHand() {
if (!cards.isEmpty()) {
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("===================================================================\n\n");
} else {
System.out.println("============================================================");
System.out.println("You got not cards in hands! Congrats, you are the winner!");
}
}
/**
* 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() {
ArrayList<Integer> legalCards = new ArrayList<>();
for (int cardID : cards) {
if (ruler.isValidPlay(this, cardID, false)) legalCards.add(cardID);
}
return legalCards;
}
/**
* 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() {
ArrayList<Integer> legalCardIndices = new ArrayList<>();
for (int i = 0; i < cards.size(); i++) {
if (ruler.isValidPlay(this, cards.get(i), false)) legalCardIndices.add(i);
}
return legalCardIndices;
}
/**
* print all cards that this user has
*/
public void printLegalCards() {
ArrayList<Integer> legals = findLegalCard();
if (!legals.isEmpty()) {
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("===================================================================\n\n");
} else {
System.out.println("\n\n============================================================");
System.out.println("You don't have any playable cards now.");
System.out.println("============================================================\n\n");
}
}
/**
* getter for cards (private attribute for tracking all cards owned by a player)
* @return the cards of the player
*/
public ArrayList<Integer> getCards() {
return cards;
}
/**
* Caller for player to play one round
* skip, draw, play ... all behavior will be handled by this function
*/
public void playOneRound() {
if (prompterGUI != null) {
playOneRoundGUI();
} else if (prompterCmd != null) {
playOneRoundCmd();
}
}
/**
* Playing with cmd as UI
*/
public void playOneRoundCmd() {
if (ruler.checkSkipandDraw(this)) {
prompterCmd.printForcedSkip();
} else {
prompterCmd.promptTakeAction();
}
}
/**
* TO BE IMPLEMENTED...
*/
public void playOneRoundGUI() {
// if (ruler.shoudPlayerBeSkipped(this)) {
// prompterGUI
// } else {}
}
}
\ No newline at end of file
import java.util.ArrayList;
public class RuleController {
public static CardParser parser = new CardParser();
/** IMPORTANT
* As long as one of the following three is matchable, the play will be considered as legal
*/
private String currentMatchableColor = "all";
private String currentMatchableNumber = "all";
private String currentMatchableSymbol = "all";
private int nextPlayerSkipLevel = 0;
private int cumulativePenaltyDraw = 0;
private boolean isClockWise = true; // if clockwise, next player will be the element in player list
/**
* judge whether a pending player should be skipped
* @param player the pending player
* @return bool
*/
public boolean checkSkipandDraw(Player player) {
if (nextPlayerSkipLevel == 3) {
assert cumulativePenaltyDraw == 0;
nextPlayerSkipLevel = 0; // the next player should no longer be skipped
return true;
} else if (nextPlayerSkipLevel != 0) {
// player will be skipped and forced to draw cards
// unless they have draw2 / wildDraw4 cards
assert cumulativePenaltyDraw != 0;
boolean toSkip = player.findLegalCard().isEmpty();
if (toSkip) {
nextPlayerSkipLevel = 0;
player.drawCards(cumulativePenaltyDraw);
resetPenaltyDraw();
}
return toSkip;
} else {
return false;
}
}
/**
* Given a card played by the user, judge whether this play is valid
* that is, all cards must be played following the rule
* @return whether the play is valid
*/
public boolean isValidPlay(Player player, int cardID, boolean updateIfValid) {
String cardDescription = parser.parseCardID(cardID);
String[] result = parser.parseCardDescription(cardDescription);
String color = result[0];
String type = result[1];
String content = result[2];
// pending skip
if (nextPlayerSkipLevel == 4) {
return false;
} else if (nextPlayerSkipLevel == 3) {
return content.equals("wildDraw4"); // not sure - check draw 4 legal?
} else if (nextPlayerSkipLevel == 2) {
return content.equals("wildDraw4") || content.equals("draw2");
}
boolean valid = false;
// if not skipped, first consider wild
if (content.equals("wild")) {
valid = true; // can be used unconditionally
}
// then consider wildDraw4
if (content.equals("wildDraw4")) {
valid = checkDraw4IsLegal(player);
}
// then other colored cards
if (checkAttrMatch(currentMatchableColor, color))
valid = true;
if (checkAttrMatch(currentMatchableNumber, content) || checkAttrMatch(currentMatchableSymbol, content))
valid = true;
if (valid && updateIfValid) {
updateRule(color, type, content);
}
return valid;
}
private void updateRule(String color, String type, String content) {
setAllowedColor(color); // wildcard "NA" - this will be updated later by player declaring the color
if (type.equals("sym")) {
if (content.equals("skip")) {
setNextPlayerSkiplevel(3);
// the states after the skip.. (supposed skipping is done)
currentMatchableSymbol = content; //??
currentMatchableNumber = "all"; //??
} else if (content.equals("draw2")) {
// next round match by either COL or SYM
setNextPlayerSkiplevel(1);
increasePenaltyDraw(2);
currentMatchableSymbol = content;
currentMatchableNumber = "none";
} else if (content.equals("wildDraw4")) {
// next round match only by COL
setNextPlayerSkiplevel(2);
increasePenaltyDraw(4);
currentMatchableSymbol = "none";
currentMatchableNumber = "none"; // color will be declared by player later
} else if (content.equals("reverse")) {
// next round match by either COL or SYM
changeGameOrder();
setNextPlayerSkiplevel(0);
currentMatchableSymbol = content;
currentMatchableNumber = "none";
} else if (content.equals("wild")) {
// next round can only match by COL
currentMatchableSymbol = "none";
currentMatchableNumber = "none";
}
} else if (type.equals("num")) {
// next round match by either COL or NUM
setNextPlayerSkiplevel(0);
currentMatchableNumber = content;
currentMatchableSymbol = "none";
}
}
private boolean checkAttrMatch(String legalString, String stringToCheck) {
return legalString.equals("all") || stringToCheck.equals(legalString);
}
/**
* Check whether a player have currently matchable **color** when attempting to play wild draw 4
*/
private boolean checkDraw4IsLegal(Player player) {
ArrayList<Integer> cards = player.getCards();
for (int i = 0; i < cards.size(); i++) {
int cardID = cards.get(i);
String cardDescription = parser.parseCardID(cardID);
String color = parser.parseCardDescription(cardDescription)[0]; // color of wild cards are NA
if (color.equals(currentMatchableNumber)) return false;
}
return true;
}
/**
* Getter and Setter for Allowed number
*/
public String getMatchableNumber() {
return currentMatchableNumber;
}
public void getAllowedNumber(String number) {
currentMatchableColor = number;
}
/**
* Getter and Setter for Allowed Symbol
*/
public String getCurrentMatchableSymbol() {
return currentMatchableSymbol;
}
public void setAllowedSymbol(String symbol) {
currentMatchableSymbol = symbol;
}
/**
* Getter and Setter for Allowed Color
*/
public String getMatchableColor() {
return currentMatchableColor;
}
public void setAllowedColor(String color) {
currentMatchableColor = color;
}
/**
* Getter and setter for nextPlayerIsSkipped
* level 0: next player won't be skipped
* level 1: next player can play a either a draw2 card or a wildDraw4 card to avoid being skipped
* level 2: next player can only play a wildDraw4 card of any color to avoid being skipped
* level 3: next player will be skipped anyway.
*/
public int getNextPlayerSkiplevel() { return nextPlayerSkipLevel; }
public void setNextPlayerSkiplevel(int level) { nextPlayerSkipLevel = level; }
private String descSkipLevel() {
if (nextPlayerSkipLevel == 0) {
return("level 0: player won't be skipped");
} else if (nextPlayerSkipLevel == 1) {
return("level 1: player can play a either a draw2 card or a wildDraw4 card to avoid being skipped");
} else if (nextPlayerSkipLevel == 2) {
return("level 2: next player can only play a wildDraw4 card of any color to avoid being skipped");
} else {
return("level 3: next player will be skipped anyway.");
}
}
/**
* Getter and setter for cumulativePenaltyDraw
* @return
*/
public int getPenaltyDraw() { return cumulativePenaltyDraw; }
public void resetPenaltyDraw() { cumulativePenaltyDraw = 0; }
public void increasePenaltyDraw(int num) { cumulativePenaltyDraw += num; }
/**
* Getter and setter for isClockwise
* @return
*/
public boolean getIsClockwise() { return isClockWise; }
public void changeGameOrder() { isClockWise = !isClockWise; }
public void reportCurrentState(Game gameController) {
System.out.println("============================= Game State Report ========================================");
System.out.println("Current matchable color : " + getMatchableColor());
System.out.println("Current matchable number : " + getMatchableNumber());
System.out.println("Current matchable symbol : " + getCurrentMatchableSymbol());
System.out.println("Game order : " + (getIsClockwise() ? "clockwise" : "counterclockwise"));
System.out.println("Player skip level is " + descSkipLevel());
System.out.println("Player will be forced to draw " + cumulativePenaltyDraw + " cards");
System.out.println("There are " + gameController.gameCardManager.numCardLeft() + " cards in the card pile.");
System.out.println("There are " + gameController.gameCardManager.numLeftDiscardPile() + " cards in the discard pile.");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment