Appending two strings to one index in an Array in Java - java

I've fixed it exactly how I want it now. If anyone else has the same issue I think this is the easiest and most efficient way of trying to set up a deck of cards. You can pick out individual cards using a random variable in deck[random][0] and deck[random][1].
Thanks for all the help, here is my code:
public class NewDeck {
public static void main(String[] args) {
String[] suits = new String[] { "Clubs", "Diamonds", "Spades", "Hearts" };
String[] faces = new String[] { "Ace", "King", "Queen", "Jack" };
String[][] deck = new String[suits.length * (faces.length + 9)][2];
int a = 0;
for (String y : suits) {
for (String x : faces) {
deck[a][0] = x;
deck[a][1] = y;
a++;
}
}
for (String y : suits) {
for (int p = 2; p < 11; p++) {
deck[a][1] = y;
String pp = Integer.toString(p);
deck[a][0] = pp;
a++;
}
}
for (int p = 0; p < deck.length; p++) {
System.out.print(deck[p][0] + " of ");
System.out.println(deck[p][1]);
}
}
}

You should add parameter types to your strings and create a Pair class. Note that you will need a Java compiler of version 1.5 or higher for the generics.
class Pair {
private final String face;
private final String suit;
Pair(String suit, String face) {
this.face = face;
this.suit = suit;
}
#Override
public String toString() {
return "(" + suit + ", " + face + ")";
}
}
Then you can use this Pair class as follows, using the appropriate List methods get and size:
List<Pair> deck = new ArrayList<Pair>();
List<String> suits = new ArrayList<String>();
suits.add("Hearts");
suits.add("Diamonds");
suits.add("Clubs");
suits.add("Spades");
List<String> faces = new ArrayList<String>();
faces.add("Ace");
faces.add("King");
faces.add("Queen");
faces.add("Jack");
for(int suit = 0; suit < suits.size(); suit++){
for(int face = 0; face < faces.size(); face++){
deck.add(new Pair(suits.get(suit), faces.get(face)));
}
}
If you override the toString method of Pair you can also System.out.println(deck) to get your desired string representation of the ArrayList.

Probably you need to change this
deck.add(suits[suit], faces[face]);
with
deck.add(suits[suit] + faces[face]);
as your idea is to concatenate elements from the list and add it the deck list.

You can not store two values at one index of List. But what you can do is
Option 1
Store concatenated \string like
Change
deck.add(suits[suit], faces[face]);
with
deck.add(suits[suit] + "," + faces[face]);
then output deck[2] = suit, face
Option 2
Change list of string to list of Object and this object contains detail of suit and face
public class Deck {
private String suit;
private String face;
// getter and setters;
}
and list become
List<Deck> deck
and add entry as
deck.add(new Deck(suits[suit], faces[face]))

Related

How to create a randomized deck of cards?

I need to create a deck of cards by using two string: "HSCD" and "A2345678910JQK".
public class Deck {
Random random=new Random();
Queue cards=new Queue(112);
String suits="HSCD";
String rands="A2345678910JQK";
public Deck() {
for (int i = 0; i < suits.length(); i++) {
for (int j = 0; j < rands.length(); j++) {
char suit = suits.charAt(random.nextInt(suits.length()));
char rand = rands.charAt(random.nextInt(rands.length()));
if (rand == '1' || rand == '0') {
String s = Integer.toString(10);
cards.enqueue(new Card(suit, s));
} else {
String s1 = Character.toString(rand);
cards.enqueue(new Card(suit, s1));
}
}
}
}
public void display(){
for (int i = 0; i < cards.size(); i++) {
System.out.print(cards.peek());
cards.enqueue(cards.dequeue());
}
}
public Queue getCards() {
return cards;
}
public void setCards(Queue cards) {
this.cards = cards;
}
public String getSuits() {
return suits;
}
public void setSuits(String suits) {
this.suits = suits;
}
public String getRands() {
return rands;
}
public void setRands(String rands) {
this.rands = rands;
}}
I have Deck and Card classes.
public class Card {
private char rand;
private String suit;
public Card(char rand, String suit) {
this.rand = rand;
this.suit = suit;
}
public Card(){}
public char getRand() {
return rand;
}
public void setRand(char rand) {
this.rand = rand;
}
public String getSuit() {
return suit;
}
public void setSuit(String suit) {
this.suit = suit;
}
public String toString(){
return "\t"+rand + suit;
}}
But i couldn't solve that every suits must have 13 rands. In my program my deck is randomly created. And my deck must be shuffled. I can't use list or array structures because teacher told us so :). Can you help me?
You are creating 14 cards per suit, not 13: you're creating 10 twice. Remove with 0 or 1 from rands.
It will be easier if you first create the cards, then shuffle them.
Creation of cards should be similar to what you're already doing, minus the randomization - just go through suits and values in order:
for each suit:
for each value:
sortedCards.add(new Card(suit, value));
Then, shuffle the cards as follows:
while (sortedCards is not empty):
shuffledCards.add(sortedCards.get(random.nextInt(sortedCards.size())))
Just duplicate four time the second string. After you take two random numbers one correspond to the sign and one to the number. Finally you put sign+number in memory and you remove the number in the string :
String signs = "HSCD";
String numbersH = "A2345678910JQK";
String numbersS = "A2345678910JQK";
String numbersC = "A2345678910JQK";
String numbersD = "A2345678910JQK";
ArrayList<String> deck = new ArrayList<String>();
Random random = new Random();
while(deck.size()<52){
int sign = random.nextInt(signs.lenght());
if(sign==0 && numbersH.lenght()>0){
int number = random.nextInt(numbersH.lenght());
deck.add(signs.charAt(sign)+numbersH.charAt(number));
numbersH = numbersH.substring(0,number)+numberH.substring(number+1);
}//here the same for other signs
}
Another method : Create your deck like iluxa say you and shuffle with this :
Random rand = new Random();
for(int i=0;i<300;i++){
int a = rand.nextInt(deck.size());
int b = rand.nextInt(deck.size());
Card cA = deck.get(a);
deck.set(a, deck.get(b));
deck.set(b, cA);
}
That's code will suffle your deck by switch two random cards many times.
You haven't included the Queue class so help is going to be limited. Here are some other suggestions.
String suits="HSCD";
String ranks="A23456789TJQK";
for (int i = 0; i < 52; i++) {
int suit = i/13; // index into suit 0 to 3 inclusive
int rank = i%13; // index into rank 0 to 12 inclusive
cards.enqueue(new Card(suits.charAt(suit), ranks.charAt(rank));
}
Also, quite often, card game software uses a T for ten, which is what I did in this example. It can be changed but in your implementation you can't store 10 as as a single character and it is cumbersome to maintain two types for card ranks. So you should probably make all your ranks and suits as type String.

Creating Two Identical, But Distinct, Decks of Cards, And Simultaneously Drawing From Both

I am utilizing the standard array-driven approach to creating, shuffling, and drawing a 52-card deck of standard playing cards. My challenge is coming in the form of having two identical, but distinct, decks drawing simultaneously, side-by-side.
Originally I thought having two instances of the class Deck in the executable DeckDrawTest class would be sufficient, but when I asked for the class to draw 104 (52 x 2) times, I got all 52 cards of one deck and 52 null entries. I then made a duplicate Deck class called Deck2, and changed all the method and variable names while keeping the functionality the same - no dice, same results. I then tried to overcome a potential multiple inheritance problem by duplicating the Card class that both Deck and Deck2 drew from, making another class identical to Card called Card2 but with different variable names. Has not changed the outcome. Code is presented below.
Card
public class Card
{
private final String name;
private final String suit;
public Card(String cardName, String cardSuit) {
this.name = cardName;
this.suit = cardSuit;
}
public String toString() {
return name + "of " + suit;
}
}
Deck2 (which draws from Card for now, will fix names once I get it functional):
public class Deck2
{
private static final SecureRandom randomClam = new SecureRandom();
private static final int DECKSIZE2 = 52;
private Card[] deck = new Card[DECKSIZE2];
private int currentCard = 0;
public Deck2() {
String[] names2 = {"A ", "2 ", "3 ","4 ", "5 ", "6 ", "7 ", "8 ", "9 ", "10 ", "J ", "Q ", "K "};
String[] suits2 = {"♠ ", "♥ ", "♣ ", "♦ "};
for (int count = 0; count < deck.length; count ++) {
deck[count] =
new Card(names2[count % 13], suits2[count /13]);
}
}
public void shuffle2() {
currentCard = 0;
for (int first2 = 0; first2 < deck.length; first2++) {
int second2 = randomClam.nextInt(DECKSIZE2);
Card temp2 = deck[first2];
deck[first2] = deck[second2];
deck[second2] = temp2;
}
}
public Card dealCard(){
if (currentCard < deck.length) {
return deck[currentCard++];
}
else {
return null;
}
}
}
DeckDrawTest (which is drawing from Deck and Deck2)
public class DeckDrawTest
{
public static void main(String[] args) {
Deck myDeck = new Deck();
myDeck.shuffle();
Deck2 yourDeck = new Deck2();
yourDeck.shuffle2();
for(int i = 1; i <=104; i++){
System.out.printf("%-20s", myDeck.dealCard(), "%-20s", yourDeck.dealCard());
if(i %2 == 0) {
System.out.println();
System.out.println();
}
}
}
}
So how do I get this program to draw from two distinct, but identical, decks, instead of just drawing from one?
Your variable i goes up to 104, but in each loop you call dealCard on both decks. That's where the null values come from. You only need to loop up to 52:
for (int i = 1; i <=52; i++) {
Your output using printf is wrong, the function only expects one formatter. Your version just outputs the value of myDeck.dealCard() and also calls (but not uses) yourDeck.dealCard(). To create a line with the output of both calls, use something like this:
System.out.printf("%-20s %-20s", myDeck.dealCard(), yourDeck.dealCard());

How to Remove a Card from a Deck

I'm trying to find a way to delete a specific card or a random card in a deck and return that deleted card. I've created classes for Card and DeckHand. In the DeckHand class, I'm trying to create a delete method that allows the user to pick a card value, delete ONE instance of that card value from the deck, then returns the card that was deleted, and lastly, shorten the array by 1. I'm also trying to make a deleteAny method that deletes a random card from the deck, returns the card that was deleted, and shorten the array by 1.
For the delete method, I'm having trouble finding a way to say:
*if the value input by the user isn't in the deck, print an error message.
*if it is, then find the first instance of a card with that value, delete it, and return the card.
I don't understand how to find the first instance of a card with the value and then finding a way to set an available suit to create the instance of the card to then delete it and shift the positions in the array.
I started trying to do an deleteAny method that deletes a random card. I'm able to get the card output to the user that's getting removed, but I'm getting an error with my method. Any ideas?
Card Class:
class Card {
private int _value, _suit;
private String[] _cardValues = {null, "Ace", "2", "3", "4","5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King"};
private String[] _cardSuits = {null, "Clubs", "Diamonds", "Hearts", "Spades"};
public Card(int value,int suit) {
_value = value;
_suit = suit;
}
public int getCardValue() {
return _value;
}
public int getCardSuit() {
return _suit;
}
public String toString() {
return _cardValues[_value] + " of " + _cardSuits[_suit];
}
}
Deck class:
class DeckHand{
private Card[] _deckHand;
private int _deckSize;
private static final int MAXSIZE = 52;
private Card[] newDeck;
public DeckHand() {
_deckHand = new Card[MAXSIZE];
_deckSize = 0;
}
public DeckHand(int deckSize) {
_deckHand = new Card[MAXSIZE];
int index = 0;
for (int suit = 1; suit <= 4; suit++) {
for (int rank = 1; rank <= 13; rank++) {
_deckHand[index] = new Card(rank, suit);
index++;
}
}
_deckSize = deckSize;
}
//Here's the delete method, but I have no idea what I'm doing here.
public void delete(int value) {
for (int i = 0; i<_deckSize; i++) {
if(_deckHand[i].getCardValue()==value) {
_deckHand[value] = _deckHand[_deckSize-1];
newDeck = new Card[_deckHand.length-1];
} else
System.out.println("\n--------------------------------------"
+ "\nThe deck does not contain that value"
+ "\n--------------------------------------");
}
}
//Here's the deleteAny method, but I'm getting an error
public void deleteAny(Card newCard) {
if(_deckSize >= MAXSIZE) {
newDeck = new Card[_deckHand.length-1];
for(int i = 0; i<_deckSize; ++i)
if(_deckHand[i].equals(newCard)) {
newDeck[i] = _deckHand[i];
}
_deckHand = newDeck;
}
//the error says it has to do with this next line
_deckHand[_deckSize-1] = newCard;
_deckSize-=1;
}
}
Main:
Here's part of my main method that uses these delete and deleteAny methods:
case 3:
System.out.println("\nWhich card would you "
+ "like to remove from the deck?");
valueOption();
System.out.print("\tOption: ");
value = keyboard.nextInt();
if(pickDeck == 1) {
standard.delete(value);
} else {
System.out.println("\n-------------------------"
+ "-------------------------------\n"
+ "The card value \"" + values[value]
+ "\" appears "
+ empty.count(value)
+ " times in the deck."
+ "\n---------------------------------"
+ "-----------------------");
}
break;
case 4:
Random generator = new Random();
value = generator.nextInt(13)+1;
suit = generator.nextInt(4)+1;
newCard = new Card(value,suit);
System.out.println("\n--------------------------"
+ "---------------------"
+ "\n" + newCard + " was removed from the "
+ "deck."
+ "\n--------------------------"
+ "---------------------");
if(pickDeck==1)
standard.deleteAny(newCard);
else
empty.deleteAny(newCard);
break;
If you need to remove an element from an array without using system.arraycopy or array.utils you might do something like the remove function that follows. (It is only static because I tested this up in one file.)
import java.util.Arrays;
public class HelloWorld{
public static String[] remove(String[] arr,int index){
String[] ret = new String[arr.length-1];
for(int i = 0; i<index; i++){
ret[i]=arr[i];
}
for(int i = index+1; i<arr.length; i++){
ret[i-1]=arr[i];
}
return(ret);
}
public static void main(String []args){
System.out.println("Hello World");
String[] r = {"This","Is","ATest"};
System.out.println(Arrays.toString(remove(r,0)));
System.out.println(Arrays.toString(remove(r,1)));
System.out.println(Arrays.toString(remove(r,2)));
}
}
My answer uses most of your method from above. I've tweaked it to incorporate means of checking if we've found the value before.
public Card delete(int value) {
Card result = new Card(-1,-1); // Starter card to check if value has been found.
newDeck = new Card[_deckHand.length-1]
int location = -1 // Initial location. This changes once we find the value.
for (int i = 0; i<_deckHand.length; i++) {
if(_deckHand[i].getCardValue()==value) { // We've found a match
if(result.value==-1){ // Check if our starter card still has its original value
result = new Card(_deckHand[i].getCardValue(),_deckHand[i].getCardSuit());
location = i; // Adjust location
}
}
// make a helper that does the rest. That way you can delete any card from the deck.
if(location != -1){ // See if location has been adjusted (i.e. value has been found)
for(int i = 0; i < location; i++){ // Copy the remnants of _deckHand to newDeck
newDeck[i]=_deckHand[i];
}
for(int j = location+1; j<_deckHand.length-1; j++){
newDeck[j]=_deckHand[j];
}
_deckHand = new Card[newDeck.length]
_deckHand = newDeck // Change _deckHand to newDeck
return result; // Return the card that was removed from _deckHand.
} else { // `else` indicates that the value has not been found
System.out.println("\n--------------------------------------"
+ "\nThe deck does not contain that value"
+ "\n--------------------------------------");
}
}
Edit:
Didn't see the last part about deleteAny(). You could make a helper method called helperDelete(value,location) that takes the value to delete and the position of the card which you want to delete. Using the same strategy as above, once you find the location of the initial value that you want, remove it from the deck, copy the deck into a new, shortened deck, and set your deck instance to be the new deck.
This should allow you to remove the card at a random position value, as needed by deleteAny(), and at a specified location value, as needed by delete().

Problems on poker game and comparator?

I am trying to create a poker game in which I create the deck in the Card class, and use a comparator to sort the deck in alphabetical order. I'm having trouble with what to put in the comparator, and in my dealer class, (this is where I create the deck, shuffle, as well as calling the comparator). When my CompareCards does compile, my Dealer class will give me the error of:
Dealer.java:24: error: incompatible types: void cannot be converted to String
String s = Collections.sort(deck);
^
Note: Dealer.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
I know that when doing the sort, you have to include the Comparator name, but in this case it doesn't work either way. Here is my card class:
import java.util.*;
public class Card{
String suit = null;
String value = null;
String rank = null;
public static final String[] SUIT = {"C", "D", "H", "S" };
public static final String[] RANK = {"A","2","3","4","5","6","7","8","9","T","J","Q","K"};
public Card(int i, int j){
suit = RANK [i];
rank = SUIT [j];
value = rank + suit;
}
public String getSuit(){
return suit;
}
public String getRank(){
return rank;
}
public String toString(){
return(value);
}
}
Here is my Comparator and CompareCards class:
public interface Comparator <Card>{
public int compare(Card o1, Card o2);
}
public class CompareCards implements Comparator<Card>{
public int compare(Card c1, Card c2){
int x = 0;
int y = 0;
int dx = c1.getRank() - c2.getRank();
if(dx == 0){
x = c1.getRank()-c2.getRank();
}
else{
y = c1.getSuit() - c2.getSuit();
}
return x;
}
And here is the dealer class:
import java.util.*;
public class Dealer{
public static void main(String[]args){
// creating deck
List<Card> deck= new ArrayList<Card>();
// calling Card
for(int i = 0; i < 13 ; i++){
for(int j = 0; j < 4 ; j++){
// String s = RANK[i] +SUIT[j];
deck.add(new Card(i, j));
}
}
finding21(deck);
}
public static void finding21 (List deck){
String s = Collections.sort(deck);
System.out.println("Sorted deck: " + s);
// After I sort the deck I am supposed to do a binary search
// for the queen of hearts
/* Collections.shuffle(deck);
System.out.println("Shuffled deck: " + deck);
String HQ = Collections.binarySearch(deck, "HQ");
System.out.print(HQ);
System.out.println(queenH);*/
}
}
Collections.sort does an in-place sort and does not return a value.
That's why the compiler says you can't convert a void to a String.
The void type is used for functions with no return value.
Just use:
Collections.sort(deck);
If you want to print the sorted deck after, you can use:
System.out.println("Sorted deck: " + deck);

How to shuffle a deck of cards using Java (trying to use hashmap, not working)?

I have a hashmap<Integer, Card> Card is a class. I have initialized the hashmap with keys from 0-51 and the values are array of Card, as follows
Card [] card = new Card[52]
for (int i=1; i<=13; i++)
for (int j=0; j<4; j++)
card[++index] = new Card( ((i*10)+j) );
and I populate the hashmap as follows:
for (int i=1; i<=13; i++)
for (int j=0; j<4; j++)
deck.put( ++key, card[++index] );
Now, what I want to do is to shuffle the values side of the hashmap, i do not want,for an example, the key[1] corresponds to card[0] and key[1] corresponds to card[1]. I want, for an exampel, the key[1] corresponds to card[38]. I want the values side to be shuffled. I tried the following:
Collections.shuffle(card,new Random()); But it seems it accepts only ArrayList and List.
HashMaps do not have a predictable order, and shuffling an unordered data structure doesn't make sense. From the Java reference docs:
This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
If you are using keys from 0-51, you should just add all of the cards to an ArrayList. Then you can use Collections.shuffle(arrayList)
can I shuffle an array?
Yes. Here's one way.
Integer[] t = { 1, 2, 3, 4, 5 };
Collections.shuffle(Arrays.asList(t));
System.out.println(Arrays.toString(t));
You should consider adjusting your design to include a Deck and Card class. Examples are shown below. Your "encoding" for a card has a potential flaw 10*suit + card will have suit 0 card 13 have the same value as suit 1, card 3. If you want to compare two cards to see which "wins", you should add a method to the Card class that does this.
Try this:
Deck Class
package com.example.cards;
import java.util.Arrays;
import java.util.Collections;
public class Deck {
// Class fields
// Object fields
private Integer[] deckOrder;
private int nextCard;
private Card[] cards;
public Deck() {
deckOrder = new Integer[52];
cards = new Card[52];
for (int i=0; i < deckOrder.length; i++) {
deckOrder[i] = i;
cards[i] = new Card(i/13,i % 13);
}
}
public void shuffle() {
Collections.shuffle(Arrays.asList(deckOrder));
nextCard = 0;
}
public Card deal() {
if (nextCard < deckOrder.length) {
nextCard++;
return cards[deckOrder[nextCard-1]];
} else {
return null;
}
}
}
Card Class
package com.example.cards;
public class Card {
// Class fields
public final static String[] suit = {"Spades","Hearts","Diamonds","Clubs"};
public final static String[] card = {"Ace","King","Queen","Jack","Ten","Nine"
,"Eight","Seven","Six","Five","Four"
,"Three","Two"};
// Object fields
private int suitIndex;
private int cardIndex;
public Card(int suit, int card) {
suitIndex = suit;
cardIndex = card;
}
public int getSuitIndex() { return suitIndex;}
public int getCardIndex() { return cardIndex;}
public String getSuit() { return suit[suitIndex];}
public String getCard() { return card[cardIndex];}
public int getEncodedCard() { return 100*suitIndex + cardIndex;}
}
Test driver
package com.example.cards;
public class TestShuffle {
public static void main(String[] args) {
Deck myDeck = new Deck();
for (int deal = 1; deal < 3; deal++) {
System.out.println("======================Deal " + deal);
for (int i = 0; i < 52; i++) {
Card nextCard = myDeck.deal();
System.out.println("Card " + i + ". " + nextCard.getCard()
+ " of " + nextCard.getSuit() + "(encoded "
+ nextCard.getEncodedCard() + ")");
}
myDeck.shuffle();
}
}
}
try this:
public static void main(String args[]) {
Map<String, Object> x = new HashMap<String, Object>();
x.put("x", 1); x.put("y", 2); x.put("z", 3); x.put("w", 4);
System.out.println(x);
List<Object> vs = new ArrayList<Object>(x.values());
Collections.shuffle(vs);
System.out.println(vs);
Iterator<Object> vIter = vs.iterator();
for (String k : x.keySet()) x.put(k, vIter.next());
System.out.println(x);
}
output :
{w=4, x=1, y=2, z=3}
[2, 3, 1, 4]
{w=2, x=3, y=1, z=4}
What you can do is extract your key value pairs as a List of Map.Entry and shuffle it and put your Map.Entry values in the cleared map
Set<Map.Entry<Integer,Card> cardEntrySet= deck.entrySet();
List<Map.Entry<Integer,Card> cardsEntryList = new ArrayList<>(cardEntrySet);
Collections.shuffle(cardsEntryList);
deck.clear();
for(Map.Entry<Integer,Card> entry :cardsEntryList){
deck.put(entry.getKey(),entry.getValue());
}

Categories