QuestionQuestion

Transcribed TextTranscribed Text

Introduction You will be writing the backend logic for a simple version of a video game sometimes known as "Bejeweled". You'll get lots of practice working with arrays, 2D arrays, and ArrayLists. Once you have your code working, you'll be able to integrate it with a GUI that we have provided to create a complete application. Your task will specifically be to implement the three classes Game, JewelFactory, and Util. These classes go in package hw3, and you should not modify anything outside this package (except possibly to edit ui.GameMain). There is a skeleton of the Util class given. The game is played on a grid of colored squares or icons that we will call "jewels". The objective is to amass points by making runs, where a run is defined as 3 or more adjacent, matching icons in a row or column. You can click and drag from an icon to an adjacent icon (horizontal or vertical) to try to exchange them. This is called selecting the pair. If exchanging the two icons creates one or more runs, the selection succeeds and the icons are exchanged; otherwise nothing happens. When a selection succeeds, all icons that are part of a run disappear. Then each column shifts down, that is, any icons that are above the empty cells move down (as if by gravity) into the empty spaces, and new ones fill the empty cells (that are left at of the top of the column). Note that because the new cells are randomly generated, runs may be formed as a result of the new cells being added to the grid. Again, all cells that are part of a run disappear, the columns shift down, empty cells are filled, and this process iterates until the grid contains no runs. Points are added to the score for each run that is formed. Detailed specification Carefully read the javadoc for details about the precise behavior of methods. The sample code includes a partial implementation of the class Util located in the hw3 package. A few methods are already implemented to help get you started. You'll also need to be familiar with the two (very simple) classes in the api package: a Jewel encapsulates a single integer, representing a color or type of icon, and a GridPosition encapsulates a Jewel along with a row and column, and is used to represent the contents of one position in the game grid. There is also a package ui containing code for a sample GUI, discussed later. There are also some usage examples later in this document in the "Getting started" section. Overview of the Util class As its name implies, Util is a "utility" class, meaning that it is just a collection of static methods performing various useful functions. The key algorithms for the game are isolated in this class in order to make them easier to develop and test independently as one-dimensional array operations independent of the game itself. These are a) the algorithm for finding runs and b) the algorithm for shifting non-null cells to the end of an array. You are required to implement these two algorithms in the Util class and not duplicate the code in the Game class. (The Game class includes methods for copying a row or column into a one-dimensional array and back again, so it will be easy to use the Util methods to operate on a row or column of the game grid.) There are also three methods in Util that are already implemented, one for creating an array of Jewel objects from a string; one for a 2D array of Jewel objects from an array of strings; and one for converting a 2D array of Jewel objects to a printable string. This is intended to make your life easier when writing test cases for your code. Overview of the JewelFactory class The purpose of a JewelFactory makes Jewel objects. (Duh.) The key method is generate(), which returns a randomly generated new Jewel whose type (that is, its int value) is within a specified range. The range of values is determined at construction. You'll need to implement the constructors and the generate method (which are easy) pretty early on, since generate is required in the Game class to implement shiftColumnDown and fillAll. In addition, the JewelFactory class specifies a method createGrid. This is harder, but is not needed for implementing the rest of the project except for the Game constructor that takes a width and height. In this constructor, only the width and height of the grid are given, and the jewels are randomly generated by the createGrid method. (The other constructor, that takes a string, is not dependent on the createGrid method.) The challenge is that the initial grid should not include any runs. For example, if you are iterating across the rows and generating a value for the cell at (row, col), and if you find that the two cells to the left both have some value v1 and the two cells above both have some value v2, then for (row, col) you need to generate a random value from the set of numbers between 0 and the max, excluding v1 and v2. Overview of the Game class This class encapsulates all the game state, primarily consisting of • a 2D array of Jewel objects, • an instance of JewelFactory, and • a score. (Tip: you should only need three instance variables!) From the high-level perspective of a client using the Game class (such as a user interface) the four most fundamental operations are the following: boolean select(GridPosition c0, GridPosition c1) attempts to exchange a pair of cells ArrayList<GridPosition> findAndMarkAllRuns() finds all runs, sets all cells to null that are part of a run, and updates the score ArrayList<GridPosition> shiftColumnDown(int col) shifts the Jewels in non-null cells down to fill null cells below ArrayList<GridPosition> fillAll() assigns new Jewels to the null cells Normally, these operations would normally be invoked in the order above, and the last three steps would be called repeatedly by the client until findAndMarkAllRuns does not find any runs (returns an empty list). However, the methods should work as specified even if invoked in a different order. (Exception: methods that find runs, including the first two operations above, are not expected to work if the grid contains any null cells.) Notice that several of the methods have a return value of type ArrayList<GridPosition>. This is a list of cells of the grid that are affected in some way by the method, and the purpose of the list is to enable a user interface to display what is happening in the game. See the Javadoc for details about these lists. The game also includes basic accessors such as getWidth(), getHeight(), getJewel(int row, int col), and getScore() that would be needed by any user interface to display the game. In addition to the four principal methods above, there are some methods that are specified to help decompose the overall implementation into simpler parts that can be tested more easily. These methods could have been made private, since they are not expected to be called by clients, but we have made them public here to simplify testing. These include the following methods. Jewel[] getRow(int row) returns a copy of the specified row of the grid Jewel[] getCol(int col) returns a copy of the specified column of the grid void setRow(int row, Jewel[] arr) copies the given array values into the specified row of the grid void setRow(int row, Jewel[] arr) copies the given array values into the specified row of the grid These methods make it easy to use the two methods of the Util class, which take a onedimensional array, to operate on an individual row or column in the game grid. The problem of finding runs is decomposed into two simpler methods, both of which should be implemented using the Util method findRuns: ArrayList<GridPosition> findHorizontalRuns(int row) finds all runs in the given row ArrayList<GridPosition> findVerticalRuns(int col) finds all runs in the given column These two methods are accessors and do not modify the grid nor the score. Obviously, these can be used to implement findAndMarkAllRuns. (Note: to accumulate all GridPositions into a final list to be returned, you might want to take advantage of the ArrayList method addAll.) In addition, the two methods above are also useful to implement select. Note that if any runs are created by exchanging two cells, one of the runs must include at least one of two cells. Therefore one strategy for select is: swap the jewels in the two cells look for runs in the row and column for each of the two cells if there are any runs, return true otherwise swap back and return false Importing the sample code The sample code includes the hw3, api, and ui packages. It is distributed as a complete Eclipse project that you can import. The code will not compile until you have created the Game and JewelFactory classes and stubbed in most of the methods. Basic instructions: 1. Download the zip file to a location outside your workspace. You don’t need to unzip it. 2. In Eclipse, go to File -> Import -> General -> Existing Projects into Workspace, click Next. 3. Click the radio button for “Select archive file”. 4. Browse to the zip file you downloaded and click Finish. Alternate procedure: If you have an older version of Java (below 8) or if for some reason you have problems with this process, or if the project does not build correctly, you can construct the project manually as follows: 1. Download the zip file to a location outside your workspace. 2. In Windows File Explorer right-click on the zip file and select Extract (Note: in OS X you can just double-click it to extract) 3. Create a new empty project in Eclipse 4. Browse to the src directory of the zip file contents 5. In the Package Explorer, navigate to the src folder of the new project. 6. Drag the hw3, ui, and api folders from Explorer/Finder into the src folder in Eclipse. The GUI The sample code includes a GUI in the ui package. The main method is in ui.GameMain. You select a pair of icons to swap by clicking dragging the mouse from one to the other. It won't work until you have started implementing the Game class; see the Getting Started section for more details The GUI is built on the Java Swing libraries. This code is complex and specialized, and is somewhat outside the scope of the course. You are not expected to be able to read and understand it, though you might be interested in exploring how it works. It's important to realize that the GUI contains no actual logic or data for the game. At all times, it simply displays the contents of your grid. It invokes the select method based on user mouse action. It invokes the findAndMarkAllRuns method if you return true from select. It then calls shiftColumnDown for each column, and finally calls fillAll. The latter three are called repeatedly until findAndMarkAllRuns returns an empty list. If the return values you provide from shiftColumnDown and fillAll are correct, the GUI will attempt to animate the "falling" motion of the icons. So if something's not working, go back to your Game class and write some more unit tests! All that the main class GameMain does is to initialize the components and start up the UI machinery. The class GamePanel contains most of the UI code and defines the "main" panel, and there is also a much simpler class ScorePanel that contains the display of the score. You can configure the game by editing the create() method of GameMain; see the comments there for examples. You can also edit the default colors here. (Optional reading) If you are curious about what’s going on, you might start by looking at the method paintComponent in GamePanel, where you can see the accessor methods such as getJewel being called to decide how to "draw" the panel. The most interesting part of any graphical UI is in the callback methods. These are the methods invoked when an event occurs, such as the user pressing a button or a timer firing. You could take a look at MyMouseListener.mousePressed and MyMouseMotionListener.mouseReleased in which you can see the call to your select method. (These are “inner classes” of GamePanel, a concept we have not seen yet, but it means they can access the GamePanel's instance variables.) If you are interested in learning more, there is a collection of simple Swing examples linked on Steve’s website. See http://www.cs.iastate.edu/~smkautz/ and look under “Other Stuff”. The absolute best comprehensive reference on Swing is the official tutorial from Oracle, http://docs.oracle.com/javase/tutorial/uiswing/TOC.html . A large proportion of other Swing tutorials found online are out-of-date and often wrong. Testing and the SpecChecker As always, you should try to work incrementally and write simple tests for your code as you develop it. Do not rely on the GUI code for testing! Trying to test your code using a GUI is very slow, unreliable, and generally frustrating. In particular, when we grade your work we are NOT going to run the GUI, we are going to verify that each method works according to its specification. Since test code that you write is not a required part of this assignment and does not need to be turned in, you are welcome to post your test code on Piazza for others to check, use and discuss. We will provide a basic SpecChecker, but it will not perform any functional tests of your code. At this point in the course, you are expected to be able to read the specfications, ask questions when things require clarification, and write your own unit tests. There are extensive examples in the "Getting started" section. The SpecChecker will verify the class names and packages, the public method names and return types, and the types of the parameters. If your class structure conforms to the spec, you should see a message similar to this in the console output: x out of x tests pass. This SpecChecker will also offer to create a zip file for you that will package up the two required classes. Remember that your instance variables should always be declared private, and if you want to add any additional “helper” methods that are not specified, they must be declared private as well. Style and documentation Special note: in this project you are writing some potentially complex loops that someone is going to have to read. You are expected to write helpful internal comments for your code so that the reader can follow what you are trying to do. Internal comments are written //-style, not Javadoc-style, and are used inside of method bodies to explain how something works (while the Javadoc comments explain what a method does). If you had to think for a few minutes to figure out how to implement something, then add a comment to explain your strategy to the reader. Internal comments always precede the code they describe, and are indented to the same level.

Solution PreviewSolution Preview

These solutions may offer step-by-step problem-solving explanations or good writing examples that include modern styles of formatting and construction of bibliographies out of text citations and references. Students may use these solutions for personal skill-building and practice. Unethical use is strictly forbidden.

import java.util.ArrayList;

import api.GridPosition;
import api.Jewel;

public class Game {

private Jewel[][] grid;
private JewelFactory generator;
private int score;

public Game(int width, int height, JewelFactory generator) {
this.grid = generator.createGrid(width, height);
this.generator = generator;
this.score = 0;
}

public Game (String[] descriptor, JewelFactory generator) {
this.grid = Util.createFromStringArray(descriptor);
this.generator = generator;
this.score = 0;
}

public Jewel getJewel(int row, int col) {
return grid[row][col];
}

public void setJewel(int row, int col, Jewel jewel) {
grid[row][col] = jewel...

By purchasing this solution you'll be able to access the following files:
Solution.PNG and Solution.zip.

$100.00
for this solution

PayPal, G Pay, ApplePay, Amazon Pay, and all major credit cards accepted.

Find A Tutor

View available Java Programming Tutors

Get College Homework Help.

Are you sure you don't want to upload any files?

Fast tutor response requires as much info as possible.

Decision:
Upload a file
Continue without uploading

SUBMIT YOUR HOMEWORK
We couldn't find that subject.
Please select the best match from the list below.

We'll send you an email right away. If it's not in your inbox, check your spam folder.

  • 1
  • 2
  • 3
Live Chats