Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Need a solution. Overview We\'re moving back in time, from the 1990\'s and Tetri

ID: 3731499 • Letter: N

Question

Need a solution.

Overview

We're moving back in time, from the 1990's and Tetris, to the 1890's and the game of Dots and Boxes (Links to an external site.)Links to an external site.. This still-popular pencil-and-paper game can be found everywhere, from paper placemats and kids' menus in restaurants, to dozens of variants available for mobile and online play.

Objectives

Once again you must develop an implementation of an interface. Your implementation will need to keep track of all aspects of this game. There is no user interface, as we are building the underlying game engine. As in other projects, you'll be provided a few additional classes to assist with your implementation. The focus here is on somewhat advanced uses of collections, as well as on exception management. You have a lot of freedom here to design and develop your code in any way you see fit, so your guidance will be somewhat more limited than in the past projects.

Requirements

The interface is called edu.vt.cs5044.DotsAndBoxes and your implementation must be called edu.vt.cs5044.DABGame. You must of course create a test class as well, called edu.vt.cs5044.DABGameTest and achieve full code coverage. You are expected (and required) develop at least one additional helper class in the same package, with any reasonable name, in order to reduce the overall complexity of your implementation.

Downloads

dab5044.jar - library file containing the compiled utility classes and interface
dab5044-api.jar - library file containing the Javadocs for the utility classes and interface

Getting Started

Start a new project in Eclipse, then import the files above exactly as you did with the files for the Tetris project. You'll need to use a lot of what you learned in that assignment to complete this assignment. Be sure to thoroughly review the API details for all the provided classes. Everything you need to know is in the API. There is no user interface of any kind, nor any other way to run your implementation beyond your own test class, so a test-driven development strategy will be important to follow.

Explanation / Answer

DABGameTest.java

package edu.vt.cs5044;

import static org.junit.Assert.*;
import java.util.TreeMap;
import org.junit.Before;
import org.junit.Test;

@SuppressWarnings("javadoc")
public class DABGameTest
{

    // Initialize local DABGame variable
    private DotsAndBoxes game;

    // Initialize and declare local variable for coordinates
    private Coordinate   coord1 = new Coordinate(0, 0);
    private Coordinate   coord2 = new Coordinate(1, 0);
    private Coordinate   coord3 = new Coordinate(0, 1);
    private Coordinate   coord4 = new Coordinate(1, 1);

    // Initialize and declare local variable for default direction
    private Direction    dir    = Direction.EAST;


    // Create new DABGame
    @Before
    public void setUp()
        throws Exception
    {
        game = new DABGame();
    }

    /*
     * Ensure game exception is thrown if a new grid has not been initialized for every method
     */
    @Test
    public void testPreInit()
    {
        try
        {
            game.drawEdge(coord1, dir);
            fail("drawEdge needs a Game Exception");
        }
        catch (GameException ge)
        {
            // PASS
        }

        try
        {
            game.getCurrentPlayer();
            fail("getCurrentPlayer needs a Game Exception");
        }
        catch (GameException ge)
        {
            // PASS
        }

        try
        {
            game.getDrawnEdgesAt(coord1);
            fail("getDrawnEdgesAt needs a Game Exception");
        }
        catch (GameException ge)
        {
            // PASS
        }

        try
        {
            game.getOwnerAt(coord1);
            fail("getOwnerAt needs a Game Exception");
        }
        catch (GameException ge)
        {
            // PASS
        }

        try
        {
            game.getScores();
            fail("getScores needs a Game Exception");
        }
        catch (GameException ge)
        {
            // PASS
        }

        try
        {
            game.getSize();
            fail("getSize needs a Game Exception");
        }
        catch (GameException ge)
        {
            // PASS
        }

    }


    /*
     * Test init method to ensure GameException is thrown if parameter is less than 2
     */
    @Test(expected = GameException.class)
    public void testInvalidInit()
    {
        game.init(1);
    }

    /*
     * Test getSize method after a grid has been initialized
     */
    @Test
    public void testGetSizeAfterInit()
    {
        game.init(2);       // SETUP

        assertTrue(game.getSize() == 2);
    }


    /*
     * Test getCurrentPlayer method after a grid has been initialized
     */
    @Test
    public void testGetCurrentPlayerAfterInit()
    {
        testGetSizeAfterInit();     // SETUP

        assertEquals(Player.ONE, game.getCurrentPlayer());
    }

    /*
     * Test drawEdge method after grid has been initialized
     */
    @Test
    public void testDrawEdgeAfterInit()
    {
        testGetSizeAfterInit();                     // SETUP

        assertTrue(game.drawEdge(coord1, dir));

    }

    /*
     * Test getDrawnEdges method on box
     */
    @Test
    public void testGetDrawnEdgesOnBoxThatContainsEdge()
    {
        testDrawEdgeAfterInit();                    // SETUP

        assertTrue(game.getDrawnEdgesAt(coord1).contains(Direction.EAST));
    }

    /*
     * Test drawEdge method on a box that already contains the edge
     */
    @Test
    public void testDrawEdgeOnBoxThatContainsEdge()
    {
        testDrawEdgeAfterInit();                    // SETUP

        assertFalse(game.drawEdge(coord1, dir));
    }

    /*
     * Test getOwnerAt method after grid has been initialized
     */
    @Test
    public void testGetOwnerAtAfterInit()
    {
        testGetSizeAfterInit();                     // SETUP

        assertTrue(game.getOwnerAt(coord1) == null);
    }


    /*
     * Test directionNotNull to ensure if null parameter is entered for direction a GameException
     * is thrown
     */
    @Test
    public void testDirectionNotNullWithNullDirection()
    {
        Direction nullDir = null;
        testGetSizeAfterInit();                     // SETUP

        try
        {
            game.drawEdge(coord1, nullDir);
            fail();
        }
        catch (GameException ge)
        {
            // PASS
        }

    }

    /*
     * Test the getOwner method after a box has been owned
     */
    @Test
    public void testGetOwnerAfterBoxIsOwned()
    {
        testGetSizeAfterInit();                     // SETUP

        game.drawEdge(coord1, Direction.EAST);      // P1
        game.drawEdge(coord1, Direction.SOUTH);     // P2
        game.drawEdge(coord1, Direction.WEST);      // P1
        game.drawEdge(coord1, Direction.NORTH);     // P2

        assertEquals(Player.TWO, game.getOwnerAt(coord1));

    }

    /*
     * Test getScores method after a box is owned for player 2
     */
    @Test
    public void testGetScoresAfterABoxIsOwnedP2()
    {
        testGetOwnerAfterBoxIsOwned();                // SETUP

        TreeMap<Player, Integer> scores = (TreeMap<Player, Integer>)game.getScores(); // Local var

        assertTrue(scores.get(Player.TWO) == 1);

    }

    /*
     * Test getScores method after a box is owned for player 1
     */
    @Test
    public void testGetScoresAfterABoxIsOwnerP1()
    {
        testGetSizeAfterInit();

        game.drawEdge(coord1, Direction.NORTH);
        game.drawEdge(coord1, Direction.EAST);
        game.drawEdge(coord1, Direction.SOUTH);
        game.drawEdge(coord4, Direction.SOUTH);
        game.drawEdge(coord1, Direction.WEST);

        TreeMap<Player, Integer> scores = (TreeMap<Player, Integer>)game.getScores();

        assertTrue(scores.get(Player.ONE) == 1);
    }

    /*
     * Test if player is null after a game is completed
     */
    @Test
    public void testPlayerNullAfterGameOver()
    {
        testGetSizeAfterInit();                     // SETUP

        game.drawEdge(coord1, Direction.EAST);      // P1
        game.drawEdge(coord1, Direction.SOUTH);     // P2
        game.drawEdge(coord1, Direction.WEST);      // P1
        game.drawEdge(coord1, Direction.NORTH);     // P2

        game.drawEdge(coord2, Direction.EAST);      // P2
        game.drawEdge(coord2, Direction.SOUTH);     // P2
        game.drawEdge(coord2, Direction.WEST);      // P1
        game.drawEdge(coord2, Direction.NORTH);     // P2

        game.drawEdge(coord3, Direction.EAST);      // P1
        game.drawEdge(coord3, Direction.SOUTH);     // P2
        game.drawEdge(coord3, Direction.WEST);      // P1
        game.drawEdge(coord3, Direction.NORTH);     // P2

        game.drawEdge(coord4, Direction.EAST);      // P1
        game.drawEdge(coord4, Direction.SOUTH);     // P2
        game.drawEdge(coord4, Direction.WEST);      // P1
        game.drawEdge(coord4, Direction.NORTH);     // P2

        assertTrue(game.getCurrentPlayer() == null);
    }

    /*
     * Test drawEdge method that completess an adjacent box
     */
    @Test
    public void testDrawEdgeThatCompletesAdjBox()
    {
        testGetSizeAfterInit();             // SETUP

        game.drawEdge(coord1, Direction.SOUTH);     // P1
        game.drawEdge(coord1, Direction.WEST);      // P2
        game.drawEdge(coord1, Direction.NORTH);     // P1
        game.drawEdge(coord2, Direction.WEST);      // P2

        assertEquals(Player.TWO, game.getOwnerAt(coord1));
    }

    /*
     * Test that a game exception is thrown if there is no adjacent box for a given edge of a box
     */
    @Test
    public void testGameExceptionAdjNotValid()
    {
        try
        {
            game.drawEdge(coord1, Direction.NORTH);
            fail("Must throw game exception");
        }
        catch (GameException ge)
        {
            // PASS
        }
    }

}


DABGame.java

package edu.vt.cs5044;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;

public class DABGame
    implements DotsAndBoxes
{
    private Player                   currentPlayer;
    private int                      gridSize;
    private HashMap<Coordinate, Box> boxGrid;


    @Override
    public boolean drawEdge(Coordinate coord, Direction dir)
    {
        // Local boolean variables used to determine if player has additional move(s)
        boolean boxOwned = false;
        boolean adjOwned = false;

        // Local box variable representing the box at coord parameter
        Box selectedBox = findBox(coord);

        // Determine if a grid has been initialized, if not game exception is thrown
        checkInit();

        // Determine if dir parameter is null, if it is game exception is thrown
        checkDirectionNotNull(dir);

        // If box selected at coordinates already has dir edge drawn, drawEdge method returns false
        if (selectedBox.hasEdge(dir))
        {
            return false;
        }

        // If box selected does not have dir edge already drawn then draw edge
        selectedBox.drawEdge(dir, currentPlayer);

        // If the box has been completed it will have an owner equivalent to the current player, and
        // the boxOwnded local boolean variable will be set to true
        boxOwned = checkBoxOwner(selectedBox);

        try
        {
            // Find the adjacent box and set it to local variable, if it exists. If not game
            // exception is thrown
            Box adjacentBox = findBox(coord.getNeighbor(dir));

            //Declare and initialize new direction variable for opposite direction
            Direction adjDir = dir.getOpposite();
          
            // Draw the edge on the adjacent box
            adjacentBox.drawEdge(adjDir, currentPlayer);

            // If the box has been completed it will have an owner equivalent to the current player,
            // and the boxOwnded local boolean variable will be set to true
            adjOwned = checkBoxOwner(adjacentBox);

        }
        // Catch game exception to be handled if thrown
        catch (GameException ge)
        {
            //Game exception caught
        }

        // If the boxOwned boolean variable has not been set to true it indicates that no boxes
        // have been completed and it is the opponents turn
        if (!boxOwned && !adjOwned)
        {
            currentPlayer = currentPlayer.getOpponent();
        }

        // Determine if game is over
        checkGameOver();

        // Return true if the method has been successfully completed
        return true;

    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Player getCurrentPlayer()
    {
        // Determine if a grid has been initialized, if not game exception is thrown
        checkInit();

        // Return the value of the currentPlayer field
        return currentPlayer;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public HashSet<Direction> getDrawnEdgesAt(Coordinate coord)
    {
        // Determine if a grid has been initialized, if not game exception is thrown
        checkInit();

        // Select the box at the given coord, if the coord aren't on the board a game exception is
        // thrown
        Box selectedBox = findBox(coord);

        // Return a HashSet of the edges already drawn for a box at given coordinates
        return selectedBox.getDrawnEdges();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Player getOwnerAt(Coordinate coord)
    {
        // Determine if a grid has been initialized, if not game exception is thrown
        checkInit();

        // Select the box at the given coord, if the coord aren't on the board a game exception is
        // thrown
        Box selectedBox = findBox(coord);

        // Return the owner of the selected box. Value will be if no player owns box
        return selectedBox.getOwner();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public TreeMap<Player, Integer> getScores()
    {
        // Determine if a grid has been initialized, if not game exception is thrown
        checkInit();

        // Instantiate a new TreeMap
        TreeMap<Player, Integer> scores = new TreeMap<>();

        // Local variables to hold the score of either player while method iterates through grid
        int playerOneScore = 0;
        int playerTwoScore = 0;

        // Iterate through grid and count the number of boxes owned by either player
        for (int x = 0; x < gridSize; x++)
        {
            for (int y = 0; y < gridSize; y++)
            {
                Coordinate currentCoord = new Coordinate(x, y);
                Box currentBox = findBox(currentCoord);
                Player boxOwner = currentBox.getOwner();

                if (Player.ONE.equals(boxOwner))
                {
                    playerOneScore++;
                }

                if (Player.TWO.equals(boxOwner))
                {
                    playerTwoScore++;
                }

            }

        }

        // Add key value pairs for player and their score to the scores TreeMap
        scores.put(Player.ONE, playerOneScore);
        scores.put(Player.TWO, playerTwoScore);

        // Return the scores TreeMap
        return scores;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public int getSize()
    {
        // Determine if a grid has been initialized, if not game exception is thrown
        checkInit();

        // Return the integer value of the gridSize field
        return gridSize;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void init(int size)
    {
        // If the size parameter is less than 2 throw a game exception
        if (size < 2)
        {
            throw new GameException("Grid size must be at least two.");
        }

        // Set the gridSize field to the value of the size parameter
        gridSize = size;

        // Set currentPlayer field to Player.ONE
        currentPlayer = Player.ONE;

        // Create TreeMap for boxGrid with (coordinates, boxes) as key value pair
        boxGrid = new HashMap<>();
        for (int x = 0; x < size; x++)
        {
            for (int y = 0; y < size; y++)
            {
                boxGrid.put(new Coordinate(x, y), new Box());
            }
        }

    }


    /**
     * Create a new DABGame object.
     */
    public DABGame()
    {
        currentPlayer = null;
        gridSize = -1;
    }


    /**
     * Helper method to determine if new game has been initialized
     */
    private void checkInit()
    {
        // If the gridSize still equals -1 it indicates a grid has not yet been initialized and
        // throws a game exception
        if (gridSize == -1)
        {
            throw new GameException("Can't get size; not initialized");
        }
    }


    /**
     * Helper method to find a specific box when given a coordinates, if the given coordinates are
     * outside the bounds of the game, a game exception will be thrown.
     *
     * @param coord
     *            is the coordinate where the box is located
     */
    private Box findBox(Coordinate coord)
    {
        // The x and y values of the coordinate parameter
        int xVal = coord.getX();
        int yVal = coord.getY();

        // If one or more of the values of the coordinates do not exist on the grid, throw a new
        // game exception
        if (xVal < 0 || yVal < 0 || xVal >= gridSize || yVal >= gridSize)
        {
            throw new GameException("That box doesn't exist; please select different coordinates.");
        }

        // If coordinates are valid, return the box object at the coordinates
        Box selectedBox = boxGrid.get(coord);
        return selectedBox;
    }


    /**
     * Helper method to determine if direction is not null. Will throw a game exception if player
     * attempts to give "null" direction
     *
     * @param dir
     *            the direction to be tested
     */
    private void checkDirectionNotNull(Direction dir)
    {
        // If direction is null throw a new game exception
        if (dir == null)
        {
            throw new GameException("Can't use direction null; please select another direction.");
        }
    }


    /**
     * Helper method to determine if a box has all four edges drawn
     */
    private boolean checkBoxOwner(Box currentBox)
    {
        // If the current box owner is null return false; otherwise return true
        return currentBox.getOwner() != null;

    }


    /**
     * Helper method to determine if game is over
     */
    private void checkGameOver()
    {
        // Local variable that will hold the value of player one and player two scores combined
        int currentScoresTotal = 0;

        // Local integer variable that is the total boxes available to be owned on a given grid
        int totalAvailableBoxes = (int)Math.pow(gridSize, 2);

        // TreeMap of the players current scores
        TreeMap<Player, Integer> scores = getScores();

        // Create key set for scores map
        Set<Player> keys = scores.keySet();

        // Iterate through keyset and add the key values to the currentScoresTotal variable
        for (Player key : keys)
        {
            currentScoresTotal += scores.get(key);
        }

        // If currentScoresTotal is equal to the totalAvailableBoxes variable it indicates that all
        // boxes have been drawn and the game is over. CurrentPlayer will be set to null.
        if (currentScoresTotal == totalAvailableBoxes)
        {
            currentPlayer = null;
        }

    }
}

Box.java


import java.util.HashSet;

public class Box
{
    private Player             owner;
    private HashSet<Direction> drawnEdges = new HashSet<>();


    /**
     * Get the current value of owner.
     *
     * @return The value of owner for this object.
     */
    public Player getOwner()
    {
        return owner;
    }


    /**
     * Get the current value of drawnEdges.
     *
     * @return The value of drawnEdges for this object.
     */
    public HashSet<Direction> getDrawnEdges()
    {
        HashSet<Direction> copyOfDrawnEdges = new HashSet<>(drawnEdges);
        return copyOfDrawnEdges;
    }


    /**
     * Determine whether the drawnEdges collection of a box contains a direction
     *
     * @param dir
     *            the direction the method will test to determine if it already exists in the
     *            drawnEdges collection
     * @return return true if the drawnEdges collection contains direction; false otherwise
     */
    public boolean hasEdge(Direction dir)
    {
        return drawnEdges.contains(dir);
    }


    /**
     * Add a direction to the drawn edges collection
     *
     * @param dir
     *            the direction to be added to the drawnEdges collection
     * @param player
     *            the current player and the owner of the box if the drawnEdges collection size is
     *            equal to four
     */
    public void drawEdge(Direction dir, Player player)
    {
        drawnEdges.add(dir);

        if (drawnEdges.size() == 4)
        {
            owner = player;
        }
    }

}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote