Skip to content
Snippets Groups Projects
Commit 0db73af2 authored by FrederickPi1969's avatar FrederickPi1969
Browse files

todo - change game state

parent 0cf84bd1
No related branches found
No related tags found
No related merge requests found
import java.util.*;
public abstract class Card {
protected String color;
public int cardID;
}
abstract class FunctionalCard extends Card {
abstract void changeGameState();
}
class SkipCard extends FunctionalCard {
void changeGameState() {};
}
class ReverseCard extends FunctionalCard {
void changeGameState() {};
}
class WirdCard extends FunctionalCard {
void changeGameState() {};
}
class WildDrawFourCard extends FunctionalCard {
void changeGameState() {};
}
class NormalCard extends Card {
protected int number;
public NormalCard(String color, int number) {
color = color;
number = number;
}
}
\ No newline at end of file
import java.lang.reflect.Array;
import java.util.*;
public class CardManager {
private ArrayList<Integer> cardPile;
private ArrayList<Integer> discardPile;
private static CardParser parser; // only for debug purpose...
public CardManager() {
parser = new CardParser();
initializeCardPile();
printCardPile();
}
private void initializeCardPile() {
cardPile = new ArrayList<Integer>();
for (int i = 1; i <= 108; i++) {
cardPile.add(i);
}
Collections.shuffle(cardPile);
}
public void printCardPile() {
if (!cardPile.isEmpty()) {
System.out.println("\n\n===================================================================");
System.out.println("Current Card Pile has " + cardPile.size() + " card left:");
for (int i = 0; i < cardPile.size(); i++) {
System.out.println(parser.parseCardID(cardPile.get(i)));
}
System.out.println("===================================================================\n\n");
} else {
System.out.println("============================================================");
System.out.println("There are no card left in the pile!");
}
}
public int numCardLeft() {
return cardPile.size();
}
/**
* draw a certain number of cards from the card pile
* @param numToDraw total number to draw. Should be positive integer
* @return an arraylist of card drawn from the pile
*/
public ArrayList<Integer> drawCards(int numToDraw) {
if (numToDraw < 0) {
System.out.println("drawCard error: Input number must be a positive integer");
return null;
}
ArrayList<Integer> cardsDrawnFromDiscard = new ArrayList<Integer>();
if (numCardLeft() < numToDraw) {
int numToDrawFromDiscard = numToDraw - cardPile.size();
cardsDrawnFromDiscard = drawCardsfromDiscardPile(numToDrawFromDiscard);
}
ArrayList<Integer> drawnCards = new ArrayList<Integer>(cardPile.subList(0, numToDraw));
drawnCards.addAll(cardsDrawnFromDiscard);
cardPile.subList(0, numToDraw).clear(); // erase the drawn cards
return drawnCards;
}
private ArrayList<Integer> drawCardsfromDiscardPile(int numToDraw) {
ArrayList<Integer> drawnCards = new ArrayList<Integer>(discardPile.subList(0, numToDraw));
cardPile.subList(0, numToDraw).clear(); // erase the drawn cards
return drawnCards;
}
/**
* @parm ID of the card to be inserted
*/
public void insertOneCardToDiscardPile(int cardID) {
discardPile.add(0, cardID);
}
}
import java.util.*;
class CardParser {
public final int NUMBER_PER_COLOR = 25;
public final int TOTAL_COLORS = 4;
public final int COLORED_CARD_NUM = NUMBER_PER_COLOR * TOTAL_COLORS;
public HashMap<Integer, String> colorDict;
public CardParser() {
colorDict = new HashMap<Integer, String>();
colorDict.put(0, "none");
colorDict.put(1, "red");
colorDict.put(2, "green");
colorDict.put(3, "blue");
colorDict.put(4, "yellow");
}
/**
* Given ID of the card, return its content as a string as "color function" - e.g. "green 1", "none wild"
* @param cardID a integer from 1 - 108, unique id for each card
* @return
*/
public String parseCardID(int cardID) {
if (cardID < 0) {
// invald cardID
return "NA NA NA";
}
if (cardID > COLORED_CARD_NUM) {
return parseWildCard(cardID);
} else {
return parseColoredCard(cardID);
}
}
/**
* helper function for parse for cards without colors
*/
private String parseWildCard(int cardID) {
if (cardID > COLORED_CARD_NUM && cardID <= COLORED_CARD_NUM + 4) {
return "NA sym wild";
} else if (cardID > COLORED_CARD_NUM + 4 && cardID <= COLORED_CARD_NUM + 8) {
return "NA sym wildDraw4";
}
return "NA NA NA";
}
/**
* helper function for parse for cards with colors
*/
private String parseColoredCard(int cardID) {
int colorID = (cardID - 1) / NUMBER_PER_COLOR + 1;
String color = colorDict.get(colorID);
Integer cardTypeID = cardID % NUMBER_PER_COLOR;
String type;
String content = "";
if (cardTypeID <= 18) {
// case 1 - 9
type = "num";
cardTypeID = cardTypeID <= 9 ? cardTypeID : (cardTypeID - 9);
content = cardTypeID.toString();
} else if (cardTypeID > 18 && cardTypeID <= 20) {
// case skip card
type = "sym";
content = "skip";
} else if (cardTypeID > 20 && cardTypeID <= 22) {
// case reverse card
type = "sym";
content = "reverse";
} else if (cardTypeID > 22 && cardTypeID <= 24 ) {
// case draw 2
type = "sym";
content = "draw2";
} else {
// case 0
type = "num";
content = "0";
}
return constructCardDescription(color, type, content);
}
private String constructCardDescription(String color, String type, String value) {
return color + " " + type + " " + value;
}
/**
* Given the description of one card, parse its color type and content
* @return a string array (String[]) : {color, type, content}
*/
public String[] parseCardDescription(String description) {
String[] results = description.split(" ", 3);
String color = results[0];
String type = results[1];
String content = results[2];
String[] output = {color, type, content};
return output;
}
/**
* 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) {
return cardID > COLORED_CARD_NUM;
}
}
\ No newline at end of file
import java.util.*;
/**
* The class for recording Game state
* Organize the interactions among all other classes
*/
public class Game {
private static CardParser parser = new CardParser();
private static final int INIT_DRAW = 7; // every player get 7 cards at beginning
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
* @param playerNum
*/
public Game(int playerNum) {
gameCardManager = new CardManager();
ruler = new RuleController();
decideFirstPlayerID(playerNum);
System.out.println("Loading player information...");
players = new ArrayList<Player>();
// playerID starts from 0 !!!!!
for (int i = 0; i < playerNum; i++) {
Player player = new Player(i);
player.drawCards(gameCardManager, INIT_DRAW);
players.add(player);
}
}
/**
* Randomly decide the start position of this game
* @param playerNum total number of players
*/
private void decideFirstPlayerID(int playerNum) {
Random rand = new Random();
currentPlayerID = rand.nextInt(playerNum + 1);
}
/**
* decide the ID of next player
* @return ID of next player
*/
private int decideNextPlayerID() {
if (isClockWise) {
return (currentPlayerID + 1) % players.size();
} else {
return (currentPlayerID - 1 + players.size()) % players.size();
}
}
/**
* Run one round of UNO
* 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...");
Player currentPlayer = players.get(currentPlayerID);
int chosenCardID = currentPlayer.playCardWithCmd(this);
currentPlayerID = decideNextPlayerID(); // update the player for next round
}
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 class Main {
public static void main(String[] args) {
}
}
\ No newline at end of file
import java.lang.reflect.Array;
import java.util.*;
public class Player {
private static CardParser parser = new CardParser();
private ArrayList<Integer> cards;
public int playerID;
public Player(int ID) {
playerID = ID;
cards = new ArrayList<Integer>();
}
/**
* FOR CMD LINE DEBUGGING
* 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) {
// instruct player to take a move
Scanner inputScanner = new Scanner(System.in);
boolean receivedValidInput = false;
int action = -1;
while (!receivedValidInput) {
promptChooseAction();
String input = inputScanner.nextLine();
try {
action = Integer.parseInt(input);
if (action == 1 || action == 2) {
receivedValidInput = true;
}
} catch (Exception e) {
System.out.println("Please choose action from 1 or 2");
}
}
if (action == 1) {
return actionOneCmd(gameController);
} else if (action == 2){
return actionTwoCmd(gameController);
}
return -1; // user did not play valid card
}
private int actionOneCmd(Game gameController) {
int cardID = -1;
while (true) {
printCardsInHand();
System.out.println("Which card would you like to play? Please input the corresponding card number...");
int chosenCardIndex = -1;
while (chosenCardIndex < 0) {
chosenCardIndex = getInputtedCardIndex();
}
cardID = cards.get(chosenCardIndex);
if(gameController.ruler.isValidPlay(this, cardID, true)) {
// maintain list-cards and discardPile
cards.remove(chosenCardIndex);
gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
break;
}
}
if (parser.isWildCard(cardID)) {
// to implement
}
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);
gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
if (parser.isWildCard(cardID)) {
// to implement
}
return cardID;
} else {
System.out.println("Sorry, the newly drawn card is not playable :(");
return -1;
}
}
/**
* helper function for playCardWithCommandLine
* parse the integer inputted by the player
* @return the ** INDEX ** of card in list cards that user chooses
*/
public int getInputtedCardIndex() {
Scanner inputScanner = new Scanner(System.in);
String input = inputScanner.nextLine();
int decision;
try {
decision = Integer.parseInt(input) - 1; // -1 because we want the index in cards list
} catch (Exception e) {
System.out.println("Please input the number corresponding the card you choose!");
return -1;
}
if (decision < 0 || decision >= cards.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
*/
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!");
}
}
/**
* getter for cards (private attribute for tracking all cards owned by a player)
* @return
*/
public ArrayList<Integer> getCards() {
return cards;
}
/**
* prompt player to take action current round
*/
private void promptChooseAction() {
printCardsInHand();
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");
}
}
\ No newline at end of file
import java.util.ArrayList;
public class RuleController {
private static CardParser parser = new CardParser();
private String currentAllowedColor = "all";
private String currentAllowedNumber = "all";
private String currentAllowedSymbol = "all";
/**
* 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];
boolean valid = false;
if (checkAttrMatch(currentAllowedColor, color))
valid = true;
if (checkAttrMatch(currentAllowedNumber, content) || checkAttrMatch(currentAllowedSymbol, content))
valid = true;
if (content.equals("wildDraw4")) {
valid = checkDraw4IsLegal(player);
}
if (valid && updateIfValid) {
currentAllowedColor = color.equals("NA") ? "none" : color; // wildcard played
if (type.equals("sym")) {
currentAllowedSymbol = content;
currentAllowedNumber = "none";
} else if (type.equals("num")) {
currentAllowedNumber = content;
currentAllowedSymbol = "none";
}
}
return false;
}
private boolean checkAttrMatch(String legalString, String stringToCheck) {
return legalString.equals("all") || stringToCheck.equals(legalString);
}
/**
* Check whether a player have currently allowed 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];
if (color.equals(currentAllowedNumber)) return false;
}
return true;
}
/**
* Getter and Setter for Allowed number
*/
public String getAllowedNumber() {
return currentAllowedNumber;
}
public void getAllowedNumber(String number) {
currentAllowedColor = number;
}
/**
* Getter and Setter for Allowed Symbol
*/
public String getCurrentAllowedSymbol() {
return currentAllowedSymbol;
}
public void setAllowedSymbol(String symbol) {
currentAllowedSymbol = symbol;
}
/**
* Getter and Setter for Allowed Color
*/
public String getAllowedColor() {
return currentAllowedColor;
}
public void setAllowedColor(String color) {
currentAllowedColor = color;
}
}
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