I'm writing the card game "war". my classes:
Main DeckOfCards
and Card
:
import java.util.*;
public class DeckOfCards
{
private ArrayList<Card> deck;
private static final Random randomNumbers=new Random();
public DeckOfCards()
{
deck=new ArrayList<Card>();
}
public DeckOfCards(int cardsFaces) //normal deck has 4 faces
{
deck=new ArrayList<Card>();
for (int i=0;i<cardsFaces;i++)
for (int j=2;j<=14;j++)
{
deck.add(new Card(j));
}
}
public void shuffle()
{
for(int first=0;first<deck.size();first++)
{
int second =randomNumbers.nextInt(deck.size()-1);
Card temp=deck.get(first);
deck.set(first, deck.get(second));
deck.set(second, temp);
}
}
public Card dealCard()
{
if (deck.isEmpty())
{
System.out.println("trying to deal from empty deck");
return null;
}
else
return deck.remove(0);
}
public ArrayList<Card> getDeck()
{
return deck;
}
public String toString()
{
String s="";
for (int i=0;i<deck.size();i++)
{
s=s+deck.get(i)+" ";
}
return s;
}
public boolean isEmpty()
{
return (deck.isEmpty());
}
public void addCard(Card c)
{
deck.add(c);
}
public int size()
{
return deck.size();
}
}
public class Card
{
private int value;//2-14 , 14 is ace.
public Card(int value)
{
this.value=value;
}
public int getValue()
{
return value;
}
public String toString()
{
return Integer.toString(value);
}
}
public class Main
{
public static void main(String[] args)
{
DeckOfCards gameDeck =new DeckOfCards(1);
gameDeck.shuffle();
DeckOfCards p1Deck=new DeckOfCards();//player 1 deck
DeckOfCards p2Deck=new DeckOfCards(); //player 2 deck
DeckOfCards sideDeck=new DeckOfCards();
Card p1Card;
Card p2Card;
boolean gameOver=false;
while(!gameDeck.isEmpty()) //dealing cards to players
{
p1Deck.addCard(gameDeck.dealCard());
p2Deck.addCard(gameDeck.dealCard());
}
while(gameOver==false)
{
p1Card=p1Deck.dealCard();
p2Card=p2Deck.dealCard();
System.out.println("p1card="+p1Card.getValue()+" p2card="+p2Card.getValue());
if(p1Card.getValue()>p2Card.getValue()) //player 1 won the cards
{
p1Deck.addCard(p1Card);
p1Deck.addCard(p2Card);
while(!sideDeck.isEmpty())
p1Deck.addCard(sideDeck.dealCard());
System.out.println("player 1 won the cards,deck sizes: p1:"+p1Deck.size()+" p2:"+p2Deck.size());
}
if(p2Card.getValue()>p1Card.getValue()) //player 2 won the cards
{
p2Deck.addCard(p1Card);
p2Deck.addCard(p2Card);
while(!sideDeck.isEmpty())
p2Deck.addCard(sideDeck.dealCard());
System.out.println("player 2 won the cards,deck sizes: p1:"+p1Deck.size()+" p2:"+p2Deck.size());
}
while(p1Card.getValue()==p2Card.getValue()) //war
{
System.out.println("war");
sideDeck.addCard(p1Card);
sideDeck.addCard(p2Card);
if(p1Deck.size()>3 && p2Deck.size()>3)
{
for(int i=0;i<2;i++)
{
sideDeck.addCard(p1Deck.dealCard());
sideDeck.addCard(p2Deck.dealCard());
}
}
else
{
winner(p1Deck,p2Deck,true);
}
}
if(winner(p1Deck,p2Deck,false))
gameOver=true;
}
}
public static boolean winner(DeckOfCards p1Deck,DeckOfCards p2Deck,boolean war)
{
if(p1Deck.isEmpty()|| p1Deck.isEmpty())
{
if(p1Deck.isEmpty())
System.out.println("player 2 is the winner");
else
System.out.println("player 1 is the winner");
return true;
}
if (p1Deck.size()<3 && p2Deck.size()<3 && war==true)
{
System.out.println("it's a tie");
return true;
}
return false;
}
}
I get NullPointerException
and don't know why. when I press on the exception it refers me to the row:
System.out.println("p1card="+p1Card.getValue()+" p2card="+p2Card.getValue());
when tried to debug I understood that sometimes for some reason my dealCard
function returns null
although the deck I try to deal from isn't empty.
2 outputs for example:
output 1:
trying to deal from empty deck
p1card=10 p2card=5
player 1 won the cards,deck sizes: p1:8 p2:6
p1card=13 p2card=14
player 2 won the cards,deck sizes: p1:7 p2:7
p1card=11 p2card=2
player 1 won the cards,deck sizes: p1:8 p2:6
p1card=9 p2card=12
player 2 won the cards,deck sizes: p1:7 p2:7
p1card=6 p2card=7
player 2 won the cards,deck sizes: p1:6 p2:8
p1card=4 p2card=8
player 2 won the cards,deck sizes: p1:5 p2:9
Exception in thread "main" java.lang.NullPointerException
at mmn11q2.Main.main(Main.java:25)
output 2:
trying to deal from empty deck
p1card=8 p2card=10
player 2 won the cards,deck sizes: p1:6 p2:8
p1card=7 p2card=13
player 2 won the cards,deck sizes: p1:5 p2:9
p1card=6 p2card=4
player 1 won the cards,deck sizes: p1:6 p2:8
p1card=12 p2card=11
player 1 won the cards,deck sizes: p1:7 p2:7
p1card=5 p2card=3
player 1 won the cards,deck sizes: p1:8 p2:6
p1card=2 p2card=14
player 2 won the cards,deck sizes: p1:7 p2:7
Exception in thread "main" java.lang.NullPointerException
at mmn11q2.Main.main(Main.java:25)
The game starts with an invalid state in decks, as shown by "trying to deal from empty deck" in the output at very start.
while(!gameDeck.isEmpty()) //dealing cards to players
{
p1Deck.addCard(gameDeck.dealCard());
p2Deck.addCard(gameDeck.dealCard());
}
Checks if the deck has a card, but attempts to deal two - as the source deck has an odd number of cards, it results in p2Deck having a card entry of None. As soon as this entry is accessed (as the last item in that deck, you get the exception.
An useful generic solution to preventing such problems would be to try proper testing.
For example, have a test for the 'shuffle' method that shuffles a deck repeatedly and then checks if the deck suddenly doesn't contain a Null value as one of the items.
Also, defensive programming helps - each function should verify if the inputs are valid, to prevent bugs in other places to cause invalid state in that class. If your addCard method would check if the argument is a valid card (instead of None), then the bug would be obviously visible.
Have a check within the dealCard function that verifies if it isn't accidentally dealing a Null value from the array - that's another possible source of the error.
"Do not repeat yourself" is a useful mantra. For example, your code has multiple places like "p1Deck.addCard(gameDeck.dealCard());", and each such place has a separate check if the source deck isn't empty as otherwise would be an error and return a null value. It is a sign that maybe you need a method that tries to pass a card between two decks and simply doesn't change them if one becomes empty.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments