Nested for loops and object array - java

My other question got flagged duplicate couse I didn't explain well enough so i try again only a lot better.
So I'm making this java Black Jack console game and have stumbled to a small wall here. I've made a class called Card which is ready. Now i'm stumbeling a bit in creating all 52 cards in to an array of cards. Well i made code that works but it seems ugly to me having three nested for loops. Is there a "real way" of doing what I did here.
So here would be part of the class Card
int value;
String suit;
String name;
public void Card(int value, int suitNumber)
this.value=value;
switch(suitNumber){
case 1 : this.suit = "Heart";
break;
.......
}
switch(value){
case 1 : this.name="Ace";
......
}
Part of Pack class have a nested for loop like this:
Card[] packOfCards = new Card[51];
for(int k=0; k<52; ){
for(int i=1; i<5; i++){
for(int j=1; j<14; j++){
packOfCards[k] = Card(j, i);
k++;
// it seems stupid for me to have 3 nested
//loops like that
}
}
}

You can get same result using one for loop by saving more time complexity instead of three for loop and repeatation. Try,
for (int k = 1; k <= 52; k++) {
int i = k % 5;
int j = k % 14;
packOfCards[k-1] = new Card(j, i);
}

You either need to loop over:
Every slot in your deck
Every possible card value (Which probably requires a nested loop; get each value for each suit, or vice-versa)
At present you seem to be looping over both.
The following code uses the first approach:
for(int i = 0; i < 52; i++) {
int suit = (i % 13) + 1;
int value = (i / 13) + 1;
packOfCards[i] = new Card(value, suit);
}
And this code uses the second (two-loop) approach:
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 13; j++) {
int cardIndex = (13 * (i-1)) + j;
packOfCards[cardIndex] = new Card(j, i);
}
}
Also note that your Card class looks wrong. You've declared a void method when I think you wanted a constructor, and then you missed the new keyword when creating the new card (hint: the compiler will alert you to a lot of these mistakes).
As others have suggested, it would probably make more sense to use enums too as the type for your card value and suit, rather than juggling between int and String.
import java.util.ArrayList;
import java.util.List;
public class Card {
private final CardValue value;
private final Suit suit;
public Card(CardValue value, Suit suit) {
this.value = value;
this.suit = suit;
}
#Override
public String toString() {
return value + " of " + suit;
}
public static void main(String[] args) {
List<Card> deck = new ArrayList<Card>();
for (Suit s : Suit.values()) {
for (CardValue v : CardValue.values()) {
deck.add(new Card(v, s));
}
}
for (Card c : deck) {
System.out.println(c);
}
Card aceOfSpades = new Card(CardValue.withValue(1), Suit.SPADES);
System.out.println(aceOfSpades);
}
public enum Suit {
HEARTS ("Hearts"),
CLUBS ("Clubs"),
DIAMONDS ("Diamonds"),
SPADES ("Spades");
private final String name;
Suit(String name) {
this.name = name;
}
#Override
public String toString() {
return this.name;
}
}
public enum CardValue {
TWO(2, "Two"),
THREE(3, "Three"),
FOUR(4, "Four"),
FIVE(5, "Five"),
SIX(6, "Six"),
SEVEN(7, "Seven"),
EIGHT(8, "Eight"),
NINE(9, "Nine"),
TEN(10, "Ten"),
JACK(11, "Jack"),
QUEEN(12, "Queen"),
KING(13, "King"),
ACE(1, "Ace");
private final int value;
private final String name;
CardValue(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public static CardValue withValue(int value) {
for (CardValue v : CardValue.values()) {
if (value == v.value) {
return v;
}
}
return null;
}
#Override
public String toString() {
return this.name;
}
}
}
You'll probably want to pull the enums out into seperate files, but for the sake of producing a relatively concisely working example I put them within the main class.

Related

ArrayIndexOutOfBoundsException When Creating Deck of Cards in Java

I am hoping to get some help even though I know this is probably a very simple bug that I cannot seem to find an answer to.
What I am trying to accomplish is to create a deck of cards, and I keep running into an out of bounds error.
Here is my code:
Card Class:
public class Card {
private String suit;
private int face;
public Card(int face, String suit){
face = this.face;
suit = this.suit;
}
public int getFace(){
return face;
}
public String getFaceAsString(int face){
int faceName = face;
String faceString = "";
if(faceName == 11){
faceString = "J";
} else if(faceName == 12){
faceString = "Q";
} else if(faceName == 13){
faceString = "K";
} else if(faceName == 14){
faceString = "A";
} else {
faceString = Integer.toString(faceName);
}
return faceString;
}
public String getSuit(){
return suit;
}
public void setSuit(String suit){
this.suit = suit;
}
}
This is my main class:
import java.util.Random;
import java.util.Scanner;
public class Hero_Game {
public static void main(String[] args) {
String[] suits = {"Spades","Clubs","Hearts","Diamonds"};
int[] faces = {2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int index = 0;
Card[] deck = new Card[52];
for(int i = 0; i<suits.length;i++){
for(int j = 0; j<faces.length;j++){
deck[index] = new Card(faces[i],suits[j]);
index++;
}
}
You switched the indexes for the faces and suits arrays in your for loops. It should be:
for(int i = 0; i<suits.length;i++){
for(int j = 0; j<faces.length;j++){
deck[index] = new Card(faces[j],suits[i]);
index++;
}
}
You also have an extra number in your "faces" array - you're trying to create 14 * 4 = 56 cards instead of 13 * 4 = 52.
Why do you have 14 faces instead of 13?
In any case, to more safely allocate the correct number of items in your deck array, use int numCardsInDeck = suits.length * faces.length; to calculate the total items in the deck.
Try this instead:
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Game {
public static class Card {
final int face;
final String suit;
public Card(int face, String suit) {
this.face = face;
this.suit = suit;
}
#Override
public String toString() {
return face + " of " + suit;
}
}
public static void main(String[] args) {
String[] suits = {"Spades","Clubs","Hearts","Diamonds"};
int[] faces = {2,3,4,5,6,7,8,9,10,11,12,13,14};
int index = 0;
int numCardsInDeck = suits.length * faces.length;
Card[] deck = new Card[numCardsInDeck];
for(int i = 0; i < suits.length; i++) {
for(int j = 0; j < faces.length; j++) {
deck[index] = new Card(faces[j],suits[i]);
index++;
}
}
System.out.println(Arrays.toString(deck));
}
}
int[] faces = {2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Get rid of 15 and do the loop as suggested by #Geshode

Creating a deck of cards and shuffling them

I have been stuck on this for sometime now, the objective is to create an array to hold the cards in, once I do create the array print them out the only card that is printing is king of hearts. Why is it not iterating?
public class Card
{
// Card suits (provided for your convenience - use is optional)
public static final int SPADES = 0;
public static final int HEARTS = 1;
public static final int CLUBS = 2;
public static final int DIAMONDS = 3;
// Card faces (provided for your convenience - use is optional)
public static final int ACE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
public static final int FOUR = 4;
public static final int FIVE = 5;
public static final int SIX = 6;
public static final int SEVEN = 7;
public static final int EIGHT = 8;
public static final int NINE = 9;
public static final int TEN = 10;
public static final int JACK = 11;
public static final int QUEEN = 12;
public static final int KING = 13;
// define fields here
private static int suit;
private static int val;
private String[] suits = {"Clubs", "Spades", "Diamonds", "Hearts"};
private String[] vals = {"Ace","2", "3", "4", "5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King" };
// This constructor builds a card with the given suit and face, turned face down.
public Card(int suit, int val)
{
this.val = val;
this.suit = suit;
}
public #Override String toString()
{
return vals[val] + " Of " + suits[suit];
}
// This method retrieves the suit (spades, hearts, etc.) of this card.
public int getSuit()
{
return this.suit;
}
// This method retrieves the face (ace through king) of this card.
public int getFace()
{
// return this.val;
switch(val)
{
case 0 : return 1;
case 1 : return 2;
case 2 : return 3;
case 3 : return 4;
case 5 : return 6;
case 6 : return 7;
case 7 : return 8;
case 8 : return 9;
case 9 : return 10;
case 10 : return 10;
case 12 : return 10;
default : return 0;
}
}
}`
import java.util.ArrayList;
import java.util.Random;
// This class represents the deck of cards from which cards are dealt to players.
public class Deck
{
//array
public static Card[] cards;
// private static ArrayList<Card> cards;
int i;
int counter;
// This constructor builds a deck of 52 cards.
Deck()
{
i = 51;
//array implementation
cards = new Card[52];
int x = 0;
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 13;j++)
{
//Array implementation
cards[x] = new Card(i,j);
x++;
}
}
}
// This method takes the top card off the deck and returns it.
public Card deal()
{
//Array implementation
int index = 0;
Card temp = cards[index];
return temp;
}
// this method returns true if there are no more cards to deal, false otherwise
public boolean isEmpty()
{
if(cards.length == 0)
{
return true;
}
return false;
}
//this method puts the deck int some random order
// public void shuffle()
// {
// for(int i = 51; i > 0; i--)
// {
// int rand = (int) (Math.random() * (i+1));
// Card temp = this.cards[i];
// this.cards[i] = cards[rand];
// cards[rand] = temp;
// }
//
// }
}
public class BlackJack extends Deck
{
public static void main(String []args)
{
System.out.println("Ready to play a game of BlackJack?");
Deck deck = new Deck();
for(int i = 0; i < cards.length;i++)
{
System.out.println(cards[i]);
}
Problem is caused by the following:
// define fields here
private static int suit;
private static int val;
because they are static, all Card instances share these, so they will all have the last value they were set to. Remove the static.
To give you a little hint how you might make the code even easier to read/maintain:
use enums instead of constants. You can give them constructors/member variables just like classes
use for-each-loops, it's way easier to read and prevents the usual off-by-1 problems
type 'static' BEFORE all other modifiers and keep all static variables and members separate from any non-static content. this way you can never mix them up by accident
Bad / unusual sides of this code are:
I use static nested enums and classes. Usually each of those should go into its own file and be non-static
I like to prefix my variables according to their scope so I cannot mess em up: pXxx for Parameter, sXxx for static variables, mXxxx for members, no prefix for method variables
public class CardGame {
static public enum SuitType {
SPADES, HEARTS, CLUBS, DIAMONDS
}
static public enum FaceType {
ACE("Ace", 1), //
TWO("2", 2), //
THREE("3", 3), //
FOUR("4", 4), //
FIVE("5", 5), //
SIX("6", 6), //
SEVEN("7", 7), //
EIGHT("8", 8), //
NINE("9", 9), //
TEN("10", 10), //
JACK("Jack", 11), //
QUEEN("Queen", 12), //
KING("King", 13), //
;
private final String mName;
private final int mValue;
private FaceType(final String pName, final int pValue) {
mName = pName;
mValue = pValue;
}
public String getName() {
return mName;
}
public int getValue() {
return mValue;
}
public int getValue_alternative() {
return ordinal() + 1; // ordinal is the index of the enum, starting at ace=0 ... king=12
// sorting and comparing of suits could also be done by .ordinal() if need be
}
}
static public class Card {
private final SuitType mSuit;
private final FaceType mFace;
public Card(final SuitType pSuit, final FaceType pFace) {
mSuit = pSuit;
mFace = pFace;
}
public SuitType getSuit() {
return mSuit;
}
public FaceType getFace() {
return mFace;
}
#Override public String toString() {
return mFace.getName() + " of " + mSuit + " - " + mFace.getValue() + (mFace.getValue() > 1 ? " points" : " point");
}
}
static public class Deck {
private final ArrayList<Card> mCards;
public Deck() {
mCards = createFullDeck();
}
private ArrayList<Card> createFullDeck() { // can also be static as it dowes not use member cariables => potential factory method
final ArrayList<Card> ret = new ArrayList<>();
for (final SuitType suit : SuitType.values()) {
for (final FaceType face : FaceType.values()) {
final Card c = new Card(suit, face);
ret.add(c);
}
}
return ret;
}
public void shuffleRandomly() {
final ArrayList<Card> tempList = new ArrayList<>();
tempList.addAll(mCards);
mCards.clear();
while (tempList.size() > 0) {
final int index = (int) (Math.random() * tempList.size());
final Card card = tempList.remove(index);
mCards.add(card);
}
}
public void print() {
System.out.println(" - - - DECK BEGINS - - - ");
int counter = 0;
for (final Card c : mCards) {
System.out.println("\t" + c);
++counter;
}
System.out.println("> Printed " + counter + " cards.");
System.out.println(" - - - DECK ENDS - - - ");
}
}
public static void main(final String[] args) {
final Deck d = new Deck();
d.print();
d.shuffleRandomly();
d.print();
}
}

Trouble with executing my code: java.lang.NullPointerException [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I just started learning Java required for my course.
Everything seems fine, no syntax errors but when I run my code I have an error
Exception in thread "main" java.lang.NullPointerException
at Deck.<init>(Deck.java:18)
at MainDriver.main(MainDriver.java:17)
Here is my code.
Class Card
public abstract class Card {
public CardValue value;
public CardSuit suit;
CardValue [] cardvalue = CardValue.values();
CardSuit [] cardsuit = CardSuit.values();
public Card () {
value = cardvalue[0];
suit = cardsuit[0];
}
public String toString() {
return this.suit + " of " + this.value;
}
abstract boolean CardCompare(Card P1, Card P2);
}
Class Deck
import java.util.Random;
public class Deck {
Card[] playingCards = new Card[52];
public Deck() {
int cardNumber = 0;
CardValue [] cardvalue = CardValue.values();
CardSuit [] cardsuit = CardSuit.values();
for (int i = 0; i < 4; i++)
{
for(int j = 0; j < 13; j++) //Error here (Deck.java:18)
{
playingCards[cardNumber].value = cardvalue[j];
cardNumber++;
}
playingCards[cardNumber].suit = cardsuit[i];
}
}
public Card draw() {
Random rand = new Random();
int cardDraw = rand.nextInt(52);
return playingCards[cardDraw];
}
}
Class Main
public class MainDriver extends Card{
static final int HANDS = 52;
boolean CardCompare(Card P1, Card P2)
{
if (P1.value.ordinal() > P2.value.ordinal())
return true;
else if (P1.suit.ordinal() > P2.suit.ordinal())
return true;
else return false;
}
public static void main(String[] args) {
Deck player1 = new Deck(); //Some reason there's a error here too (MainDriver.java:17)
Deck player2 = new Deck();
int player1Score = 0, player2Score = 0;
int CardCounter = 0;
while(CardCounter < 52)
{
player1.draw();
player2.draw();
System.out.println(player1 + " " + player2);
CardCounter++;
}
System.out.printf("Final score: Player 1--%d; Player 2--%d", player1Score, player2Score);
}
}
I don't understand why the MainDriver.java:17 is having an error at all. I used abstract in Card because I will also extend it with other class(have not worked on yet) and I will define a different boolean through there. I also have trouble with comparing the cards in the main driver.
I did not include CardValue and CardSuit but they're public enums with suits(Clubs, Diamonds, Hearts, Spades) & values(Two, Three, all the way to Jack, Queen, King, Ace).
If you think you are getting an NPE at this line:
for(int j = 0; j < 13; j++) //Error here (Deck.java:18)
you are mistaken. An NPE at that line is impossible. Nothing in that particular line uses reference types in any way.
Check that you have recompiled all of your code and that the version of the source code matches the compiled classes that you are using.
If we allow for your mistake with building / running, then #Eran has identified a plausible cause of the NPEs.
It's more likely the error is here :
playingCards[cardNumber].value = cardvalue[j];
since you never assign a new Card to playingCards[cardNumber], which is null.
Change your loop to :
for (int i = 0; i < 4; i++)
{
for(int j = 0; j < 13; j++)
{
playingCards[cardNumber] = new Card ();
playingCards[cardNumber].value = cardvalue[j];
cardNumber++;
}
playingCards[cardNumber].suit = cardsuit[i];
}
Also change
public abstract class Card
to
public class Card
Since you can't instantiate an abstract class.

JAVA changing from an array to a list and using the shuffle method

I have an assignment to create a deck of cards and deal five random cards. I finally got it "working" but I need help with a couple things. One I just read that java now has a shuffle method to shuffle a list. We're on arrays right now so I think arrays were wanted is there a way to use the shuffle method with an array? If not can someone guide me in switching to a list? I think it will help with answer my next question. The only thing left for me to do is somehow state how many cards are left in the deck after the 5 random cards are dealt. However, seeing as how I'm using an array and you cannot remove items from an array because it's fixed (right?) I wanted to see if there was a way to simulate removing the cards from the array so that they aren't dealt again? Or would it just be easier to turn the arrays into a list/collection?
Here is my code. Any help is greatly appreciated. Also, I'll take any suggestions on cleaning the code up too...
public class CardGame {
public static void main (String [] args) {
DeckOfCards deck = new DeckOfCards();
//call shuffle
deck.shuffle(1000);
Card b;
for (int i = 0; i < 5; i++) {
b = deck.deal();
System.out.println("Deal a card: " + b);
}
}
}
class Card {
public static final int SPADE = 4;
public static final int HEART = 3;
public static final int CLUB = 2;
public static final int DIAMOND = 1;
private static final String[] Suit = {"*", "Hearts", "Clubs", "Spades", "Diamonds"};
private static final String[] Rank = {"*", "*", "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
private int cardSuit;
private int cardRank;
public Card( int suit, int rank ) {
if ( rank == 1 )
cardRank = 14; // Give Ace the rank 14
else
cardRank = (int) rank;
cardSuit = (int) suit;
}
public int suit() {
return ( this.cardSuit );
}
public String suitStr() {
return( this.Suit[ this.cardSuit ] );
}
public int rank() {
return ( this.cardRank );
}
public String rankStr() {
return ( Rank[ this.cardRank ] );
}
public String toString() {
return ( Rank[ this.cardRank ] + " of "+ Suit[ this.cardSuit ] );
}
}
class DeckOfCards {
public static final int NEWCARDS = 52;
private Card[] deckOfCards; // Contains all 52 cards
private int currentCard; // deal THIS card in deck
public DeckOfCards( ) {
deckOfCards = new Card[ NEWCARDS ];
int i = 0;
for (int suit = Card.DIAMOND; suit <= Card.SPADE; suit++)
for ( int rank = 1; rank <= 13; rank++ )
deckOfCards[i++] = new Card(suit, rank);
currentCard = 0;
}
//shuffle(n): shuffle the deck
public void shuffle(int n) {
int i, j, k;
for ( k = 0; k < n; k++ ){
i = (int) ( NEWCARDS * Math.random() ); // Pick 2 random cards
j = (int) ( NEWCARDS * Math.random() ); // in the deck
//swap these randomly picked cards
Card temp = deckOfCards[i];
deckOfCards[i] = deckOfCards[j];
deckOfCards[j] = temp;
}
currentCard = 0; // Reset current card to deal
}
//deal(): deal deckOfCards[currentCard] out
public Card deal() {
if (currentCard < NEWCARDS) {
return ( deckOfCards[currentCard++] );
}
else{
System.out.println("Out of cards error");
return ( null ); // Error;
}
}
public String toString() {
String s = "";
int k;
k = 0;
for ( int i = 0; i < 4; i++ ) {
for ( int j = 1; j <= 13; j++ )
s += (deckOfCards[k++] + " ");
s += "\n";
}
return (s);
}
}
After all the help I decided to rewrite my code and here is what I got but I'm having a little trouble bringing it all together and making it work!
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CardGame {
public static void main (String [] args) {
DeckOfCards deck = new DeckOfCards();
//call shuffle
deck.shuffle();
Card b;
for (int i = 0; i < 5; i++) {
b = deck.deal();
System.out.println("Deal a card: " + b);
}
}
}
class Card {
enum Suit {
HEARTS(1),
CLUBS(2),
DIAMONDS(3),
SPADES(4);
private int suitValue;
private Suit (int suitValue)
{
this.suitValue = suitValue;
}
public int getSuitValue()
{
return suitValue;
}
}
private Suit suit;
private Value value;
public Card (Suit suit, Value value)
{
this.suit = suit;
this.value = value;
}
public Suit getSuit() {
return suit;
}
public Value getValue() {
return value;
}
/*
public int compareTo(Card o) {
return 0;
}
} */
class DeckOfCards
{
private List<Card> cards = new ArrayList<Card>();
public DeckOfCards () {
for (Suit suit : Suit.values()) {
for (Value value : Value.values()) {
Card card = new Card(suit, value);
cards.add(card);
}
}
}
public List<Card> getCards() {
return cards;
}
public void shuffleDeckOfCards() {
Collections.shuffle(cards);
}
public String toString() {
return this.Value + " of "+ this.Suit;
}
}
Here is a fully working sample program which demonstrates all the things you need - Shuffling and removing cards from an array.
Sample Card class:
public class Card {
private String value = "";
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Card(String value) {
super();
this.value = value;
}
}
Sample program:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class CardGame {
public static void main(String[] args) {
List<Card> pack = new ArrayList<Card>();
Card c1 = new Card("c1");
Card c2 = new Card("c2");
Card c3 = new Card("c3");
pack.add(c1);
pack.add(c2);
pack.add(c3);
System.out.print("List : ");
CardGame.displayCardList(pack);
Card[] packArr = cardListToArray(pack);
System.out.print("Array : ");
CardGame.displayCardArray(packArr);
// http://stackoverflow.com/questions/4228975/how-to-randomize-arraylist
long seed = System.nanoTime();
Collections.shuffle(pack, new Random(seed));
System.out.print("Shuffle List : ");
CardGame.displayCardList(pack);
packArr = cardListToArray(pack);
System.out.print("Shuffle Array : ");
CardGame.displayCardArray(packArr);
System.out.print("Remove Card from Array : ");
CardGame.removeCardFromArray(packArr, new Card("c1"));
CardGame.displayCardArray(packArr);
}
public static boolean removeCardFromArray(Card[] packArr, Card card) {
boolean cardFound = false;
for (int i = 0; i < packArr.length; i++) {
if (packArr[i].getValue().equalsIgnoreCase(card.getValue())) {
packArr[i] = null;
cardFound = true;
break;
}
}
return cardFound;
}
public static Card[] cardListToArray(List<Card> pack) {
Card[] packArr = new Card[pack.size()];
for (int i = 0; i < pack.size(); i++) {
packArr[i] = pack.get(i);
}
return packArr;
}
public static void displayCardList(List<Card> pack) {
for (Card c : pack) {
System.out.print(c.getValue() + ", ");
}
System.out.println();
}
public static void displayCardArray(Card[] packArr) {
for (Card c : packArr) {
if (c == null) {
System.out.print("REMOVED, ");
} else {
System.out.print(c.getValue() + ", ");
}
}
System.out.println();
}
}
Card
In the Card class the suits should be an enum. You can create the enum like this.
enum Suit {
SPADE,
HEART,
CLUB,
DIAMOND
};
Then the class should hold a variable of it's current suit like
Suit suit;
You can change the value of it very easily.
suit = Suit.HEART;
If you must use an index to access a suit you could use
suit = Suit.values()[index];
When getting the rank of the card you could use
return Rank[suit.ordinal()];
The name of the functions in the Card class are not the typical names you should use. Some of these should be getters. I would recommend names like getSuit() and getSuitName(), you want names that just by reading them you can understand what they do. Names like suit() are a little confusing, they don't tell you what they are doing with suit.
DeckOfCards
In the DeckOfCards class, when initializing the deck use a for each loop for the suits.
for (Suit suit : Suits.values()) {
...
}
This will loop over every suit.
If you wanted to switch over to a List you should declare your private variable deckOfCards to be an ArrayList.
private List<Card> deckOfCards = new ArrayList<>();
If you haven't worked with lists before, this is creating a list of Card objects. The diamond operator (<>) assumes the object type from the type you specified before (Card) This is a java 7 feature, if you are working with older version you would use
new ArrayList<Card>();
Instead of tracking your position in the deck, you add a card with the add() function
deckOfCards.add(card);
This would allow you to use Collections.shuffle(deckOfCards) to shuffle the cards around randomly.
To access a card, you use the get(int i) function
deckOfCards.get(index);
If you are still using arrays, when you are shuffling use a Random object. Throw a
Random random = new Random();
in the begging of your class. The inside of the for loop could look like this
int i = random.nextInt(NEWCARDS);
int j = random.nextInt(NEWCARDS);
Card temp = deckOfCards[i];
deckOfCards[i] = deckOfCards[j];
deckOfCards[j] = temp;
In the shuffle function I would change the names of i, j, and k. Variable K should be called i because it is the iterator. Variable j and k should be renamed to more meaningful names.
If you want to convert Arrays to lists you can use
Arrays.asList(new ArrayList<Card>());
And the opposite of that, to convert back to an array.
list.toArray();//This will return an array of Objects[]
Card[] cards = new Card[NEWCARDS];
list.toArray(cards)//This will store the list into the array cards.
//Note if the lists is bigger than the array it is storing it in, the function will return a new array that can hold all of the elemnents in the list.
Note: In these example I have been using ArrayList, there are other implementations of the List class which you may want to research.
Personal Preference
I would remove the parenthesis off of the return statements except on your toString() for the Card class.
You have some extra spaces when using parenthesis in your code such as your DeckOfCards constructor. I would make it like so
public DeckOfCards() {
There also shouldn't be spaces surrounding the stuff inside parenthesis such as
i = (int) ( NEWCARDS * Math.random() );
//should be
i = (int) (NEWCARDS * Math.random());

Deck of cards JAVA

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);
}
}

Categories

Resources