Cast an object to arraylist?
In my efforts to learn I have moved a method to initialize a deck of cards into its own Deck class. This has led to issues with the Deck not being an ArrayList. Here is my code:
publicclass handOfCards{
staticint startCards = 5;
static String[] hand =new String[startCards];
publicstaticvoid main(String[] args){
handOfCards newHand =new handOfCards();
Deck deck =new Deck();
deal(deck);
}
staticvoid deal(Deck deck){
int cardCount = 0;
int index = 0;
Random generator =new Random();
while (cardCount < startCards){
index = generator.nextInt((deck.getSize(deck)));
String card = (deck.getCard(deck, index));
printCards(card);
createHand(card, cardCount);
deck.removeCard(deck, index);
cardCount++;
}
}
}
And the code for the Deck class:
publicclass Deck{
final String[] value =new String[]{"2","3","4","5",
"6","7","8","9","10","Jack","Queen","King","Ace"};
final String[] suit =new String[]{"Spades","Clubs","Hearts","Diamonds"};
ArrayList<Object> deck =new ArrayList<Object>();{
for (int i = 0; i < value.length; i++){
for (int j = 0; j < suit.length; j++){
String card = value[i] +" of " + suit[j];
deck.add(card);
}
}
}
int getSize(ArrayList deck){
int size = 0;
size = deck.size();
return size;
}
String getCard(ArrayList deck,int index){
String card = (String)deck.get(index);
return card;
}
void removeCard(ArrayList deck,int index){
deck.remove(index);
}
}
How do I go about passing the deck as a parameter correctly?
Not sure your exact question, but I think you want:
String getCard(ArrayList deck, int index){
String card = (String)deck.get(index);
return card;
}
to be:
String getCard(int index){
String card = (String)deck.get(index);
return card;
}
You don't need to pass a "Deck" into getCard.
If you declare the ArrayList to be ArrayList<String> instead of ArrayList<Object>, you won't need the explicit cast to String.
Same with removeCard--just pass the index.
> Not sure your exact question, but I think you want:
> String getCard(ArrayList deck, int index){
> String card = (String)deck.get(index);
> rn card;
> }
> to be:
> String getCard(int index){
> String card = (String)deck.get(index);
> rn card;
> }
> You don't need to pass a "Deck" into getCard.
>
> If you declare the ArrayList to be ArrayList<String>
> instead of ArrayList<Object>, you won't need the
> explicit cast to String.
>
> Same with removeCard--just pass the index.
Thanks for your help. Both suggestions worked perfectly.
You can take the design an extra step and have a Card class. Then your Deck class will have an arrayList of Cards. The getCard method will return the next available Card in the list.
> You can take the design an extra step and have a Card
> class. Then your Deck class will have an arrayList of
> Cards. The getCard method will return the next
> available Card in the list.
Trying to implement this and ran into a couple of issues. Here is the deck class now:
public class Deck{
ArrayList<String> deck = new ArrayList<String>();{
Card card = new Card();
card.initializeCards();
}
int getSize(){
int size = 0;
size = deck.size();
return size;
}
String getCard(int index){
String card = deck.get(index);
return card;
}
void removeCard(int index){
deck.remove(index);
}
void addCard(String card){
deck.add(card);
}
}
I believe I am in an infinite loop with how I call the card class, which is below:
public class Card extends Deck{
final String[] value = new String[]{"2","3","4","5",
"6","7","8","9","10","Jack","Queen","King","Ace"};
final String[] suit = new String[]{"Spades", "Clubs", "Hearts", "Diamonds"};
void initializeCards(){
for (int i = 0; i < value.length; i++){
for (int j = 0; j < suit.length; j++){
String card = value[i] + " of " + suit[j];
deck.addCard(card);
}
}
}
}
The other issue is the deck.addCard(card); statement above. It says the addCard(String) method is undefined but I thought I defined it here:
void addCard(String card){
deck.add(card);
}
Suggestions for correcting these errors please...
You have Card extending Deck. Does it make sense that Paw should extend Dog?
The arrayList in Deck should contain Cards not Strings. The Card class should only contain two bits of information: suit and value. Creation of the Card objects should be in the Deck class not the Card class.
Try working on fixing these things.
Rather than have the caller create a Random object that selects random indices from the Deck, it would make more sense to have the Deck know how to randomize itself, either with a Random object or using java.util.Collections.shuffle.
It really doesn't make sense (for most cardgames, anyway) to have a deck of cards where you take the nth card from the deck. If you take cards from an arbitrary location in the deck when dealing in poker, then you're cheating.
So you should have a method, say Deck.shuffle(), to shuffle the deck, and then another method, say Deck.topCard() to get and remove the top card from the deck (which may have been shuffled at this point). The caller shouldn't be able to remove cards from arbitrary locations in the deck.
> Rather than have the caller create a Random object
> that selects random indices from the Deck, it would
> make more sense to have the Deck know how to
> randomize itself, either with a Random object or
> using java.util.Collections.shuffle.
>
> It really doesn't make sense (for most cardgames,
> anyway) to have a deck of cards where you take the
> nth card from the deck. If you take cards
> from an arbitrary location in the deck when dealing
> in poker, then you're cheating.
>
> So you should have a method, say Deck.shuffle(), to
> shuffle the deck, and then another method, say
> Deck.topCard() to get and remove the top card from
> the deck (which may have been shuffled at this
> point). The caller shouldn't be able to remove cards
> from arbitrary locations in the deck.
From the standpoint of emulating reality, this is obviously much closer to how it would work. Do the mechanics of how it is done really matter, however? Is one random selection from the deck somehow going to be less of a true reflection than randomizing the entire deck and picking the top card? Please elaborate.
> You have Card extending Deck. Does it make sense that
> Paw should extend Dog?
Sorry, trying to read as much about a couple of things as I can. I know it doesn't make much sense but I needed access to a couple of variables from my Deck class. That was the quickest fix. Advice?
>
> The arrayList in Deck should contain Cards not
> Strings. The Card class should only contain two bits
> of information: suit and value. Creation of the Card
> objects should be in the Deck class not the Card
> class.
>
> Try working on fixing these things.
I am working on them and I am very close. I have reworked the classes to this:
public class Deck{
final String[] value = new String[]{"2","3","4","5",
"6","7","8","9","10","Jack","Queen","King","Ace"};
final String[] suit = new String[]{"Spades", "Clubs", "Hearts", "Diamonds"};
ArrayList<Card> deck = new ArrayList<Card>();{
Card card = new Card();
for (int i = 0; i < value.length; i++){
for (int j = 0; j < suit.length; j++){
card.initializeCards(i,j);
deck.add(card);
}
}
}
int getSize(){
int size = 0;
size = deck.size();
return size;
}
String getCard(int index){
String card = deck.get(index);
return card;
}
void removeCard(int index){
deck.remove(index);
}
void addCard(String card){
deck.add(card);
}
}
and:
public class Card extends Deck{
Card initializeCards(int i, int j){
String card = value[i] + " of " + suit[j];
return card;
}
}
Now I am just having some issues between the card and string. I will keep working. Thanks for all the help.
> The arrayList in Deck should contain Cards not
> Strings.
When I try to change my arrays and arraylists to contain Card objects, it has a cascading effect on this program. On one end I have:
String card = value[i] + " of " + suit[j];
Which is a string but I need a Card object. I am not sure if I can cast this to a Card but I have been unable to so far. On the other end I have a method that calls split which breaks my card back into its rank and suit for reasons of hand comparison:
public static void compareHand(String[] hand){
String[] tokens = new String[hand.length];
Map<String, Object> rank = new HashMap<String, Object>();
Map<String, Object> suit = new HashMap<String, Object>();
for (int j = 0; j < hand.length; j++){
tokens = hand[j].split("\\s");
Split needs a string passed in. I would guess I need a regex instead of the split. It all comes down to how I declare the card. Any suggestions?
As stated, Card should not extend Deck.
Say you had a Person with two attributes: First Name, Last Name. It might look like this:
public class Person
{
private String firstName;
private String lastName;
public String getFirstName();
public String getLastName();
public Person(String first, String last)
{
firstName = first;
lastName = last;
}
public String toString()
{
return firstName + " " + lastName;
}
}
You need a class Card that looks like the above, except that you want a "value" and a "suit", not a "firstName" and a lastName". You may need to add more methods (e.g., "equals"), but that should give you a start. You don't need setSuit/setValue, because a card's suit/value never change.
Can you figure out how to write a Card class using that example? I didn't fill in getFirstName/getLastName, but you should be able to figure those out.
If done correctly, this loop:
for (int j = 0; j < suit.length; j++){
card.initializeCards(i,j);
deck.add(card);
}
will just be:
for (int j = 0; j < suit.length; j++){
deck.add(new Card(value[i], suit[j]));
}
Also, you can use enhanced for loop to populate your deck, like so:
class Deck{
final String[] value = new String[]{"2","3","4","5",
"6","7","8","9","10","Jack","Queen","King","Ace"};
final String[] suit = new String[]{"Spades", "Clubs", "Hearts", "Diamonds"};
ArrayList<Card> deck = new ArrayList<Card>();
{
for (String cardVal : value){
for (String cardSuit : suit){
deck.add(new Card(cardVal,cardSuit));
}
}
}
int getSize(ArrayList deck){
return deck.size();
}
Card getCard(int index){
return (Card)deck.get(index);
}
void removeCard(int index){
deck.remove(index);
}
void shuffle()
{
Collections.shuffle(deck);
}
}
I also added a shuffle method for you. So between the post above and this one, you should be able to finish the Deck Class and the Card Class.
Message was edited by:
SomeoneElse
Thanks to both of you. I was able to implement much of what was suggested and the printed output was correct. One last issue that I mentioned before was that now that I am passing aroung objects instead of strings, I am having an issue trying to call a split on a card. This obviously worked fine when the card was a string but now it has issues. See below:
public static void compareHand(Card[] hand){
String[] tokens = new String[hand.length];
Map<String, Object> rank = new HashMap<String, Object>();
Map<String, Object> suit = new HashMap<String, Object>();
for (int j = 0; j < hand.length; j++){
tokens = hand[j].split("\\s");>>>>>>>>>>>>>>>>>>>This Line
if (rank.containsKey(tokens[0])){
((mapCounter)rank.get(tokens[0])).i++;
}
else{
rank.put(tokens[0], new mapCounter());
}
if (suit.containsKey(tokens[2])){
((mapCounter)suit.get(tokens[2])).i++;
}
else{
suit.put(tokens[2], new mapCounter());
}
}
This code is to break up the card into its components so I can run some comparisons on the hand. The marked line is now an issue. I cannot cast by placing (String) at the beginning. How do i return a card object back into a string?
Never mind. I used:tokens = hand[j].toString().split("\\s");and it worked fine. Thanks to everyone that has helped me.
Here is what I have so far. If anyone has anymore suggestions on how I could improve this, please let me know. I did not implement the collections.shuffle yet as I am not sure if shuffling the entire deck adds an improvement over picking and dealing out a random card (please expound if you disagree).
package poker;
import java.util.*;
class mapCounter {
int i = 1;
public String toString() { return Integer.toString(i); }
}
public class handOfCards{
static int startCards = 5;
static Card[] hand = new Card[startCards];
public static void main(String[] args){
handOfCards newHand = new handOfCards();
Deck deck = new Deck();
deal(deck);
}
static void deal(Deck deck){
int cardCount = 0;
int index = 0;
Random generator = new Random();
while (cardCount < startCards) {
index = generator.nextInt((deck.getSize()));
Card card = (deck.getCard(index));
printCards(card);
createHand(card, cardCount);
deck.removeCard(index);
cardCount++;
}
}
static void printCards(Card card){
System.out.println(card);
}
public static void createHand(Card card, int index){
hand[index] = card;
if (index == startCards - 1){
compareHand(hand);
}
}
public static void compareHand(Card[] hand){
String[] tokens = new String[hand.length];
Map<String, Object> rank = new HashMap<String, Object>();
Map<String, Object> suit = new HashMap<String, Object>();
for (int j = 0; j < hand.length; j++){
tokens = hand[j].toString().split("\\s");
if (rank.containsKey(tokens[0])){
((mapCounter)rank.get(tokens[0])).i++;
}
else{
rank.put(tokens[0], new mapCounter());
}
if (suit.containsKey(tokens[2])){
((mapCounter)suit.get(tokens[2])).i++;
}
else{
suit.put(tokens[2], new mapCounter());
}
}
boolean trip = false;
boolean pair = false;
String tripRank = "";
String pairRank = "";
for (Iterator iter = rank.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)(entry.getKey());
String value = (entry.getValue()).toString();
if (value.equals("1")){
System.out.println("You have one " + key + ".");
}
else if (value.equals("2")){
if (trip == true){
System.out.println("You have a full house! "
+ tripRank + "s over " + key + "s.");
}
else if (pair == true){
System.out.println("You have two pair... "
+ key + "s and " + pairRank + "s.");
}
else{
System.out.println("You have a pair of " + key + "s.");
pair = true;
pairRank = key;
}
}
else if (value.equals("3")){
if (pair == true){
System.out.println("You have a full house! "
+ key + "s over " + pairRank + "s.");
}
else
System.out.println("You have trip " + key + "s.");
trip = true;
tripRank = key;
}
else if (value.equals("4")){
System.out.println("You have quad " + key + "s.");
}
}
for (Iterator iter = suit.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
String value = (entry.getValue()).toString();
if (value.equals("5")){
System.out.println("You have a " + key + " flush");
}
}
}
}
Deck class:
package poker;
import java.util.ArrayList;
public class Deck{
final String[] value = new String[]{"2","3","4","5",
"6","7","8","9","10","Jack","Queen","King","Ace"};
final String[] suit = new String[]{"Spades", "Clubs", "Hearts", "Diamonds"};
ArrayList<Card> deck = new ArrayList<Card>();{
for (String cardVal : value){
for (String cardSuit : suit){
deck.add(new Card(cardVal, cardSuit));
}
}
}
int getSize(){
return deck.size();
}
Card getCard(int index){
return deck.get(index);
}
void removeCard(int index){
deck.remove(index);
}
}
And card class:
package poker;
public class Card {
private String cardSuit;
private String cardRank;
public Card (String value, String suit){
cardSuit = suit;
cardRank = value;
}
public String toString(){
return cardRank + " of " + cardSuit;
}
}
You shouldn't use split anymore at all.
That's what the getSuit and getValue were supposed to help you do.
Which do you fine easier to understand (especially if you pretend someone else wrote the code, and wants you to read it)?
Your way:
tokens = hand[j].toString().split("\\s");
if (rank.containsKey(tokens[0])){
((mapCounter)rank.get(tokens[0])).i++;
}
else{
rank.put(tokens[0], new mapCounter());
}
With getSuit/getRank (similarly, replace the test for "token[2]" with "cardSuit"):
String cardSuit = hand[j].getSuit();
String cardRank = hand[j].getRank();
if (rank.containsKey(cardRank)){
((mapCounter)rank.get(cardRank)).i++;
}
else{
rank.put(cardRank, new mapCounter());
}
By the way, MapCounter is a class name, so it should be capitalized.
And, you don't need (it's redundant):
if (trip == true)
Just use:
if (trip)
Sorry if I have butchered some of this. It works as intended. Here are the two pieces again:
public static void compareHand(Card[] hand){
//String[] tokens = new String[hand.length];
Map<String, Object> rank = new HashMap<String, Object>();
Map<String, Object> suit = new HashMap<String, Object>();
for (int j = 0; j < hand.length; j++){
String cardSuit = hand[j].getSuit(hand[j]);
String cardRank = hand[j].getRank(hand[j]);
//tokens = hand[j].toString().split("\\s");
if (rank.containsKey(cardRank)){
((mapCounter)rank.get(cardRank)).i++;
}
else{
rank.put(cardRank, new mapCounter());
}
if (suit.containsKey(cardSuit)){
((mapCounter)suit.get(cardSuit)).i++;
}
else{
suit.put(cardSuit, new mapCounter());
}
}
And:
public class Card {
private String cardSuit;
private String cardRank;
public String getSuit(Card card){
String[] tokens = card.toString().split("\\s");
String suit = tokens[2];
return suit;
}
public String getRank(Card card){
String[] tokens = card.toString().split("\\s");
String rank = tokens[0];
return rank;
}
public Card (String value, String suit){
cardSuit = suit;
cardRank = value;
}
public String toString(){
return cardRank + " of " + cardSuit;
}
}
Thanks for all your help on this. I have learned quite a bit about structure and syntax from this.
You're welcome, and I'm glad you're learning syntax and structure.
But, you are missing the point. :-(
You do not want to have "split" of the "toString" value anywhere in your code.
getRank should be really simple. getSuit is like it. No parameters, and nothing inside except a simple "return".
public String getRank() {return cardRank;}
And, your 'rank' and 'suit' maps should have "MapCounter" values, so you don't need the additional cast:
Map<String, MapCounter> rank = new HashMap<String, MapCounter>();
...
String cardRank = hand[j].getRank();
...
rank.get(cardRank).i++;
...
and similar for Suit.
Keep trying. You'll figure it out soon. :-)
Wow. I had thought that those methods had to have something in them. I have to admit that that structure is over my head. I will keep looking at it and try to find some other examples. Once again, thanks for all your help.