Connect 4 Game

时间:2015-05-12 02:55:58

标签: java nullpointerexception

此处的所有源文件:

https://drive.google.com/folderview?id=0B6qyughWLLZ1fm5uSzUtOG1vMDRiMVBMZU9GMWIzanpiUmNyMGNVZUE1R1NYdXZzRXQtTms&usp=sharing

我是编程新手,无法弄清楚为什么我会收到此错误。我已经阅读了我能找到的所有线程,似乎没有任何工作。我知道可以通过查看对象并确保创建它来调试Null PointerException,我认为我已经创建了它。请告诉我你的看法。

该错误说明了它在这一行。 在leftToRight方法内... winsColAvailable和winnerSlotAvailable

代码:

import java.util.Random;

public class MyAgent extends Agent
{
Random r;

/**
 * Constructs a new agent, giving it the game and telling it whether it is    Red or Yellow.
 * 
 * @param game The game the agent will be playing.
 * @param iAmRed True if the agent is Red, False if the agent is Yellow.
 */
 public MyAgent(Connect4Game game, boolean iAmRed)
 {
    super(game, iAmRed);
    r = new Random();
 }

 /**
 * The move method is run every time it is this agent's turn in the game. You may assume that
 * when move() is called, the game has at least one open slot for a token, and the game has not
 * already been won.
 * 
 * By the end of the move method, the agent should have placed one token into the game at some
 * point.
 * 
 * After the move() method is called, the game engine will check to make sure the move was
 * valid. A move might be invalid if:
 * - No token was place into the game.
 * - More than one token was placed into the game.
 * - A previous token was removed from the game.
 * - The color of a previous token was changed.
 * - There are empty spaces below where the token was placed.
 * 
 * If an invalid move is made, the game engine will announce it and the game will be ended.
 * 
 */
 public void move()
 {
    // check if middle column is occupied
    // Check and see if I have a winning move
    int ifICanWin = iCanWin(iAmRed, myGame);
    int ifTheyCanWin = theyCanWin(iAmRed, myGame);    
    if (ifICanWin >= 0) 
    {
        moveOnColumn(ifICanWin);
    }// Check and see if opponent has a winning move
    else if (ifTheyCanWin >=0) 
    {
        moveOnColumn(ifTheyCanWin);
    } else 
    {

        // Add a disk to all columns -->Shows board potentially after this move
        // Duplicate the current game board
        Connect4Game duplicateOfGame = new Connect4Game(myGame);
        for (int col = 0; col < duplicateOfGame.getColumnCount(); ++col)
        {
            int lowestEmptySlotIndex = getLowestEmptyIndex(duplicateOfGame.getColumn(col));   // Find the top empty slot in the column
                                                                                              // If the column is full, lowestEmptySlot will be -1
            if (lowestEmptySlotIndex > -1)  // if the column is not full
            {
                 Connect4Slot lowestEmptySlot = duplicateOfGame.getColumn(col).getSlot(lowestEmptySlotIndex);  // get the slot in this column at this index
                 if (iAmRed) // If the current agent is the Red player...
                 {
                     lowestEmptySlot.addRed(); // Place a red token into the empty slot
                 }
                 else // If the current agent is the Yellow player (not the Red player)...
                 {
                     lowestEmptySlot.addYellow(); // Place a yellow token into the empty slot
                 }
            }
        }
        ifICanWin = iCanWin(iAmRed, duplicateOfGame); // Checks if I can win on the board showing all my possible moves
        if (ifICanWin >= 0)
        {
            moveOnColumn(ifICanWin);
        }
        // other players disk to all columns --> Shows board two moves from current state
        for (int col = 0; col < duplicateOfGame.getColumnCount(); ++col)
        {
            int lowestEmptySlotIndex = getLowestEmptyIndex(duplicateOfGame.getColumn(col));   // Find the top empty slot in the column
                                                                                              // If the column is full, lowestEmptySlot will be -1
            if (lowestEmptySlotIndex > -1)  // if the column is not full
            {
                 Connect4Slot lowestEmptySlot = duplicateOfGame.getColumn(col).getSlot(lowestEmptySlotIndex);  // get the slot in this column at this index
                 if (iAmRed) // If the current agent is the Red player...add other token
                 {
                     lowestEmptySlot.addYellow(); // Place a red token into the empty slot
                 }
                 else // If the current agent is the Yellow player (not the Red player)...
                 {
                     lowestEmptySlot.addRed(); // Place a yellow token into the empty slot
                 }
            }
        }
        ifTheyCanWin = theyCanWin(iAmRed, duplicateOfGame); // Checks if they can win on the board showing all their possible moves
        if (ifTheyCanWin >= 0)
        {
            moveOnColumn(ifTheyCanWin);
        }
        if (ifTheyCanWin == -1 && ifICanWin == -1)
        {
            moveOnColumn(randomMove());
        }
    }
 }
/**
 * Drops a token into a particular column so that it will fall to the bottom of the column.
 * If the column is already full, nothing will change.
 * 
 * @param columnNumber The column into which to drop the token.
 */
public void moveOnColumn(int columnNumber)
{
    int lowestEmptySlotIndex = getLowestEmptyIndex(myGame.getColumn(columnNumber));   // Find the top empty slot in the column
                                                                                              // If the column is full, lowestEmptySlot will be -1
    if (lowestEmptySlotIndex > -1)  // if the column is not full
    {
        Connect4Slot lowestEmptySlot = myGame.getColumn(columnNumber).getSlot(lowestEmptySlotIndex);  // get the slot in this column at this index
        if (iAmRed) // If the current agent is the Red player...
        {
            lowestEmptySlot.addRed(); // Place a red token into the empty slot
        }
        else // If the current agent is the Yellow player (not the Red player)...
        {
            lowestEmptySlot.addYellow(); // Place a yellow token into the empty slot
        }
    }
}

/**
 * Returns the index of the top empty slot in a particular column.
 * 
 * @param column The column to check.
 * @return the index of the top empty slot in a particular column; -1 if the column is already full.
 */
public int getLowestEmptyIndex(Connect4Column column) {
    int lowestEmptySlot = -1;
    for  (int i = 0; i < column.getRowCount(); i++)
    {
        if (!column.getSlot(i).getIsFilled())
        {
            lowestEmptySlot = i;
        }
    }
    return lowestEmptySlot;
}

/**
 * Returns a random valid move. If your agent doesn't know what to do, making a random move
 * can allow the game to go on anyway.
 * 
 * @return a random valid move.
 */
public int randomMove()
{
    int i = r.nextInt(myGame.getColumnCount());
    while (getLowestEmptyIndex(myGame.getColumn(i)) == -1)
    {
        i = r.nextInt(myGame.getColumnCount());
    }
    return i;
}

/**
 * Returns the column that would allow the agent to win.
 * 
 * You might want your agent to check to see if it has a winning move available to it so that
 * it can go ahead and make that move. Implement this method to return what column would
 * allow the agent to win.
 *
 * @return the column that would allow the agent to win.
 */
public int iCanWin(boolean isRed, Connect4Game aGame) 
{

    // Horizontal R --> L
    int leftToRight = canWinLeftToRight(isRed, aGame);

    // Horizontal L --> R
    int rightToLeft = canWinRightToLeft(isRed, aGame);

    // Vertical
    int verticaWin = canWinVertically(isRed, aGame);

    // Diagonal Up-->R
    int upToRight = canWinDiagonalRight(isRed, aGame);

    // Diagonal Up-->L
    int upToLeft = canWinDiagonalLeft(isRed, aGame);

    if (leftToRight > 0) {return leftToRight;}
    else if (rightToLeft > 0) {return rightToLeft;}
    else if(verticaWin > 0) {return verticaWin;}
    else if (upToRight > 0) {return upToRight;}
    else if (upToLeft > 0) {return upToLeft;}
    else return -1;
}

/**
 * Returns the column that would allow the opponent to win.
 * 
 * Implement this method to return what column should
 * be blocked to prevent the opponent from winning.
 *
 * @return the column that would allow the opponent to win.
 */
 public int theyCanWin(boolean isRed, Connect4Game aGame) 
 {
     boolean oppColor = !isRed;
     // Horizontal R --> L
     int leftToRight = canWinLeftToRight(oppColor, aGame);

     // Horizontal L --> R
     int rightToLeft = canWinRightToLeft(oppColor, aGame);

     // Vertical
     int verticaWin = canWinVertically(oppColor, aGame);

     // Diagonal Up-->R
     int upToRight = canWinDiagonalRight(oppColor, aGame);

     // Diagonal Up-->L
     int upToLeft = canWinDiagonalLeft(oppColor, aGame);
    if (leftToRight > 0) {return leftToRight;}
    else if (rightToLeft > 0) {return rightToLeft;}
    else if(verticaWin > 0) {return verticaWin;}
    else if (upToRight > 0) {return upToRight;}
    else if (upToLeft > 0) {return upToLeft;}
    else return -1;
}

/**
 * Returns the name of this agent.
 *
 * @return the agent's name
 */
public String getName()
{
    String name = "The Cyber King";
    return name;
}

/**
 * Returns a column number if player can play a winning move on a row Left to Right, or a -1 if no winning move available for that player.
 * 
 * @param currentGame is the game board used to determing if a player has a winning move.
 * @param checkedColor is the color to be assessed.
 * @return the winning column number or a -1
 */
private int canWinLeftToRight(boolean checkedColor, Connect4Game currentGame) 
{
    for(int row=0; row < 6; ++row )
    {
        int counter = 0;
        for (int col=0; col < 7; ++col) {
            Connect4Column  currCol = new Connect4Column(myGame.getColumn(col));
            Connect4Slot currSlot = new Connect4Slot(currCol.getSlot(row));
            boolean currSlotIsFilled = currSlot.getIsFilled();
            if (currSlotIsFilled) { // if not null
                if (currSlot.getIsRed() == checkedColor) {
                    ++counter;
                } 
                else {
                    counter = 0;
                }
            }
            else{
                counter = 0;
            }
            Connect4Column winningColAvailable = currentGame.getColumn(col+1);
            Connect4Slot winningSlotAvailable = winningColAvailable.getSlot(row);
            if (counter == 3 && (col+1)<7 && !winningSlotAvailable.getIsFilled()) {
                return col+1;
            }
        }
    }
    return -1;
}
/**
 * Returns a column number if player can play a winning move on a row right to Left, or a -1 if no winning move available for that player.
 * 
 * @param currentGame is the game board used to determing if a player has a winning move.
 * @param checkedColor is the color to be assessed.
 * @return the winning column number or a -1
 */
private int canWinRightToLeft(boolean checkedColor, Connect4Game currentGame) 
{
    for(int row=0; row < currentGame.getRowCount(); ++row )
    {
        int counter = 0;
        for (int col=currentGame.getColumnCount()-1; col >=0 ; --col) {
            Connect4Column  currCol = currentGame.getColumn(col);
            Connect4Slot currSlot = currCol.getSlot(row);
            boolean currSlotIsFilled = currSlot.getIsFilled();
            if (currSlotIsFilled) { // if not null
                if (currSlot.getIsRed() == checkedColor) {
                    ++counter;
                } 
                else {
                    counter = 0;
                }
            }
            else{
                counter = 0;
            }
            Connect4Column winningColAvailable = currentGame.getColumn(col-1);
            Connect4Slot winningSlotAvailable = winningColAvailable.getSlot(row);
            if (counter == 3 && (col-1) >= 0 && !winningSlotAvailable.getIsFilled()) {
                return col-1;
            }
        }
    }
    return -1;
}
/**
 * Returns a column number if player can play a winning move it, or a -1 if no winning move available for that player.
 * 
 * @param currentGame is the game board used to determing if a player has a winning move.
 * @param checkedColor is the color to be assessed.
 * @return the winning column number or a -1
 */
private int canWinVertically(boolean checkedColor, Connect4Game currentGame)
{
    for (int col = 0; col < currentGame.getColumnCount(); ++col) {
        int counter = 0;
        for (int slot = 0; slot < currentGame.getRowCount(); slot++) {
            Connect4Column  currCol = currentGame.getColumn(col);
            Connect4Slot currSlot = currCol.getSlot(slot);
            boolean currSlotIsFilled = currSlot.getIsFilled();
            if (currSlotIsFilled) { // if not null
                if (currSlot.getIsRed() == checkedColor) {
                    ++counter;
                    System.out.println("Col: " + col + " Slot: "+ slot +" being checked, and is player, so ++counter. Counter is now " + counter);
                } else {
                    counter = 0;
                    System.out.println("Col: " + col + " Slot: "+ slot +" being checked, and is not player, so counter = 0. Counter is now " + counter);
                }
            } else {
                counter = 0;
                System.out.println("Col: " + col + " Slot: "+ slot +" being checked, and is null so counter = 0. Counter is now " + counter);
            }
            Connect4Slot winningSlot = currCol.getSlot(slot+1);
            if (counter == 3 && (slot+1) < 6 && !winningSlot.getIsFilled()) {
                return col;
            }
        }
    }
    return -1;
}
/**
 * Returns a column number if player can play a winning move three columns over and three slots up to the Right.
 * 
 * @param currentGame is the game board used to determing if a player has a winning move.
 * @param checkedColor is the color to be assessed.
 * @return the winning column number or a -1
 */
private int canWinDiagonalRight(boolean checkedColor, Connect4Game currentGame)
{
    for (int col = 0; col < 4; ++col) 
    {
        for (int slot = 0; slot < 3; slot++) 
        {
            System.out.println("Col: " + col + " Slot: "+ slot +" being checked for a diagonal win for player.");
            // Slot 1
            Connect4Column  col1 = currentGame.getColumn(col);
            Connect4Slot slot1 = col1.getSlot(slot);
            boolean slot1IsFilled = slot1.getIsFilled();
            // Slot 2
            Connect4Column  col2 = currentGame.getColumn(col+1);
            Connect4Slot slot2 = col2.getSlot(slot+1);
            boolean slot2IsFilled = slot2.getIsFilled();
            // slot 3
            Connect4Column  col3 = currentGame.getColumn(col+2);
            Connect4Slot slot3 = col3.getSlot(slot+2);
            boolean slot3IsFilled = slot3.getIsFilled();
            // Slot 4
            Connect4Column  winningCol = currentGame.getColumn(col+3);
            Connect4Slot winningSlot = winningCol.getSlot(slot+3);
            boolean winningSlotIsFilled = winningSlot.getIsFilled();
            if (slot1IsFilled &&
                slot1.getIsRed() == checkedColor &&
                slot2IsFilled &&
                slot2.getIsRed() == checkedColor &&
                slot3IsFilled &&
                slot3.getIsRed() == checkedColor &&
                !winningSlotIsFilled) 
            {
                return col+3;
            } 
        }
    }
    return -1;
}
/**
 * Returns a column number if player can play a winning move three columns over and three slots up to the Left.
 * 
 * @param currentGame is the game board used to determing if a player has a winning move.
 * @param checkedColor is the color to be assessed.
 * @return the winning column number or a -1
 */
private int canWinDiagonalLeft(boolean checkedColor, Connect4Game currentGame)
{
    for (int col = 6; col > 2; --col) 
    {
        for (int slot = 0; slot < 3; slot++) 
        {
            System.out.println("Col: " + col + " Slot: "+ slot +" being checked for a diagonal win for player.");
                // Slot 1
            Connect4Column  col1 = currentGame.getColumn(col);
            Connect4Slot slot1 = col1.getSlot(slot);
            boolean slot1IsFilled = slot1.getIsFilled();
            // Slot 2
            Connect4Column  col2 = currentGame.getColumn(col-1);
            Connect4Slot slot2 = col2.getSlot(slot+1);
            boolean slot2IsFilled = slot2.getIsFilled();
            // slot 3
            Connect4Column  col3 = currentGame.getColumn(col-2);
            Connect4Slot slot3 = col3.getSlot(slot+2);
            boolean slot3IsFilled = slot3.getIsFilled();
            // Slot 4
            Connect4Column  winningCol = currentGame.getColumn(col-3);
            Connect4Slot winningSlot = winningCol.getSlot(slot+3);
            boolean winningSlotIsFilled = winningSlot.getIsFilled();
            if (slot1IsFilled &&
                slot1.getIsRed() == checkedColor &&
                slot2IsFilled &&
                slot2.getIsRed() == checkedColor &&
                slot3IsFilled &&
                slot3.getIsRed() == checkedColor &&
                !winningSlotIsFilled) 
            {
                return col+3;
            } 
        }
    }
    return -1;
}
}

记录:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at MyAgent.canWinLeftToRight(MyAgent.java:273)
    at MyAgent.iCanWin(MyAgent.java:179)
    at MyAgent.move(MyAgent.java:42)
    at Connect4Frame.nextMove(Connect4Frame.java:119)
    at Connect4Frame.nextMoveButtonPressed(Connect4Frame.java:234)
    at Connect4Frame$2.actionPerformed(Connect4Frame.java:58)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6525)

0 个答案:

没有答案