I am using the class card example from java website to try to build a game.
http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
I am taking in the number of hands and the number of cards per hands as arguments
like: java -jar a02.jar 4 3
I have added values to the ranks and suits. I am printing the DECK then the HAND...
What i am trying to do is print the deck first
with their values times together.
for example: Ten of Hearts
Ten = 10
Hearts = 4
So, i print out Ten of Hearts(40)
When i print the deck, I am having a problem getting them to print on one line by the number of cards per hand. like:
eight of spades(8), ten of hearts(40), deuce of hearts(8)
What can i do to fix this?
My other issue is that is there a better way of retrieving the values of the cards than what i am doing? could i use some type of compare?
because when i print out the hand after the deck i am having a hard time getting the values and the hand right ( so i commented out the code )
I also commented the part of code in main() where i am retrieving the values.
how could i do this differently?
Keep in mind i want the values printed also with the Hand like i am doing with deck
I will shorted the output..
here is the output:
C:\Java\a02>java -jar a1.jar 3 4
THREE of SPADES(3), // i would like this to print out like hand does below
FIVE of HEARTS(20),
DEUCE of DIAMONDS(6),
KING of CLUBS(20),
DEUCE of HEARTS(8),
TEN of HEARTS(40),
JACK of HEARTS(40),
ACE of HEARTS(44),
NINE of CLUBS(18),
EIGHT of SPADES(8),
QUEEN of SPADES(10),
KING of HEARTS(40),
NINE of SPADES(9),
SEVEN of SPADES(7),
SEVEN of HEARTS(28),
EIGHT of HEARTS(32),
TEN of SPADES(10),
DEUCE of CLUBS(4),
EIGHT of DIAMONDS(24),
// here is the hand - which i also want the values
[SIX of CLUBS, SEVEN of DIAMONDS, TEN of DIAMONDS, TEN of CLUBS]
[SIX of HEARTS, THREE of HEARTS, SIX of SPADES, DEUCE of SPADES]
[JACK of SPADES, NINE of DIAMONDS, SEVEN of CLUBS, THREE of DIAMONDS]
C:\Java\a02>
here is the code:
import java.util.*;
public class Cards{
public enum Rank { DEUCE(2), THREE(3), FOUR(4), FIVE(5), SIX(6),
SEVEN(7), EIGHT(8), NINE(9), TEN(10), JACK(10), QUEEN(10), KING(10), ACE(11);
private int Rankpoints;
private Rank(int points)
{
this.Rankpoints = points;
}
public int getRankpoints()
{
return Rankpoints;
}
}
public enum Suit { CLUBS(2), DIAMONDS(3), HEARTS(4), SPADES(1);
private int Suitpoints;
Suit(int points)
{
Suitpoints = points;
}
public int getSuitpoints()
{
return Suitpoints;
}
}
private final Rank rank;
private final Suit suit;
private Cards(Rank rank, Suit suit)
{
this.rank = rank;
this.suit = suit;
}
public Rank rank()
{
return this.rank;
}
public Suit suit()
{
return this.suit;
}
public String toString()
{
return rank + " of " + suit;
}
private static final List<Cards> protoDeck = new ArrayList<Cards>();
// Initialize prototype deck
static {
for (Suit suit : Suit.values())
for (Rank rank : Rank.values())
protoDeck.add(new Cards(rank, suit));
}
public static ArrayList<Cards> newDeck()
{
return new ArrayList<Cards>(protoDeck); // Return copy of prototype deck
}
}
and here is main()
import java.util.*;
public class Deal {
public static void main(String args[])
{
int numHands = Integer.parseInt(args[0]);
int cardsPerHand = Integer.parseInt(args[1]);
List<Cards> deck = Cards.newDeck();
Collections.shuffle(deck);
int total = 0;
// ArrayList<Cards> hand = new ArrayList<Cards>();
// this is how i am handling the values.. which is not good.
for (Cards card : deck)
{
for(Cards.Suit a : Cards.Suit.values())
{
for(Cards.Rank b : Cards.Rank.values())
{
if(card.rank() == b)
{
if(card.suit() == a) // as you can see this works. theres got to be a better way??
{
total = b.getRankpoints();
// hand.add(card);
System.out.println(card.rank() + " of " + card.suit() + "(" + a.getSuitpoints() * total + ")" + ",");
}
}
}
}
}
for (int i=0; i < numHands; i++)
System.out.println(deal(deck, cardsPerHand)); // prints the hand
//deal(deck,cardsPerHand,numHands);
}
// hand
public static ArrayList<Cards> deal(List<Cards> deck, int n) {
int deckSize = deck.size();
List<Cards> handView = deck.subList(deckSize-n, deckSize);
ArrayList<Cards> hand = new ArrayList<Cards>(handView);
handView.clear();
// Map<String, Map<String, Integer>> inputWords = new HashMap<String, Map<String, Integer>>();
int total = 0;
return hand;
}
}
//for (Cards card : hand)
//{
// for(Cards.Suit a : Cards.Suit.values())
// {
//for(Cards.Rank b : Cards.Rank.values())
// {
// if(card.rank() == b)
// {
// if(card.suit() == a)
//{
// total = b.getRankpoints();
// System.out.println("card.rank() + " of " + card.suit() + "(" + a.getSuitpoints() * total + ")" + ",");
// return hand;
//}
//}
//}
//}
//}
//return hand;
//}
//}
Any help is much appreciated. code snippets or hints are very welcome =)
Keep in mind i am pretty new to Java..
Thank you
Try changing your Card classes toString() method to something like this:
public String toString()
{
return rank + " of " + suit+ "(" + suit.getSuitpoints() * rank.getRankpoints() + ")" + ",");
}
Then this:
System.out.println(card.rank() + " of " + card.suit() + "(" + a.getSuitpoints() * total + ")" + ",");
Can become:
System.out.println(card);
In regard to getting it all to print on one line you're looking for System.out.print() rather than System.out.println().
Related
I am trying to create a Blackjack game. The game itself is pretty easy (at least my version). A player draws a card from a shuffled deck and calculates the sum of the cards which has been drawn. I have a decklist of cards with the type String and that is now a big problem for me. I have no clue how I can calculate the sum since they are of the type String. Do you have any guidelines on what I can do? The only solution I've figured out is really bad and is to compare the card with a String and give it a value. For example, drawnCard.equals("Four of hearts") = "4";
public class Player {
private String nickName;
private int playerNumOfCards;
ArrayList<Card> playerHand = new ArrayList<>();
public Player (String name){
this.nickName = name;
}
public String getNickName() {
return nickName;
}
public void addCard(Card aCard){
playerHand.add(aCard);
this.playerNumOfCards++;
}
public void getHandSum(){
}
public void getPlayerHand(){
for(Card cards: playerHand){
System.out.println(cards.toString());
}
}
}
public class DeckOfCards {
private Card[] deck;
private static final Random random = new Random();
private int currentCard; //index of next Card to be deal (0-51)
private static int NUMBER_OF_CARDS = 52; //Constant number of cards
public DeckOfCards(){
String [] faces = {"Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack","Queen", "King"};
String [] suits = {"Hearts", "Diamonds", "Clubs", "Spades"};
deck = new Card [NUMBER_OF_CARDS]; // create array with Cards (52)
currentCard = 0;
//Populate deck with Cards
for(int count = 0; count < deck.length; count++)
deck [count] = new Card(faces [count % 13], suits [count / 13]);
}
public void shuffleDeck(){
currentCard = 0;
for (int first = 0; first < deck.length; first++){
int second = random.nextInt(NUMBER_OF_CARDS); //Select a random card from number 0-51 (Number_of_cards)
//Loops through all the cards and swaps it with the "Second" card which is randomly chosen card from hte same list.
Card temp = deck[first];
deck [first] = deck [second];
deck [second] = temp;
}
}
public void getCardDeck(){
int start = 1;
for(Card k : deck) {
System.out.println("" + start + "/52 " + k);
start++;
}
}
public Card dealNextCard(){
//Get the top card
Card topCard = this.deck[0];
//shift all the subsequent cards to the left by one index
for(int currentCard = 1; currentCard < NUMBER_OF_CARDS; currentCard ++){
this.deck[currentCard-1] = this.deck[currentCard];
}
this.deck[NUMBER_OF_CARDS-1] = null;
//decrement the number of cards in our deck
this.NUMBER_OF_CARDS--;
return topCard;
}
}
public class Card {
private String face; //Face of card, i.e "King" & "Queen"
private String suit; //Suit of card, i.e "Hearts" & "diamonds"
public Card (String cardFace, String cardSuit){ //Constructor which initializes card's face and suit
this.face = cardFace;
this.suit = cardSuit;
}
public String toString(){ //return String representation of Card
return face + " of " + suit;
}
}
public class BlackJackGame {
public static void main(String[] args) {
DeckOfCards deck1 = new DeckOfCards();
Player player1 = new Player("mille");
deck1.shuffleDeck();
}
}
Create an enum to represent Face
enum Face {
Ace(number), //I don't know what number is for Ace and others.
Deuce(number),
Three(3),
Four(4),
Five(5),
Six(6),
Seven(7),
Eight(8),
Nine(9),
Ten(10),
Jack(number),
Queen(number),
King(number);
private final int number;
Faces(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
Change type of face from String to Face.
class Card {
private Face face;
private String suit;
public Card (Face cardFace, String cardSuit){card's face and suit
this.face = cardFace;
this.suit = cardSuit;
}
public String toString(){
return face + " of " + suit;
}
public int getNumber() {
return face.getNumber();
}
}
Add a method to get the face number from card class and then use it accordingly. You will need to change other parts or your project as well but I will leave that for you to do.
Also suggest using enum for Suit.
I couldn't see the deck list there, but if your card Strings always follow the same naming convention (i.e. "four of hearts") you could make your job a little easier by splitting each string by the " " space fields and then comparing the first word in the string to get the number (or corresponding 10 for king/queen etc..)
String cardName = "four of hearts" (or whatever the variable name is);
String[] parts = string.split(" ");
String number = parts[0];
thus number would equal "four" only instead of having to compare "four of hearts" to return the number 4.
Hope that helps
Instead of translating I've added comment in the code. But its mainly strings that are in Swedish.
I have trouble adding a feature where the game asks the user the amount of decks (each deck containing the standard 52 cards.)
Just like how the game ask if the deck should be shuffled or not the user should be asked how many decks the game should contain, the rest can be as it is for now.
I've tried (but ofc it didnt work):
int n = //amount of decks
int[] deck = new int[52*n];
Here is the program:
import java.util.Scanner;
public class KortSpel {
public static void main(String[] args) {
Boolean fortsatt = true;
while(fortsatt){
Scanner scan = new Scanner(System.in);
int[] deck = new int[52];
String[] suits = {"Hjärter", "Spader", "Ruter", "Klöver"}; //the suits
String[] ranks = {"Ess", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Knäckt", "Drottning", "Kung"}; //the rank of the cards
for( int i = 0; i < deck.length; i++) deck[i] = i;
System.out.print("Skriv dra för att dra korten annars avsluta."); //ask the user if he want to keep playing or not
String svar2 = scan.nextLine();
if (svar2.equalsIgnoreCase("Avsluta")){
fortsatt = false;
System.out.println("Du har nu avslutat."); //tells the user he has exit
}
else {
System.out.print("Vill du bland korten? (ja/nej) "); //ask the user if he want to shuffle the cards Y/N
String svar = scan.nextLine();
if (svar.equalsIgnoreCase("ja")) { // if shuffled
for( int i = 0; i < deck.length; i++) {
int index = (int)(Math.random() * deck.length);
int temp = deck[i];
deck[i] = deck[index];
deck[index] = temp;
}
for( int i = 0; i < 52; i++) {
String suit = suits[deck[i] / 13];
String rank = ranks[deck[i] % 13];
System.out.println("Kort nummer " + deck[i] + ": " + suit + " " + rank);
}
}
else { //if not suffled
for( int i = 0; i < deck.length; i++) deck[i] = i;
for( int i = 0; i < 52; i++) {
String suit = suits[deck[i] / 13];
String rank = ranks[deck[i] % 13];
System.out.println("Kort nummer " + deck[i] + ": " + suit + " " + rank);
}
}
}
}
}
}
All help is appreciated and since Im not very good with java, simplicity is preferred.
Thanks in advance!
All this gets a lot easier if you take up a formal Object Oriented model instead of informally defining a card.
What is a card? In this context, that's rather simple; it's a pair of values, one of which is a suit, and the other is a rank. So long as the suit and rank are both valid, both are cards. This gives us the following class:
public class Card{
public final String suit;
public final String rank;
public Card(String s, String r){
suit = s;
rank = r;
}
}
Before we go further, I would like to note here that using the type String for suit and rank is not a great idea; both have a finite set of potential values and as such can be better represented as an enumerated type (or Enum). We can define the Enums like this (though obviously you could change the words to be swedish):
public enum Suit{
HEARTS,
SPADES,
CLUBS,
DIAMONDS
}
public enum Rank{
ACE,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING
}
Which changes our Card class to look like this:
public class Card{
public final Suit suit;
public final Rank rank;
public Card(Suit s, Rank r){
suit = s;
rank = r;
}
}
From here, creating a deck class is easy:
public class Deck{
private ArrayList<Card> deck; //An array of cards that represents this deck.
public Deck(){
deck = new ArrayList<Card>();
//For every combination of suit and rank, create and add a card to this deck
for(Suit s : Suit.values()){
for(Rank r : Rank.values()){
deck.add(new Card(s, r));
}
}
}
}
From here you can add functionality to the deck class for shuffling, drawing cards, etc.
For your original question, creating multiple decks is just a question of creating many single decks and adding all of their contents together. We can create a constructor that does that, and add that to our deck class:
public class Deck{
private ArrayList<Card> deck; //An array of cards that represents this deck.
public Deck(){
deck = new ArrayList<Card>();
//For every combination of suit and rank, create and add a card to this deck
for(Suit s : Suit.values()){
for(Rank r : Rank.values()){
deck.add(new Card(s, r));
}
}
}
/** Creates a deck that is the sum of all the cards in the input deck(s) */
public Deck(Deck... decks){
deck = new ArrayList<Card>();
for(Deck d : decks){
deck.addAll(d.deck);
}
}
}
I am creating a deck of poker cards (52 cards). I want to be able to print it out for example:
2 of Club, 3 of Club......
2 of Diamond, 3 of Diamond....
Queen of Diamond, King of Diamond
and so on for the 52 cards.
I am able to do this now but having problem when it comes to the face cards which are the Jack, Queen, King and Ace. Currently I am using numbers to represent them. so instead of printing Jack of Clubs, it shows as 11 of Clubs which is wrong. I tried to store the face cards in an enum and tried to loop them but can't really get around to do it.
Can I get some advice on how I could get my face cards in instead of representing them as numbers. I have attached my main method and the class below. Thanks for help.
//Card Class
import java.util.Objects;
public class Card {
public enum Suits{
CLUBS, DIAMONDS, HEARTS, SPADES;
}
public enum Faces{
JACK, QUEEN, KING, ACE;
}
private int rank;
private String suit;
public Card(int rank, String suit){
this.rank = rank;
this.suit = suit;
}
public int getRank(){
return rank;
}
public String getSuit(){
return suit;
}
public String format(){
return String.format("%d of %s, ", getRank(), getSuit());
}
}
//Main method
public class CardTester {
public static void main(String[] args) {
Card[] cards = new Card[52];
int i = 0;
for (Card.Suits suit : Card.Suits.values()) {
for (int y = 2; y < 15; y++) {
cards[i] = new Card(y, suit.name());
i++;
}
}
for(Card p : cards){
System.out.print(p.format() + " ");
}
}
}
Change your format() method to:
public String format(){
if (getRank() < 11) {
return String.format("%d of %s, ", getRank(), getSuit());
}
else {
Faces face = Faces.values()[getRank() - 11];
return String.format("%s of %s, ", face, getSuit());
}
}
Alternatively, here's a better implementation for Card:
import java.util.Objects;
public class Card {
public enum Suit {
CLUBS, DIAMONDS, HEARTS, SPADES;
}
public enum Rank {
TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN,
JACK, QUEEN, KING, ACE;
}
private final Suit suit;
private final Rank rank;
public Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
public Suit getSuit(){
return suit;
}
public Rank getRank(){
return rank;
}
#Override
public String toString() {
return rank + " of " + suit;
}
#Override
public int hashCode() {
int hash = 5;
hash = 97 * hash + Objects.hashCode(this.suit);
hash = 97 * hash + Objects.hashCode(this.rank);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Card other = (Card) obj;
if (this.suit != other.suit) {
return false;
}
if (this.rank != other.rank) {
return false;
}
return true;
}
}
You can use it like this:
import java.util.ArrayList;
import java.util.List;
public class CardTester {
public static void main(String[] args) {
List<Card> cardList = new ArrayList<>();
Card lastCard = new Card(Card.Suit.SPADES, Card.Rank.ACE);
for (Card.Suit suit : Card.Suit.values()) {
for (Card.Rank rank : Card.Rank.values()) {
Card card = new Card(suit, rank);
cardList.add(card);
if (!card.equals(lastCard)) {
System.out.print(card + ", ");
}
else {
System.out.print(card);
}
}
}
// use cardList
}
}
Your modelling of cards is flawed, and your problem highlights this. Rank is not numeric and should not be an 'int'. You might want to use an enum for the rank.
You might be tempted to give your rank an integer value, but this is probably not a good idea. The value is generally defined by the game you are playing, and not by the deck of cards. For example in poker a king is ranked higher than a jack, but in blackjack they are ranked the same.
May be source code shown below will help you:
public enum Faces
{
JACK( 1, "Jack" ), QUEEN( 2, "Queen" ), KING( 3, "King" ), ACE( 4, "Ace" );
public int GetNumber()
{
return m_number;
}
public String GetName()
{
return m_name;
}
private Faces( int number_, String name_ )
{
m_number = number_;
m_name = name_;
}
private int m_number;
private String m_name;
}
you may delete the enum Faces you already have and add the following method to class Card:
public String getFace(int rank){
String result = "";
switch (rank){
case 11: result = "Jack"; break;
case 12: result = "QUEEN"; break;
case 13: result = "KING"; break;
case 14: result = "ACE"; break;
default:{
result = Integer.toString(rank);
break;
}
}
return result;
}
and modify your format() method to look like this:
public String format(){
return String.format("%s of %s, ", getFace(getRank()), getSuit());
}
This will do the job ;-)
A card consists of RANK and SUIT. Common poker software convention is to represent cards as SUIT+RANK Strings, as in 3c for 3 of clubs and Kd for king of diamonds. (see pokerstove or most hand history producers and consumers)
You need to expand the concept of RANK beyond faces. I've been using the Steve Brecher poker eval library, and his RANK class looks like this:
A simple lookup of the string "23456789TJQKA" converts between the enum and the RANK. There is a similar SUIT enum and a pretty reasonable Comparable class that combines the two.
public static enum Rank {
TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE;
/**
* #return the character in {#link #RANK_CHARS} denoting this rank.
*/
public char toChar() {
return RANK_CHARS.charAt(this.ordinal());
}
/**
* #param c
* a character present in {#link #RANK_CHARS} (case
* insensitive)
* #return the Rank denoted by character.
* #throws IllegalArgumentException
* if c not in {#link #RANK_CHARS}
*/
public static Rank fromChar(char c) {
int i = RANK_CHARS.indexOf(Character.toUpperCase(c));
if (i >= 0)
return Rank.values()[i];
throw new IllegalArgumentException("'" + c + "'");
}
/**
* #return the pip value of this Rank, ranging from 2 for a
* <code>TWO</code> (deuce) to 14 for an <code>ACE</code>.
*/
public int pipValue() {
return this.ordinal() + 2;
}
public static final String RANK_CHARS = "23456789TJQKA";
}
You can find his old but still perfectly serviceable libraries here: http://www.brecware.com/Software/software.html or http://pokersource.sourceforge.net/
U can try this solution which uses enum. First of all you need to create two enums. One for suits and the other for cards.
The enum for suits is:
public enum suits
{
club, diamond,heart,spades
}
The enum for cards is:
public enum cards
{
two(2), three(3), four(4), five(5), six(6), seven(7), eight(8),nine(9),
ten(10), jack(11), queen(12), king(13),ace(14);
int number;
private cards(int number)
{
this.number=number;
}
public int getNumber()
{
return this.number;
}
}
THen in your main class you can loop through both the enums to get your result as follows:
public class Javaclass
{
public static void main(String[] args)
{
int count=2;
for(suits suit:suits.values())
{
for(cards card: cards.values())
{
if(count<=10)
System.out.println(card.getNumber()+" of "+suit);
else
System.out.println(card+" of "+suit);
count++;
}
count=2;
System.out.println("");
}
}
}
Hope this helps.
I have created my deck of cards that deals every card and a suit until there is no card remaining. For my project, I need to split it up into 3 classes which includes a driver class. I first created one class with everything so I knew how to make it all work.
public class DeckOfCards2 {
public static void main(String[] args) {
int[] deck = new int[52];
String[] suits = {"Spades", "Hearts", "Diamonds", "Clubs"};
String[] ranks = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
// Initialize cards
for (int i = 0; i < deck.length; i++) {
deck[i] = i;
}
// Shuffle the cards
for (int i = 0; i < deck.length; i++) {
int index = (int)(Math.random() * deck.length);
int temp = deck[i];
deck[i] = deck[index];
deck[index] = temp;
}
// Display the all the cards
for (int i = 0; i < 52; i++) {
String suit = suits[deck[i] / 13];
String rank = ranks[deck[i] % 13];
System.out.println( rank + " of " + suit);
}
}
}
Now trying to split it up into 3 classes. I am getting red sqiggle lines on ALL my deck/suit variables on my DeckOfCards class. I dont know how to fix it.
public class DeckOfCards {
private Card theCard;
private int remainingCards = 52;
DeckOfCards() {
theCard = new Card();
}
public void shuffle(){
for (int i = 0; i < deck.length; i++) {
int index = (int)(Math.random() deck.length);
int temp = deck[i];
deck[i] = deck[index];
deck[index] = temp;
remainingCards--;
}
}
public void deal(){
for (int i = 0; i < 52; i++) {
String suit = suits[deck[i] / 13];
String rank = ranks[deck[i] % 13];
System.out.println( rank + " of " + suit);
System.out.println("Remaining cards: " + remainingCards);
}
}
}
Card class:
public class Card {
int[] deck = new int[52];
String[] suits = {"Spades", "Hearts", "Diamonds", "Clubs"};
String[] ranks = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
Card() {
for (int i = 0; i < deck.length; i++) {
deck[i] = i;
}
}
}
Dealer class
public class Dealer {
public static void main(String[]args){
System.out.println("The deck will randomly print out a card from a full deck each time");
DeckOfCards player = new DeckOfCards();
player.deal();
}
}
As somebody else already said, your design is not very clear and Object Oriented.
The most obvious error is that in your design a Card knows about a Deck of Cards. The Deck should know about cards and instantiate objects in its constructor. For Example:
public class DeckOfCards {
private Card cards[];
public DeckOfCards() {
this.cards = new Card[52];
for (int i = 0; i < ; i++) {
Card card = new Card(...); //Instantiate a Card
this.cards[i] = card; //Adding card to the Deck
}
}
Afterwards, if you want you can also extend Deck in order to build different Deck of Cards (for example with more than 52 cards, Jolly etc.). For Example:
public class SpecialDeck extends DeckOfCards {
....
Another thing that I'd change is the use of String arrays to represent suits and ranks. Since Java 1.5, the language supports Enumeration, which are perfect for this kind of problems. For Example:
public enum Suits {
SPADES,
HEARTS,
DIAMONDS,
CLUBS;
}
With Enum you get some benefits, for example:
1) Enum is type-safe you can not assign anything else other than predefined Enum constants to an Enum variable. For Example, you could write your Card's constructor as following:
public class Card {
private Suits suit;
private Ranks rank;
public Card(Suits suit, Ranks rank) {
this.suit = suit;
this.rank = rank;
}
This way you are sure to build consistent cards that accept only values of your enumeration.
2) You can use Enum in Java inside Switch statement like int or char primitive data type (here we have to say that since Java 1.7 switch statement is allowed also on String)
3) Adding new constants on Enum in Java is easy and you can add new constants without breaking existing code.
4) You can iterate through Enum, this can be very helpful when instantiating Cards. For Example:
/* Creating all possible cards... */
for (Suits s : Suits.values()) {
for (Ranks r : Ranks.values()) {
Card c = new Card(s,r);
}
}
In order to not invent again the wheel, I'd also change the way you keep Cards from array to a Java Collection, this way you get a lot of powerful methods to work on your deck, but most important you can use the Java Collection's shuffle function to shuffle your Deck. For example:
private List<Card> cards = new ArrayList<Card>();
//Building the Deck...
//...
public void shuffle() {
Collections.shuffle(this.cards);
}
This is my implementation:
public class CardsDeck {
private ArrayList<Card> mCards;
private ArrayList<Card> mPulledCards;
private Random mRandom;
public enum Suit {
SPADES,
HEARTS,
DIAMONDS,
CLUBS;
}
public enum Rank {
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING,
ACE;
}
public CardsDeck() {
mRandom = new Random();
mPulledCards = new ArrayList<Card>();
mCards = new ArrayList<Card>(Suit.values().length * Rank.values().length);
reset();
}
public void reset() {
mPulledCards.clear();
mCards.clear();
/* Creating all possible cards... */
for (Suit s : Suit.values()) {
for (Rank r : Rank.values()) {
Card c = new Card(s, r);
mCards.add(c);
}
}
}
public static class Card {
private Suit mSuit;
private Rank mRank;
public Card(Suit suit, Rank rank) {
this.mSuit = suit;
this.mRank = rank;
}
public Suit getSuit() {
return mSuit;
}
public Rank getRank() {
return mRank;
}
public int getValue() {
return mRank.ordinal() + 2;
}
#Override
public boolean equals(Object o) {
return (o != null && o instanceof Card && ((Card) o).mRank == mRank && ((Card) o).mSuit == mSuit);
}
}
/**
* get a random card, removing it from the pack
* #return
*/
public Card pullRandom() {
if (mCards.isEmpty())
return null;
Card res = mCards.remove(randInt(0, mCards.size() - 1));
if (res != null)
mPulledCards.add(res);
return res;
}
/**
* Get a random cards, leaves it inside the pack
* #return
*/
public Card getRandom() {
if (mCards.isEmpty())
return null;
Card res = mCards.get(randInt(0, mCards.size() - 1));
return res;
}
/**
* Returns a pseudo-random number between min and max, inclusive.
* The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*
* #param min Minimum value
* #param max Maximum value. Must be greater than min.
* #return Integer between min and max, inclusive.
* #see java.util.Random#nextInt(int)
*/
public int randInt(int min, int max) {
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = mRandom.nextInt((max - min) + 1) + min;
return randomNum;
}
public boolean isEmpty(){
return mCards.isEmpty();
}
}
Here is some code. It uses 2 classes (Card.java and Deck.java) to accomplish this issue, and to top it off it auto sorts it for you when you create the deck object. :)
import java.util.*;
public class deck2 {
ArrayList<Card> cards = new ArrayList<Card>();
String[] values = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] suit = {"Club", "Spade", "Diamond", "Heart"};
static boolean firstThread = true;
public deck2(){
for (int i = 0; i<suit.length; i++) {
for(int j=0; j<values.length; j++){
this.cards.add(new Card(suit[i],values[j]));
}
}
//shuffle the deck when its created
Collections.shuffle(this.cards);
}
public ArrayList<Card> getDeck(){
return cards;
}
public static void main(String[] args){
deck2 deck = new deck2();
//print out the deck.
System.out.println(deck.getDeck());
}
}
//separate class
public class Card {
private String suit;
private String value;
public Card(String suit, String value){
this.suit = suit;
this.value = value;
}
public Card(){}
public String getSuit(){
return suit;
}
public void setSuit(String suit){
this.suit = suit;
}
public String getValue(){
return value;
}
public void setValue(String value){
this.value = value;
}
public String toString(){
return "\n"+value + " of "+ suit;
}
}
Very Simple code to generate deck off Card:
class Card{
private final String suit;
private final String rank;
public Card(String suit, String rank){
this.suit = suit;
this.rank = rank;
}
#Override
public String toString() {
return "Card [suit=" + suit + ", rank=" + rank + "]";
}
}
class DeckOfCard{
private static final String suits[] = {"club", "diamond", "heart", "spade"};
private static final String ranks[] = {null,"ace", "deuce", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "jack", "queen", "king"};
private final ArrayList<Card> cards;
public DeckOfCard(){
cards = new ArrayList<Card>();
for (int i = 0; i<suits.length; i++) {
for(int j=0; j<ranks.length; j++){
this.cards.add(new Card(suits[i],ranks[j]));
}
}
//Shuffle after the creation
Collections.shuffle(this.cards);
}
public ArrayList<Card> getCards() {
return cards;
}
}
public class CardPuzzle {
public static void main(String[] args) {
DeckOfCard deck = new DeckOfCard();
ArrayList<Card> cards = deck.getCards();
for(Card card:cards){
System.out.println(card);
}
}
}
There is something wrong with your design. Try to make your classes represent real world things. For example:
The class Card should represent one card, that is the nature of a "Card". The Card class does not need to know about Decks.
The Deck class should contain 52 Card objects (plus jokers?).
First you have an architectural issue with your classes. You moved the property deck inside your class Card. But of couse it is a property of the card deck and thus has to be inside class DeckOfCards. The initialization loop should then not be in the constructor of Card but of your deck class. Moreover, the deck is an array of int at the moment but should be an array of Cards.
Second, inside method Deal you should refer to suits as Card.suits and make this member static final. Same for ranks.
And last, please stick to naming conventions. Method names are always starting with a lower case letter, i.e. shuffle instead of Shuffle.
There are many errors in your code, for example you are not really calling your deck by just typing deck in your Shuffle method. You can only call it by typing theCard.deck
I have changed your shuffle method:
public void Shuffle(){
for (int i = 0; i < theCard.deck.length; i++) {
int index = (int)(Math.random()*theCard.deck.length );
int temp = theCard.deck[i];
theCard.deck[i] = theCard.deck[index];
theCard.deck[index] = temp;
remainingCards--;
}
}
Also, as it is said you have structural problem. You should name classes as you understand in real life, for example, when you say card, it is only one card, when you say deck it is supposed to be 52+2 cards. In this way your code would be more understandable.
There is a lot of error in your program.
Calculation of index. I think it should be Math.random()%deck.length
In the display of card. According to me, you should make a class of card which has rank suit and make the array of that class type
If you want I can give you the Complete structure of that but it is better if u make it by yourself
I think the solution is just as simple as this:
Card temp = deck[cardAindex];
deck[cardAIndex]=deck[cardBIndex];
deck[cardBIndex]=temp;
public class shuffleCards{
public static void main(String[] args) {
String[] cardsType ={"club","spade","heart","diamond"};
String [] cardValue = {"Ace","2","3","4","5","6","7","8","9","10","King", "Queen", "Jack" };
List<String> cards = new ArrayList<String>();
for(int i=0;i<=(cardsType.length)-1;i++){
for(int j=0;j<=(cardValue.length)-1;j++){
cards.add(cardsType[i] + " " + "of" + " " + cardValue[j]) ;
}
}
Collections.shuffle(cards);
System.out.print("Enter the number of cards within:" + cards.size() + " = ");
Scanner data = new Scanner(System.in);
Integer inputString = data.nextInt();
for(int l=0;l<= inputString -1;l++){
System.out.print( cards.get(l)) ;
}
}
}
import java.util.List;
import java.util.ArrayList;
import static java.lang.System.out;
import lombok.Setter;
import lombok.Getter;
import java.awt.Color;
public class Deck {
private static #Getter List<Card> deck = null;
final int SUIT_COUNT = 4;
final int VALUE_COUNT = 13;
public Deck() {
deck = new ArrayList<>();
Card card = null;
int suitIndex = 0, valueIndex = 0;
while (suitIndex < SUIT_COUNT) {
while (valueIndex < VALUE_COUNT) {
card = new Card(Suit.values()[suitIndex], FaceValue.values()[valueIndex]);
valueIndex++;
deck.add(card);
}
valueIndex = 0;
suitIndex++;
}
}
private enum Suit{CLUBS("Clubs", Color.BLACK), DIAMONDS("Diamonds", Color.RED),HEARTS("Hearts", Color.RED), SPADES("Spades", Color.BLACK);
private #Getter String name = null;
private #Getter Color color = null;
Suit(String name) {
this.name = name;
}
Suit(String name, Color color) {
this.name = name;
this.color = color;
}
}
private enum FaceValue{ACE(1), TWO(2), THREE(3),
FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT (8), NINE(9), TEN(10),
JACK(11), QUEEN(12), KING(13);
private #Getter int cardValue = 0;
FaceValue(int value) {
this.cardValue = value;
}
}
private class Card {
private #Getter #Setter Suit suit = null;
private #Getter #Setter FaceValue faceValue = null;
Card(Suit suit, FaceValue value) {
this.suit = suit;
this.faceValue = value;
}
public String toString() {
return getSuit() + " " + getFaceValue();
}
public String properties() {
return getSuit().getName() + " " + getFaceValue().getCardValue();
}
}
public static void main(String...inputs) {
Deck deck = new Deck();
List<Card> cards = deck.getDeck();
cards.stream().filter(card -> card.getSuit().getColor() != Color.RED && card.getFaceValue().getCardValue() > 4).map(card -> card.toString() + " " + card.properties()).forEach(out::println);
}
}
My card class where the method is defined.
package blackjackgamemodel;
public class Card {
protected Rank rank;
protected Suit suit;
public Card(Card.Rank rank, Card.Suit suit) {
this.rank = rank;
this.suit = suit;
}
public String toString() {
return "" + rank + " of " + suit;
}
public Card.Rank rank() {
return rank;
}
public Card.Suit suit() {
return suit;
}
public enum Rank {
ACE (1), TWO (2), THREE (3), FOUR (4), FIVE (5), SIX (6), SEVEN (7),
EIGHT (8), NINE (9), TEN (10), JACK (11), QUEEN (12), KING (13);
private int value;
Rank(int value) {
this.value = value;
}
public int value() {
return value;
}
}
public enum Suit {
SPADES, HEARTS, CLUBS, DIAMONDS
}
}
The game class where the error is
package blackjackgamemodel;
import blackjackgamemodel.Card;
import blackjackgamemodel.Deck;
public class Game {
protected Deck deck;
protected int sum;
protected int aces;
public Game() {
// Initialize deck, sum and aces.
deck = new Deck();
sum = 0;
aces = 0;
}
public Card draw() {
// Draw a card from the deck
Card drawn_card = deck.draw();
// Calculate the value to add to sum
int v = drawn_card.value();
if (v == 1) {
v = 11;
// If the card is an ace, increase the count of aces.
aces++;
}
else if (v > 10) {
v = 10;
}
// Now v is the Blackjack value of the card.
// If the sum is greater than 21 and there are aces,
// Then decrease the sum by 10 and the aces by 1.
if (aces > 0 && sum > 21) {
sum = sum - 10;
aces = aces - 1;
}
// Return the card that was drawn.
return drawn_card;
}
public int sum() {
// Getter for sum.
return sum;
}
}
ERROR
Description Resource Path Location Type
The method value() is undefined for the type Card Game.java /BlackJack/src/blackjackgamemodel line 25 Java Problem
It's the Card.Rank enum that has the value() method, not the Card class.
Try:
int v = drawn_card.rank().value()
Indeed Card has no value method: It has a rank method and Card.Rank has a value method.
value() isn't a method on Card it is on Card.Rank in your included code.
The message is correct, Card does not have a value() method. Did you mean to get the card's rank and then get that value? That's looks like the intent.
Does your Card have a value method? It looks like Card's rank has a value method.
Try:
int v = drawn_card.rank().value();