8
\$\begingroup\$

I'm working on a card game in Java that simulates the drinking game Kings Cup for a school project. I'm having trouble putting the pieces together, and was wondering if someone could tell me what I could do to improve my code.

 @author              :Kimberly
 IDE                  :NETBEANS

public class Card extends Deck {

        enum Rank {
        ACE   ("Ace"),
        TWO   ("2"),
        THREE ("3"),
        FOUR  ("4"),
        FIVE  ("5"),
        SIX   ("6"),
        SEVEN ("7"),
        EIGHT ("8"),
        NINE  ("9"),
        TEN   ("10"),
        JACK  ("Jack"),
        QUEEN ("Queen"),
        KING  ("King");
        String rank;
        Rank(String rank) {
            this.rank = rank;
         }
        }
        enum Suit {
        HEARTS      ("Hearts"),
        DIAMONDS    ("Diamonds"),
        SPADES      ("Spades"),
        CLUBS       ("Clubs");
        String name;
        Suit(String name) {
            this.name = name;
        }
    } 
    public Rank rank;
    public Suit suit;

    Card(Suit suit, Rank rank){
            this.rank=rank;
            this.suit=suit;
    }

    public @Override String toString(){
              return rank.rank + " of " + suit.name;
    }
}

public class Deck {

    private int dealt;

    /**
     * Shuffles the deck of cards.
     */
    public static ArrayList<Card> cards;
     Deck() {
         cards = new ArrayList<Card>();
            for (Card.Suit suit : Card.Suit.values()){
                    for (Card.Rank rank : Card.Rank.values()){
                       cards.add( new Card(suit,rank));
                     }
            }
            Collections.shuffle(cards, new Random());
            Collections.shuffle(cards, new Random(System.nanoTime()));
     }

     public Card getCard(){
         return cards.get(0);
     }

     public void removeFromDeck(){     
         cards.remove(0);
     }
}

public class Human extends Player{
    Scanner in;

    public Human(boolean turn) {
        super("HUMAN", turn);
        in = new Scanner(System.in);
    }
}

public class Computer extends Player{

    Random random;
    double cWeight;
    String cGender = "";

       public Computer(boolean turn){
           //super("COMPUTER", turn);
          turn = true;
          random = new Random();
       }

       public double weight() {
           ArrayList<Integer> compWeight = new ArrayList<>();
           compWeight.add(110);
           compWeight.add(170);
           compWeight.add(250);
           Collections.shuffle(compWeight, new Random());
           for(int i = 0; i < 3; i++)
           {
               cWeight =  compWeight.get(i);
           }

            return cWeight;
       }

       public String gender() {
           ArrayList<String>compGender = new ArrayList<>();
           compGender.add("male");
           compGender.add("female");
           Collections.shuffle(compGender, new Random());
           for(int i = 0; i < 2; i++)
           {
               cGender =  compGender.get(i);
           }
           return cGender;
       }
}

public class Player {

    public static final double MAX_BAC = 0.5;
    public static int cardImplement = 0;
    public static double SD = 0.0; //amount of drinks
    public static double BW = 0.0; //body water constant
    public static final double MaleBW = 0.58;
    public static final double FemaleBW = 0.49;
    public static final double MR = 0.017; //metabolism constant
    public static final double DP = 2.0; //drinking period (2 hours)
    public static double BAC = 0.0;

    public boolean turn;

    public Player(double BAC, boolean turn) {
        this.BAC = BAC;
        this.turn = turn;
    }

    public double BAC() {
        if(gender.equals("male"))
            BW = MaleBW;
        else 
            BW = FemaleBW;
        BAC = ((.806 * SD * 1.2) / (BW * weight)) - (MR * DP);
        return BAC;
    }

    public static void draw() {
        System.out.println(cards.get(cardImplement));
        cardImplement++;
    }


    public static void sip() {
        if (BAC < MAX_BAC) {
        SD += 0.2;
        }
    }

    public boolean switchTurn() {
        turn = !turn;
        return turn;
    }
}

public class Rules extends KingsCupGame{

    private static int kings = 0;

    public static void setRules() {

        final String[] CATEGORY_WORDS = {"apple, apricot, banana, bilberry,"
            + "blackberry, blackcurrant, blueberry, coconut, currant, cherry,"
            + " cherimoya, clementine, date, damson, durian, elderberry, fig,"
            + " feijoa, gooseberry, grape, grapefruit, huckleberry, jackfruit,"
            + " jambul, jujube, kiwi, kumquat, lemon, lime, loquat, lychee,"
            + " mango, mangostine, melon, cantaloupe, honeydew, watermelon,"
            + " rock melon, nectarine, orange, passionfruit, peach, pear, plum,"
            + " prune, pineapple, pomegranate, pomelo, raisin, raspberry,"
            + " rambutan, redcurrant, satsuma, strawberry, tangerine, ugli,"
            + "archery, badminton, basketball, volleyball, boxing, cycling, "
            + "diving, equestian, handball"};

        final String[] RHYME_WORDS = {"bink, blink, brink, chink, cinq,"
            + " cinque, clink, dink, finck, fincke, fink, finke, flink, frink,"
            + " hinck, hink, inc, inc., ink, klinck, klink, klinke, krinke,"
            + " linc, linck, link, linke, lynk, minc, mink, minke, pink,"
            + " plink, prink, rinck, rink, rinke, schinke, schlink, shrink,"
            + " sink, skink, slink, smink, spink, stink, swink, sync, think,"
            + " vink, wink, zinc, zinck, zink, zinke, at, bat, batt, batte, bhatt,"
            + " blatt,brat, bratt, catt, chat, dat, fat, flat, flatt, gat,"
            + " gatt,glatt, gnat, hat, hatt, hnat, jagt, kat, katt, klatt,"
            + " krat, kratt, latke, mat, matt, matte, nat, pat, patt, platt,"
            + " platte,  pratt, pratte, rat, ratte, sat, scat, schadt, shatt," 
            + " slaght, slat, spat, splat, sprat, spratt, stat, tat, that,"
            + " vat"};

        Scanner in = new Scanner(System.in);

        for(Card.Rank c : Card.Rank.values()) {  

            //Waterfalls
            if(c.equals("Ace")) {
                System.out.println("Player drew an Ace.");
                System.out.println("Player must drink a whole drink (5 sips)!");
                Player.sip();
                Player.sip();
                Player.sip();
                Player.sip();
                Player.sip();
            }

            //You
            if(c.equals("Two")) {
                System.out.println("Player drew a Two.");
                System.out.println("The other player must take a sip.");
                Player.sip();
            }

            //Me
            if(c.equals("Three")) {
                System.out.println("Player drew a Three.");
                System.out.println("Player must take a sip.");
                Player.sip();
            }

            //Women
            if(c.equals("Four")) {
                System.out.println("Player drew a Four.");
                System.out.println("Female players must take a sip.");
                if(BW == FemaleBW) {
                    Player.sip();
                }
            }

            //Rhymes
            if(c.equals("Five")) {
                System.out.println("Player drew a Five.");


                ArrayList <String> rhymeWord = new ArrayList <>();
                rhymeWord.add("cat");
                rhymeWord.add("drink");
                Collections.shuffle(rhymeWord, new Random());
                int count = 0;
                System.out.println("You have 30 seconds to type 5 words"
                        + " that rhyme with " + rhymeWord);
                //JOptionPane.showMessageDialog(null, "You have 30 seconds to type 5 words"
                //        + " that rhyme with " + rhymeWord);
                if (in.hasNext()) {
                    String rhymeAnswer = in.next();
                    if(RHYME_WORDS[0].contains(rhymeAnswer)) {
                        count++;
                        if(count >= 5) {
                            System.out.println("Good Job! Computer drinks!");
                            //JOptionPane.showMessageDialog(null, "Good Job! Computer drinks.");
                            Player.sip();
                        } 
                    }
                    else 
                    {
                       System.out.println("Sorry. You have to take a sip!");
                       //JOptionPane.showMessageDialog(null, "Sorry. You drink!");
                       Player.sip();
                    }        
                }
            }

            //Guys
            if(c.equals("Six")) {
                System.out.println("Player drew a Six.");
                System.out.println("Male players must take a sip.");
                if(BW == FemaleBW) {
                    Player.sip();
                }
            }

            //Extra sip
            if(c.equals("Seven")) {
                System.out.println("Player drew a Seven.");
                System.out.println("Player must take an extra sip.");
                Player.sip();
                Player.sip();
            }

            //Mate
            if(c.equals("Eight")) {
                System.out.println("Player drew an Eight.");
                System.out.println("Both players must take a sip.");
                Player.sip();
            }

            //Categories
            if(c.equals("Nine")) {
                System.out.println("Player drew a Nine.");

                ArrayList <String> categoryWord = new ArrayList <>();
                categoryWord.add("Sports");
                categoryWord.add("Fruits");
                Collections.shuffle(categoryWord, new Random());
                int count = 0;
                //JOptionPane.showMessageDialog(null, "You have 30 seconds to type 5 categories of"
                         //+ categoryWord);
                System.out.println("You have 30 seconds to type 5 categories of " + categoryWord);
                if (in.hasNext()) {
                    String categoryAnswer = in.next();
                    if(CATEGORY_WORDS[0].contains(categoryAnswer)) {
                        count++;
                        if(count >= 5) {
                            System.out.println("Good Job! Computer must take a sip.");
                            //JOptionPane.showMessageDialog(null, "Good Job! Computer drinks.");
                            Player.sip();
                        } 
                    }
                    else 
                    {
                        System.out.println("Sorry! You must take a sip!");
                       //JOptionPane.showMessageDialog(null, "Sorry. You drink!");
                       Player.sip();
                    }        
                }
            }

            //Draw Again
            if(c.equals("Ten")) {
                System.out.println("Player drew a Ten.");
                        System.out.println("Player must draw another card.");
                Player.draw();
            }

            //Least Drunk
            if(c.equals("Jack")) {
                System.out.println("Player drew a Jack.");
                System.out.println("The Player with the lowest BAC must take a sip.");
                if(Human.BAC < Computer.BAC) {
                    Player.sip();
                }
                else if(Computer.BAC < Human.BAC) {
                    Player.sip();
                }
                else {
                    System.out.println("");

                }
            }

            //Questions
            if(c.equals("Queen")) {
                System.out.println("Player drew a Queen.");
                System.out.println("You must answer this question: ");
                String answer = "";
                ArrayList<String> questions = new ArrayList<> ();
                questions.add("If you have a big one of these, odds are"
                        + " you are highly educated.");
                questions.add("Experts say a man tends to be happier and more"
                        + " secure if he has one of these.");
                questions.add("Guys think it's cool, but 60% of women think"
                        + " it's a major turn off when a guy does this.");
                questions.add("What's Dr. Brown's middle name?");
                questions.add("");

                String answers = ("signature, sister, sisters, wink, roy");
                Collections.shuffle(questions, new Random());
                for(String question: questions) {
                            JOptionPane.showMessageDialog(null, 
                                    "Answer this question." + question);
                        }
                if(in.hasNext())
                {
                    answer = in.next();
                }
                if(answers.contains(answer)) {
                    JOptionPane.showMessageDialog(null, "Correct! Computer drinks.");
                    Player.sip();
                }
                else {
                    JOptionPane.showMessageDialog(null, "Wrong! Player drinks.");
                    Player.sip();
                }
            }

            //Mug
            int mug = 0;
            if(c.equals("King")) {
                System.out.println("Player drew a King.");
                if(kings == 3) {
                   System.out.println("It's the final King! Player must drink a whole drink (5 sips)!");
                   Player.sip();
                   Player.sip();
                   Player.sip();
                   Player.sip();
                   Player.sip();
                }
                else {
                    kings++;
                    mug++;
                    System.out.println("Player pours some of their drink into the mug.");
                    System.out.println(4 - kings + " out of 4 Kings remaining.");
                }
            }
        }
}
}

import java.util.Scanner;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class KingsCupGame {

    private final Human human;
    private final Computer computer;
    public static double weight = 0.0;
    public static String gender = "";
    private static String name = "";
    private static String confirm = "";

    public static int playerTurn=1;

    static Deck deck = new Deck();

    public KingsCupGame() {
        human = new Human(true);
        computer = new Computer(false);
    }

    public static void main(String[] args) throws IOException {  
        KingsCupGame frame = new KingsCupGame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 700);
        frame.setVisible(true);

    }   
        public static void inputs() {
            Scanner in = new Scanner(System.in);

            System.out.print("What's your first name: ");
            if(in.hasNext()) 
                name = in.next();

            System.out.println("Are you male or female? (Enter male or female)");
                if(in.hasNext()) 
                    gender = in.next();

            System.out.println("Enter your weight (don't lie): ");
                if(in.hasNextDouble()) 
                    weight = in.nextDouble();

            System.out.println("Hello " + name + "! You are a " + gender + 
                " who weighs " + weight + ".");

            System.out.println("Is this correct? (Enter yes or no)");
                if(in.hasNext()) 
                    confirm = in.next();
                if(confirm.equals("yes")) {

                }
        }

    private static int getNum(String prompt,String title) {
        return Integer.parseInt
            (JOptionPane.showInputDialog(null,prompt,title,3));
    }  

    public static String getGender() {
        return gender;
    }

    private static String getRule(){
        return Rules.get(deck.getCard().rank.ordinal());
    }

    private static void finalMessage() {
        JOptionPane.showMessageDialog(null,"Player "+playerTurn+" has died of alcohol poisoning.\n\n"+
                    getRule()+"\n\n", "Restart the Program to Play again",1);
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ well when I get some more time I will give a much more thorough review of the code but I find a few things wrong with your inheritance rules. A super class of Player being implemented by Computer and Human is a good thing. However Player not being abstract is a good way for a mistake. A deck extending a card, or vise versa does not make sense. a deck is a collection of cards, but does not extend it. Work on those for now \$\endgroup\$ – Robert Snyder Apr 16 '14 at 3:33
10
\$\begingroup\$

I'm probably missing a fair bit, but these are the things I picked up on:


Why does Card extend Deck? They are both objects in their own right and don't require inheritance.

If Player is intended to be an object it shouldn't have any static variables or methods. You might also want to consider making it an abstract class as you don't want to be able to make a new Player, you only want to be able to make a new instance of Player such as a Human or a Computer

You seem to be calling Player.sip() five times in a row manually. To make things easier, I would create another sip() method which takes an int parameter of how many times you want to do it, i.e:

public void sip(int times) {
    for (int i = 0; i < times; i++) {
        sip();
    }
}

Your rhyme words algorithm is entirely wrong. Firstly, you are only checking if the first element in the array of words contains the answer (which it won't, unless they type the same String five times)

if(RHYME_WORDS[0].contains(rhymeAnswer)) {

I would change RHYME_WORDS to be a HashSet which actually has a contains method which will do what you are trying to achieve.

Consider extracting each of the different card types to its own private method, so you don't just have one massive block of code, and it will make testing each one easier.

I'm not entirely convinced your program works how you want it to at the moment. You should usually make sure you get everything working how it should be before you consider submitting it for code review, as we're not here to test it for you we are here to offer advice on improvement.

Hopefully the points I've raised will give you some direction towards improvement, and then you can keep working on it and report back if you need more help.

\$\endgroup\$
7
\$\begingroup\$
  • ArrayList<String>compGender = new ArrayList<>(); should be declared (on the left side) as a List<String> (keep the higher abstraction where possible). Also be careful with spacing; it does compile correctly here, but it could lead to serious problem elsewhere.

  • In Deck, public static ArrayList<Card> cards should not be static. And the constructor should be public.

  • Collections.shuffle(cards, new Random()); Collections.shuffle(cards, new Random(System.nanoTime())); should be replaced by just one Collections.shuffle(cards, random) where random is a static Random member of Deck.

  • In Deck, you should just have one method that both gets and removes the card in one atomic operation. You can get in some weird states otherwise.

  • Player.draw should not be static.

  • In Rules, CATEGORY_WORDS and RHYMES words should just be static final member variables.

  • In Rules, the long series of if's should be one switch statement. Also, you iterate over all cards, but I assume you really want to process the player input.

  • Rules should not extend KingsCupGame. Likely it should be a member (composition) within KingsCupGame.

I did not go over everything. You should read more material about both inheritance and static because you seem to use those two concepts randomly.

\$\endgroup\$
  • \$\begingroup\$ After seeing @Jamal's answer, I noticed that there were a bunch of things to say about this code. Thanks for saying them! \$\endgroup\$ – Simon Forsberg Sep 22 '14 at 18:25
6
\$\begingroup\$
  • The indentation within Card is a little weird, but especially inconsistent with everything else in the other classes. If you follow the Java style guide closely, such things shouldn't stand out so easily.

  • rank and suit should be private as they shouldn't be exposed to the public interface like that. They should also be final so that they cannot be modified after initialization (it doesn't make sense to change a card's value later on, and it could make the code error-prone).

  • You already shuffle the deck upon initialization, but shouldn't the user also be able to shuffle the deck without recreating it? In some games, I believe, the deck can be shuffled with the existing cards, up to a certain point. Having a separate method for this will help make the class more usable.

    public void shuffle() {
        Collections.shuffle(cards, new Random());
        Collections.shuffle(cards, new Random(System.nanoTime()));
    }
    

    Also, in order to avoid duplicating code, have the constructor call this instead.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.