I am making a simple card game and I'm trying to use my file paths to .jpg files for card images. I am getting a NullPointerException, but I am new to Java and struggling to understand what exactly this means and what to look for.
This is my output:
Tie.
error in nextCard
Computer wins!
error in nextCard
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at War.getPlayerCard(War.java:160)
    at WarGUI$PlayCardListener.actionPerformed(WarGUI.java:98)
I have traced it thus far:
War class:
public String getPlayerCard()
{
   return playerWarCard.getFilepath();  // Error
}
called from WarGUI:
playerCard = new ImageIcon(game.getPlayerCard()); // Error
I have a feeling the problem is my getFilepath method in my Card class (marked at the bottom), but I'm unsure and so would appreciate if someone could confirm.
Card Class:
public class Card 
{      
   // Suits
   private int suit;                           
   public final static int SPADES = 1;
   public final static int HEARTS = 2;
   public final static int DIAMONDS = 3;
   public final static int CLUBS = 4;
   // Ranks
   private int rank; 
   public final static int JACK = 11;       
   public final static int QUEEN = 12;       
   public final static int KING = 13;
   public final static int ACE = 14; 
   String cardFilepath;                             
   /**
    The constructor initializes the card's rank and suit.
    @param rank
    @param suit
   */
   public Card(int rank, int suit) 
   {
      this.rank = rank;
      this.suit = suit;     
      cardFilepath = "cardpics/" + suit + rank + ".jpg";
   }
   /**
    The other constructor initializes the card's rank and suit.
    @param otherCard to be copied
   */ 
   public Card(Card otherCard) 
   {
      this.rank = otherCard.rank;
      this.suit = otherCard.suit;
   }
   /**
    The getRank method returns the int that represents the card's rank.
    @return card's rank
   */
   public int getSuit() 
   {
      return suit;
   }
   /**
    The getRank method returns the int that represents the card's rank.
    @return card's rank
   */
   public int getRank() 
   {
      return rank;
   }
   /**
   * Returns a description of this card.
   * @return the name of the card.
   */
    public String toString() 
    {
        return getRankAsString() + " of " + getSuitAsString();
    }
   /**
    The equals method compares the rank of the card to the rank of
    another card. If they are the same, the method returns true.
    @return boolean
   */
   public boolean equals(Card otherCard ) 
   {
      return rank == otherCard.rank;
   }
   /**
    The getSuitString method returns the card's suit as a string.
    @return suitString
   */
   public String getSuitAsString() 
   {
      switch (suit)
      {
         case SPADES:   return "Spades";
         case HEARTS:   return "Hearts";
         case DIAMONDS: return "Diamonds";
         case CLUBS:    return "Clubs";
         default:       return "Invalid";
      }
   }
   /**
    The getRankString method returns the card's rank.
    @return rank
   */
   public String getRankAsString() 
   {
      switch (rank) 
      {
         case 2:    return "2";
         case 3:    return "3";
         case 4:    return "4";
         case 5:    return "5";
         case 6:    return "6";
         case 7:    return "7";
         case 8:    return "8";
         case 9:    return "9";
         case 10:   return "10";
         case 11:   return "Jack";
         case 12:   return "Queen";
         case 13:   return "King";
         case 14:   return "Ace";
         default:   return "??";
      }
   }
   /**
    Returns the .jpg image of card
    @return path to image
   */
   public String getFilepath()     // Error?
   {
       return cardFilepath;
   }
}
Attached for reference is my War class:
import java.util.ArrayList;
import javax.swing.*;
public class War
{
   static Cardpile warPile;
   static Cardpile player1 = new Cardpile();
   static Cardpile player2 = new Cardpile();
   static Card unseenPlayerCard;
   static Card unseenComputerCard;
   static Card playerWarCard;
   static Card computerWarCard;
   static String war = "false";
   /**
    Constructor prepares, shuffles deck then deals to players.
   */
   public void War() 
   {
      Deck deck = new Deck();
      deck.shuffle();
      while(deck.getSize() > 0)
      {
         player1.collectCard(deck.deal());
         player2.collectCard(deck.deal());
      }
   }
   /**
    The compareCards method compares rank of card to determine winner
    @param playersCard, computersCard
    @return outcome
   */
   public static int compareCards(Card playersCard, Card computersCard)
   {
       if (playersCard.getRank() > computersCard.getRank())
            {
              player1.collectCard(playersCard);
              player1.collectCard(computersCard);
              System.out.println("Player's card: " + playersCard.toString() + "\nComputer's card: " + 
                                 computersCard.toString() + "\nYou win!");
              return 1;
            }
            else if (playersCard.getRank() < computersCard.getRank())
            {
              player2.collectCard(playersCard);
              player2.collectCard(computersCard);
              System.out.println("Your card: " + playersCard.toString() + "\nComputer's card: " + 
                                 computersCard.toString() + "\nYou lose.");
              return 2;
            }
            // If cards are equal, war
            else
            {
                war = "true";
                System.out.println("Your card: " + playersCard.toString());
                System.out.println("Computer's card: " + computersCard.toString());
                JOptionPane.showMessageDialog(null, "War!");
                beginWar(playersCard, computersCard);
                return 3;
            }
   }
   /**
    The beginWar method draws war cards, then compares to determine
    the winner of the war.
    @param playersCard, computersCard
   */
   public static void beginWar(Card playersCard, Card computersCard)
   {     
       // Prize cards 
       unseenPlayerCard = player1.playCard();
       unseenComputerCard = player2.playCard();
       // Add cards to winning pile
       warPile.collectCard(playersCard);
       warPile.collectCard(computersCard);
       warPile.collectCard(unseenPlayerCard);
       warPile.collectCard(unseenComputerCard);
       // Determine winner
       playerWarCard = player1.playCard();
       computerWarCard = player2.playCard();
       int outcome = compareCards(playerWarCard, computerWarCard);
       if (outcome == '1')
       {
           System.out.println("You win the war!");
       }
       if (outcome == '2')
       {
           System.out.println("You lose the war.");
       }
   }
   /**
    The computerCardsLeft method returns the number of cards in
    the computer's hand.
    @return computer hand size
   */
   public int computerCardsLeft()
   {
       return player2.getSize();
   }
   /**
    The playerCardsLeft method returns the number of cards in
    the players's hand.
    @return player hand size
   */
   public int playerCardsLeft()
   {
       return player1.getSize();
   }
   /**
    The getComputerCard method returns the image path of
    the computer's card for the GUI.
    @return filepath
   */
   public String getComputerCard()
   {
       return computerWarCard.getFilepath();
   }
   /**
    The getPlayerCard method returns the image path of
    the computer's card for the GUI.
    @return filepath
   */
   public String getPlayerCard() 
   {
       return playerWarCard.getFilepath();       // Error
   }
   /**
    The playerDraw method draws the next card in the player's pile.
    @return card
   */
   public Card playerDraw()
   {
       if (player1.getSize() < 1)  
       {
          endGame();
       }
       return player1.nextCard(); 
   }
   /**
    The computerDraw method draws the next card in the computer's pile.
   */
   public Card computerDraw()
   {   
       if (player2.getSize() < 1)
       {
          endGame();
       }
       return player2.playCard();
   }
   /**
    The endGame method displays the results.
   */
   public void endGame()
   {
        if (player1.getSize() > player2.getSize())
              System.out.println("Player wins!");
        else if (player2.getSize() > player1.getSize())
              System.out.println("Computer wins!");
        else
              System.out.println("Tie.");
   }
   /**
    The enoughCards method determins whether or not a player meets a minimum
    card requirement.
   */
   public static boolean enoughCards(int n)
   {
      if (player1.getSize() < n || player2.getSize() < n)
      {
         return false;
      }   
      return true;
   }  
}
...and my WarGUI
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class WarGUI extends JFrame
{  
   private WarGUI guiGame;    
   private War game;                                                                         
   private JPanel rightPlayerPanel;           // Player                   
   private JPanel leftPlayerPanel;            // Computer
   private JPanel buttonPanel;                // Holds buttons                  
   private JPanel gamePanel;                  // Main deck area
   private JButton playButton;       
   private static JLabel backLabelLeft;                       
   private static JLabel playerCardLabel;                          
   private static JLabel computerCardLabel; 
   private ImageIcon back;                    // Icon for backside of card
   private ImageIcon blank;                   // Place holder
   private static ImageIcon playerCard;              // Player 1's current card
   private static ImageIcon computerCard;            // Player 2's current card
   private JTextField playerCardsLeft;
   private JTextField computerCardsLeft;
//    static Hand player1;
//    static Hand player2;
   private Card playersCard;
   Card computersCard;
   private String war = "false";  
   String imagePath = "cardPics/back.jpg";                              
   /**
    This constructor builds & adds panels to contentpane.
   */
   public WarGUI()
   {
      // Set contentPane
      setLayout(new BorderLayout());
      setTitle("Game of War");
      setSize(1100, 550);
      setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      setLocationRelativeTo(null);
      // Build & add deck panel
      assembleGamePanel();
      add(gamePanel, BorderLayout.CENTER);      
      // Build & add player panels
      assembleDecksPanel();
      add(leftPlayerPanel, BorderLayout.WEST);
      add(rightPlayerPanel, BorderLayout.EAST);
      // Build & add button panel
      assembleButtonPanel();
      add(buttonPanel, BorderLayout.SOUTH);
      setVisible(true);
      // Prepare deck & Player hands
      game = new War();  
      // //Welcome message
//        JOptionPane.showMessageDialog(null, "Welcome!");
   }
   /**
    The PlayCardListener tracks clicks on Play Card button. Cards are drawn, war status is checked, scores and images are adjusted.
   */
   private class PlayCardListener implements ActionListener
   {
      public void actionPerformed(ActionEvent e)
      {
         // Regular gameplay
         if (war.equals("false"))
         {
            Card playersCard = game.playerDraw();    
            Card computersCard = game.computerDraw(); 
            // Update card images
            playerCard = new ImageIcon(game.getPlayerCard());    // Error
            playerCardLabel.setIcon(playerCard);
            computerCard = new ImageIcon(computersCard.getFilepath());
            computerCardLabel.setIcon(computerCard);
            // Compare
            game.compareCards(playersCard, computersCard);
                        // // Otherwise, update score 
//             //if (!war.equals("true"))
//             else
//             {
//                 // playerCardsLeft.setText("Player's Cards: " + (player1.getSize() - 1));
// //                 computerCardsLeft.setText("Computer's Cards: " + (player2.getSize() - 1));
// 
//             }
            playerCardsLeft.setText("Player's Cards: " + (game.playerCardsLeft() - 1));
            computerCardsLeft.setText("Computer's Cards: " + (game.computerCardsLeft() - 1));
          }
         // War deckplay
         // Second click - face down card
         else if (war.equals("true"))
         {
            // Set icons to card backside
            playerCardLabel.setIcon(back);
            computerCardLabel.setIcon(back);
            war = "last";
         }   
         // Third click
         else if (war.equals("last"))
         {
            // Identify cards involved in the war, update icons
            computerCard = new ImageIcon(game.getComputerCard());
            computerCardLabel.setIcon(computerCard);
            playerCard = new ImageIcon(game.getPlayerCard());
            playerCardLabel.setIcon(playerCard);
            war = "final";
         }
         // War final
         else if (war.equals("final"))
         {
            war = "false";
            // Update scores
            playerCardsLeft.setText("Player's Cards: " + (game.playerCardsLeft()));
            computerCardsLeft.setText("Computer's Cards: " + (game.computerCardsLeft()));
         }
         else
            System.out.println("ERROR");
      }
   }
   /**
    The assembleGamePanel builds the cardPanel - the main deck area, where cards are displayed.
   */
   private void assembleGamePanel()
   {
      // Place holder for cards
      blank = new ImageIcon();
      playerCardLabel = new JLabel(blank);
      computerCardLabel = new JLabel(blank);
      // Add labels to cardPanel 
      gamePanel = new JPanel();
      gamePanel.add(playerCardLabel);
      gamePanel.add(computerCardLabel);
      gamePanel.setPreferredSize(new Dimension(545, 540));
      gamePanel.setBackground(new Color(0, 64, 0));
   }
   /**
    The assembleDecksPanel method builds the panel that displays the players' cardpiles.
   */
   private void assembleDecksPanel()
   {
      // Icons of card backside
      back = new ImageIcon(imagePath);
      // Add icons
      backLabelLeft = new JLabel();
      backLabelLeft.setIcon(back);
      JLabel backLabelRight = new JLabel();
      backLabelRight.setIcon(back);
      // Add labels to panels
      // Right
      rightPlayerPanel = new JPanel();
      rightPlayerPanel.setPreferredSize(new Dimension(150,220));
      rightPlayerPanel.add(backLabelRight);
      rightPlayerPanel.setBackground(new Color(0, 64, 0));
      playerCardsLeft = new JTextField("Player's Cards: 26", 13);
      playerCardsLeft.setEditable(false);
      rightPlayerPanel.add(playerCardsLeft);
      // Left 
      leftPlayerPanel = new JPanel();
      leftPlayerPanel.setPreferredSize(new Dimension(150,220));
      leftPlayerPanel.add(backLabelLeft);
      leftPlayerPanel.setBackground(new Color(0, 64, 0));
      computerCardsLeft = new JTextField("Computer's Cards: 26", 13); 
      computerCardsLeft.setEditable(false);
      leftPlayerPanel.add(computerCardsLeft);
   }
   /**
    The assembleButtonPanel method adds buttons to button panel.
   */
   private void assembleButtonPanel()
   {
      // Create & add button
      JButton playCardButton = new JButton("Play!");
      playCardButton.setPreferredSize(new Dimension(150,80));
      buttonPanel = new JPanel();
      buttonPanel.add(playCardButton);
      buttonPanel.setBackground(new Color(0, 64, 0));
      // Add event listeners for the buttons.
      playCardButton.addActionListener(new PlayCardListener());
   }     
   /**
    The main method begins the GUI deck.
   */
   public static void main(String[] args) 
   {
       WarGUI guiGame = new WarGUI();
   } 
}
Edit: I now understand there is a problem somewhere else. as such, I will post my other classes...
Cardpile
public class Cardpile
{
   // Create an array to hold the player's pile, and parameters for that array. 
   private Card[] cardPile;
   private int front;
   private int end;
   /**
    Constructor creates an empty pile capable of holding 52 cards.
   */
   public Cardpile()
   {
      cardPile = new Card[52];
      front = 0; 
      end = 0;
   }
   /**
    The nextCard method returns the card at the front of the pile.
    @return c
   */
   public Card nextCard()
   {
      if (front == end)
      {
         System.out.println("error in nextCard");
      }
      Card c = cardPile[front];
      front++;
      return c;   
   }
   /**
    The collectCard method adds a card to the pile.
   */
   public void collectCard(Card c) 
   {
      cardPile[end] = c;
      end++;
   }
   public Card playCard()
   {
      return nextCard();
   }
   /**
    The getSize method returns the size of the pile.
    @return size
   */
   public int getSize()
   {
      int size = end - front;
      return size;
   }
   /**
    The clear method clears the pile of all cards.
   */
   public void clear()
   {
      front = 0;
      end = 0;
   }
}
Deck:
import java.util.*;
public class Deck
{
   private Card[] deck;
   private int numCards;
   /**
    The constructor creates a deck of 52 cards
   */
   public Deck()
   {
      deck = new Card[52];
      fillDeck();
   }
   /**
    The fillDeck method fills the deck with cards.
   */
   public void fillDeck()
   {
      int index = 0;
      for (int q = 1; q <= 13; q++)
      {
         for (int n = 1; n <= 4; n++)
         {
            deck[index] = new Card(q, n);
            index++;
         }
      }
   }
   /**
    The shuffle method shuffles the deck.
   */
   public void shuffle()
   {
      for (int sh = 0; sh < numCards - 1; sh++)
      {
         int r = myRandom(sh, numCards - 1);
         Card shuffleCard = deck[sh];
         deck[sh] = deck[r];
         deck[r] = shuffleCard;
      }
   }
   /**
    The deal method deals to the players.
    @return updated deck
   */
   public Card deal()
   {
      if(numCards == 0)
      {
         return null;
      }
      numCards--;        
      return deck[numCards];     
   }
   /**
    The getSize method returns the size of the deck
    @return numCards in deck
   */
   public int getSize()
   {
      return numCards;
   }
   /**
    The myRandom method returns a random number.
    @return random number
   */
   private static int myRandom(int low, int high)
   {
      int random = (int)((high + 1 - low) * Math.random() + low);
      return random;
   }
}
 
     
    