Reputation: 79
I have been trying to create a basic card game(experiment) using java. After shuffling the deck of cards, I need to pass 6 shuffled cards to each player based on number of players which took participated in the game. (Max 6 players)
By using setHand() method in "Player" class, I was able to dislay 6 cards but after starting the game, in main method by looping through the players, I was shown only 2 cards if there is ever 2 players.
public static void main (String[] args) {
//Create players between 2-6
Game newGame = new Game();
List<Player> players = newGame.createPlayers();
//Let user decide the number of cards set either 24 or 36 or 52 and create deck
if(players != null){
newGame.createDeck(players);
for (Player player: players){
player.showHand();
}
}
}
public class Game {
private Dealer dealer;
private List<Player> players = new ArrayList<>();
private int numberOfPlayers;
public List<Player> createPlayers(){
Scanner scanner = new Scanner(System.in);
System.out.println("Number of players(up to 6)");
numberOfPlayers = scanner.nextInt();
if(numberOfPlayers <= 6) {
int count = 0;
while (count < numberOfPlayers) {
System.out.println("Please enter the names");
String playerName = scanner.next();
players.add(new Player(playerName));
count++;
}
return players;
}else{
System.out.println("More than 6 players are not allowed");
return null;
}
}
public void createDeck(List<Player> players){
System.out.println("Number of Cards (24/36/52)");
Scanner scanner = new Scanner(System.in);
int numberOfCards = scanner.nextInt();
Dealer newDeck = new Dealer(numberOfCards, numberOfPlayers);
newDeck.shuffleDeck();
newDeck.dealShuffledCardsToPlayers(players);
}
}
public class Dealer {
private Deck deck;
private List<Player> players;
private final int NUMBER_OF_CARDS;
public Dealer(int numberOfCards, int numberOfPlayers) {
this.deck = new Deck(numberOfCards);
this.players = new ArrayList<>(numberOfPlayers);
this.NUMBER_OF_CARDS = numberOfCards;
}
public void shuffleDeck(){
Collections.shuffle(deck.getDeck());
}
public void dealShuffledCardsToPlayers(List<Player> players){
for(Player player: players){
for(int i= 0; i<6; i++) {
player.setHand(deck.deal(6));
}
}
}
}
public class Player {
private String name;
private int points;
private List<Card> hand;
public Player(String name) {
this.name = name;
this.points = 0;
this.hand = new ArrayList<>();
}
public List<Card> getHand(){
return hand;
}
public void setHand(List<Card> hand) {
this.hand = hand;
// System.out.println(hand);
}
public void showHand(){
for(int i=0; i<this.hand.size(); i++){
System.out.println(this.hand.get(i));
}
}
}
public class Deck{
private List<Card> deck;
// private static final Random GENERATOR = new Random();
public Deck (int numberOfCards) {
deck = new ArrayList<>(numberOfCards);
int count = 0;
for (final Card.Suit suit : Card.Suit.values()) {
for (final Card.Rank rank : Card.Rank.values()) {
deck.add(new Card(rank, suit));
count++;
}
}
}
public List<Card> getDeck(){
return deck;
}
public List<Card> deal(int size){
List<Card> hand = new ArrayList<>(size);
hand.add(deck.remove(size));
return hand;
}
}
Expected result is to deal 6 shuffled cards to players. Also please share your thoughts about what needs to be improved and what I have done wrong.
Upvotes: 2
Views: 3209
Reputation: 2595
As mentioned in the comments, it's typically good to consolidate your issue into a shorter code example that illustrates the problem. Also the debugger is your friend, set breakpoints and step through to determine if variable values match what you're expecting them to in different points of the application.
The reason you're not seeing the result you want is because of the logic in dealShuffledCardsToPlayers(...)
and the deck.deal(...)
methods.
Let's start with the internals of the deck.deal(int size) method.
public List<Card> deal(int size){
List<Card> hand = new ArrayList<>(size);
hand.add(deck.remove(size));
return hand;
}
Within this method, every time it's called you are creating a new hand ArrayList of the size passed in, but then you are only adding one object to it (the card at index size
of the deck). If you look at the header for List.remove you'll notice that it only returns the element that was removed from the List (in your case 1 card).
Removes the element at the specified position in this list (optional operation). Shifts any subsequent elements to the left (subtracts one from their indices). Returns the element that was removed from the list.
So then within dealer.dealShuffledCardsToPlayers(List<Player> players)
setting each players hand six times within this loop
for(Player player: players){
for(int i= 0; i<6; i++) {
player.setHand(deck.deal(6));
}
}
But each time you're setting it, it's only the one (last) card that you removed from the deck within the deck.deal(...) method which is why you only end up with one card per player.
I think what you inteded was to have the deck.deal(...)
method deal 6 random cards and return the hand dealt, something along these lines:
public List<Card> deal(int size){
List<Card> hand = new ArrayList<>(size);
Random rand = new Random();
for (int dealtCount = 0; dealtCount < size; dealtCount++) {
hand.add(deck.remove(rand.nextInt(deck.size())));
}
return hand;
}
Or you could probably omit the random and just take the first/last 6 cards since you already shuffled (this would be the equivalent of dealing off the top of the deck after shuffling).
Then with that adjustment in place, you can remove the external loop within your dealer.dealShuffledCardsToPlayers(List<Player> players)
so that just becomes:
for(Player player: players){
player.setHand(deck.deal(6));
}
After adding the player name printed above the card printout (for clarity in the debug log) you end up with this when setting 3 random players:
Number of players(up to 6)
3
Please enter the names
George
Please enter the names
Maria
Please enter the names
Joe
Number of Cards (24/36/52)
52
Player: George
FOUR of DIAMONDS
TEN of DIAMONDS
THREE of CLUBS
TWO of CLUBS
NINE of SPADES
EIGHT of SPADES
Player: Maria
TWO of DIAMONDS
KING of CLUBS
FOUR of SPADES
FIVE of HEARTS
JACK of SPADES
SEVEN of DIAMONDS
Player: Joe
NINE of HEARTS
JACK of HEARTS
FIVE of DIAMONDS
ACE of CLUBS
ACE of SPADES
JACK of CLUBS
One other thing is you most likely want to guard against an incorect combination of players/card count -- i.e. you can't have a 6 player game that deals 6 cards to each players if your card count is only 24.
Edit -- Modified Classes with my examples inserted:
Dealer.java
public class Dealer {
private Deck deck;
private List<Player> players;
private final int NUMBER_OF_CARDS;
public Dealer(int numberOfCards, int numberOfPlayers) {
this.deck = new Deck(numberOfCards);
this.players = new ArrayList<>(numberOfPlayers);
this.NUMBER_OF_CARDS = numberOfCards;
}
public void shuffleDeck(){
Collections.shuffle(deck.getDeck());
}
public void dealShuffledCardsToPlayers(List<Player> players){
// List<Card> tempCard = deck.getDeck();
// for(int i=0; i < players.size(); i++){
// for(int j=0; j < 6; j++){
// players.add(tempCard.remove(i+j*6));
// }
// }
for(Player player: players){
player.setHand(deck.deal(6));
}
}
}
Deck.java
public class Deck{
private List<Card> deck;
// private static final Random GENERATOR = new Random();
public Deck (int numberOfCards) {
deck = new ArrayList<>(numberOfCards);
int count = 0;
for (final Card.Suit suit : Card.Suit.values()) {
for (final Card.Rank rank : Card.Rank.values()) {
deck.add(new Card(rank, suit));
count++;
}
}
}
public List<Card> getDeck(){
return deck;
}
public List<Card> deal(int size){
List<Card> hand = new ArrayList<>(size);
Random rand = new Random();
for (int dealtCount = 0; dealtCount < size; dealtCount++) {
hand.add(deck.remove(rand.nextInt(deck.size())));
}
return hand;
}
@Override
public String toString(){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < deck.size(); i++){
builder.append(i + " ");
builder.append(deck.get(i));
builder.append(System.getProperty("line.separator"));
}
return builder.toString();
}
}
Upvotes: 2