Question
I just need some java classes implemented for a MagicTetris game. The specifications and sample code are down below. Here is the code that we
I just need some java classes implemented for a MagicTetris game. The specifications and sample code are down below.
Here is the code that we were supplied, for the most part, they shouldnt be modified unless you need to.
AbstractGame Class
package api;
import java.util.List;
/** * A partial implementation of the Game interface for * Tetris-like falling block games. Subclasses must implement * the determinePositionsToCollapse() and determineScore() methods. */ public abstract class AbstractGame implements Game { /** * Width of the game grid. */ private final int width;
/** * Height of the game grid. */ private final int height;
/** * The shape that is subject to motion during the step() method * or via invocations of the shiftXXX() or rotate() methods. */ private Shape current;
/** * A grid whose positions may be occupied by the blocks * the current falling shape or blocks that can no longer * be moved. Unoccupied cells are null. */ private Block[][] grid;
/** * Status of the game after each invocation of step(), as described * in the GameStatus documentation. */ private GameStatus gameStatus;
/** * Generator for new shapes. (The BasicGenerator implementation * will uniformly select one of the six shape types). */ private Generator generator;
/** * State variable indicating which blocks are to be deleted when the * status is COLLAPSING. The implementation maintains the invariant that * positionsToCollapse.size() is nonzero if and only if gameStatus is COLLAPSING. */ private List positionsToCollapse;
/** * Constructs a new AbstractBlockGame. */ protected AbstractGame(int givenWidth, int givenHeight, Generator generator) { width = givenWidth; height = givenHeight; grid = new Block[getHeight()][getWidth()]; this.generator = generator; current = generator.getNext(getWidth()); gameStatus = GameStatus.NEW_SHAPE; }
/** * Returns a list of locations for all cells that form part of * a collapsible set. This list may contain duplicates. * @return * list of locations for positions to be collapsed */ protected abstract List determinePositionsToCollapse(); /** * Returns the current score. * @return * the current score */ protected abstract int determineScore();
@Override public Block getBlock(int row, int col) { return grid[row][col]; } /** * Sets a block at the given row and column. * @param row * @param col * @param value */ public void setBlock(int row, int col, Block value) { grid[row][col] = value; } @Override public int getHeight() { return height; }
@Override public Shape getCurrent() { if (gameStatus == GameStatus.COLLAPSING || gameStatus == GameStatus.GAME_OVER) { throw new IllegalStateException(); } return current; }
@Override public int getWidth() { return width; }
@Override public List getPositionsToCollapse() { if (positionsToCollapse.size() == 0) { throw new IllegalStateException(); } return positionsToCollapse; }
@Override public boolean transform() { boolean ret = canTransform(); if (ret) { current.transform(); } return ret; }
@Override public void cycle() { current.cycle(); } @Override public boolean shiftLeft() { boolean ret = canShiftLeft(); if (ret) { current.shiftLeft(); } return ret; }
@Override public boolean shiftRight() { boolean ret = canShiftRight(); if (ret) { current.shiftRight(); } return ret; }
@Override public int getScore() { return determineScore(); }
@Override public boolean gameOver() { return gameStatus == GameStatus.GAME_OVER; }
// // Main game logic - see Game interface documentation // @Override public GameStatus step() { switch (gameStatus) { case GAME_OVER: // do nothing break; case NEW_SHAPE: case FALLING: if (gameStatus == GameStatus.NEW_SHAPE) { gameStatus = GameStatus.FALLING; } if (canShiftDown()) { current.shiftDown(); } else { // Add blocks of the current shape to the grid, maybe // temporarily, in order to check whether it has completed // a collapsible group for (Cell c : current.getCells()) { int x = c.getCol(); int y = c.getRow(); if (y >= 0 && y = 0 && x = 0 && y = 0 && x = 0 && y = 0 && x
/** * Deletes the blocks at the indicated positions and shifts * blocks above them down. Only blocks lying within a column * above a deleted block are shifted down. This method * does not update the game state and should normally be called * only from the step() method. * @param positionsToCollapse * list of positions to collapse, may contain duplicates. */ public void collapsePositions(List positionsToCollapse) { for (int col = 0; col = 0; --row) { if (!marked[row]) { grid[index][col] = grid[row][col]; index -= 1; } } for (int row = index; row >= 0; --row) { grid[row][col] = null; } } /** * Determines whether the current shape can be shifted down. Does not * modify the game state. * @return true if the current shape can be shifted down, false otherwise */ private boolean canShiftDown() { Shape t = (Shape) current.clone(); t.shiftDown(); return !collides(t); }
/** * Determines whether the current shape can be shifted right. Does not * modify the game state. * @return true if the current shape can be shifted right, false otherwise */ private boolean canShiftRight() { Shape t = (Shape) current.clone(); t.shiftRight(); return !collides(t); }
/** * Determines whether the current shape can be shifted left. Does not * modify the game state. * @return true if the current shape can be shifted left, false otherwise */ private boolean canShiftLeft() { Shape t = (Shape) current.clone(); t.shiftLeft(); return !collides(t); }
/** * Determines whether the current shape can be transform. Does not * modify the game state. * @return true if the current shape can be transformed, false otherwise */ private boolean canTransform() { Shape t = (Shape) current.clone(); t.transform(); return !collides(t); }
/** * Determines whether the given shape overlaps * with the occupied cells of the grid, or extends beyond the sides * or bottom of the grid. (A shape in its initial position * MAY extend above the grid.) * * @param t a shape * @return true if the cells of the given shape extend beyond the * sides or bottom of the grid or overlap with any occupied cells of * the grid */ private boolean collides(Shape t) { for (Cell c : t.getCells()) { int x = c.getCol(); int y = c.getRow(); if (x width - 1 || y > height - 1) { return true; }
// row, column if (y >= 0 && grid[y][x] != null) { return true; } } return false; }
}
Generator Class
package api;
/** * Abstraction of a generator for game pieces in a Tetris-like * video game. */ public interface Generator { /** * Returns a new Shape instance according to this generator's * strategy. * @param width * the width the game grid * @return * a new Shape */ Shape getNext(int width); }
BasicPlayLevel Class
Block Class
package api;
import java.awt.Color;
/** * Interface specifying an icon or block in a Tetris-like * game. */ public class Block { /** * The color associated with this block. */ private final Color color; /** * The magic status of this block. */ private final boolean magic; /** * Constructs a Block with the given color that is not magic. * @param c * color to be associated with this block */ public Block(Color c) { this.color = c; magic = false; }
/** * Constructs a Block with the given color and magic state. * @param c * color to be associated with this block * @param magic * true if this block should be in the magic state, false otherwise */ public Block(Color c, boolean magic) { this.color = c; this.magic = magic; } // /** // * Copy constructor. // * @param existingBlock // */ // public Block(Block existingBlock) // { // this.color = existingBlock.color; // this.magic = existingBlock.magic; // } /** * Returns the color associated with this block. * @return * color for this block */ public Color getColorHint() { return color; }
/** * Determines whether this block has the same color and magic * state as the given block. * @param block * given block * @return * true if this block matches the given block */ public boolean matches(Block block) { return (block != null && block.getColorHint() == this.color); } /** * Determines the magic state of this block. * @return * true if this block is magic */ public boolean isMagic() { return magic; } @Override public String toString() { String m = ""; if (magic) { m = "*"; } return getColorString() + m; } @Override public boolean equals(Object obj) { if (obj == null || obj.getClass() != this.getClass()) { return false; } Block other = (Block) obj; return color == other.color && magic == other.magic; }
/** * Returns a string representation of this block's color * @return * string representation of this block's color */ private String getColorString() { if (color == Color.ORANGE) return "ORANGE"; if (color == Color.BLUE) return "BLUE"; if (color == Color.CYAN) return "CYAN"; if (color == Color.YELLOW) return "YELLOW"; if (color == Color.MAGENTA) return "MAGENTA"; if (color == Color.GREEN) return "GREEN"; if (color == Color.RED) return "RED"; return "unknown"; } }
Cell Class
package api;
/** * Container for a block and a position. */ public class Cell { /** * The block represented by this Cell. */ private Block block; /** * The position of this Cell. */ private Position position; /** * Constructs a Cell from the given block and position. * @param b * @param position */ public Cell(Block b, Position position) { this.block = b; this.position = new Position(position); } /** * Copy constructor creates a deep copy of the given Cell. * @param existing * the given Cell */ public Cell(Cell existing) { // Blocks are immutable, no need to copy this.block = existing.block; this.position = new Position(existing.position); } /** * Returns the column for this cell's position. * @return * the column for this cell */ public int getCol() { return position.col(); } /** * Returns the row for this cell's position. * @return * the row for this cell */ public int getRow() { return position.row(); } /** * Sets the column for this cell's position. * @param col * the new column */ public void setCol(int col) { position.setCol(col); } /** * Sets the row for this cell's position. * @param row * the new row */ public void setRow(int row) { position.setRow(row); } /** * Returns the block associated with this Cell. * @return * the block associated with this Cell */ public Block getBlock() { return block; } /** * Sets the block associated with this Cell. * @param b * the new block */ public void setBlock(Block b) { block = b; } @Override public String toString() { String b = ""; if (block == null) { b = "null block"; } else if (block.isMagic()) { b = "*"; } String p = position == null ? "null" : position.toString(); return p + b; } @Override public boolean equals(Object obj) { if (obj == null || obj.getClass() != this.getClass()) { return false; } Cell other = (Cell) obj; return position.equals(other.position) && block.equals(other.block); } }
Game Class
package api;
import java.util.List;
/** * Interface for a Tetris-like game. Implementations of this * interface should maintain all aspects of the game state. The state * consists of a grid of Block objects representing occupied * and unoccupied positions, plus a current Shape whose position is * normally updated by the step() method and can be altered by the * transform(), shiftDown(), shiftLeft(), and shiftRight() methods. * An additional part of the game state is the status that is returned by * each invocation of the step() method. The status values are described * in detail in the GameStatus documentation. */ public interface Game { /** * Transition the game through one discrete step. A step may consist of *
*
shifting the current shape down by one cell *
changing the status to COLLAPSING when when the current shape cannot * be dropped further and completes a collapsible set (e.g., * in a standard Tetris game, a collapsible set would be a * completed horizontal row) *
changing the status to STOPPED when the current shape cannot * be dropped further, but does not complete a collapsible set *
changing the status to NEW_SHAPE when a new shape * is started at the top of the grid *
deleting all cells to be collapsed *
changing the status to GAME_OVER when a new shape collides with * occupied positions in the top row *
* @return the game status after the step */ GameStatus step(); /** * Performs a transform() operation on the current shape if it is * possible to do so without letting it extend beyond the sides or * bottom of the grid and without colliding with occupied cells in the grid. * * @return true if the current shape was moved, false otherwise */ boolean transform(); /** * Performs a cycle() operation on the current shape. */ void cycle(); /** * Shifts the current shape one cell to the left (decreasing the column), * if it is possible to do so without letting it extend beyond the sides or * bottom of the grid and without colliding with occupied cells in the grid. * * @return true if the current shape was moved, false otherwise */ boolean shiftLeft(); /** * Shifts the current shape one cell to the right (increasing the column), * if it is possible to do so without letting it extend beyond the sides or * bottom of the grid and without colliding with occupied cells in the grid. * * @return true if the current shape was moved, false otherwise */ boolean shiftRight(); /** * Returns the block associated with the given row and column, or null if * the location is unoccupied. * @param row * the row of the cell * @param col * the column of the cell * @return the block associated with the given row/column in the grid */ Block getBlock(int row, int col); /** * Returns the current shape. * @return * the current shape. * @throws IllegalStateException if the game status is COLLAPSING or GAME_OVER */ Shape getCurrent(); /** * Returns the width of the grid. * @return * the width of the grid. */ int getWidth(); /** * Returns the height of the grid. * @return * the height of the grid. */ int getHeight(); /** * Returns the grid positions to be collapsed. This method can only be * called when the game state is COLLAPSING. The returned list is in no * particular order and may contain duplicates. (The purpose of this method is * to allow clients to apply special rendering or animation to the * collapsing positions.) * @return * list of Position objects representing the the grid positions to be * collapsed * @throws IllegalStateException if the game status is not COLLAPSING */ List getPositionsToCollapse(); /** * Returns the current score for this game. * @return * the current score for this game */ int getScore(); /** * Determines whether the game is over, which occurs when a new * shape in its initial position collides with occupied cells * of the grid. * @return * true if the game is over, false otherwise */ boolean gameOver(); }
GameStatus Class
package api; /** * Status values for a Tetris-like game. The meaning of each values is * as follows: *
*
NEW_SHAPE *
There is a new current block group at the top of the grid *
FALLING *
The current block group was successfully shifted down one cell. *
STOPPED *
The current block group could not be shifted down, but did * not complete a collapsible set (it still may be possible to move * the polynomial horizontally) *
COLLAPSING *
There is at least one collapsible set, and the next * invocation of step() will collapse them *
GAME_OVER *
A new block group cannot be placed at the top of the grid without * colliding with occupied cells *
*/ public enum GameStatus { NEW_SHAPE, FALLING, STOPPED, COLLAPSING, GAME_OVER }
PlayLevel Class
package api;
/** * An IPlayLevel is an abstraction of various attributes of * a level of difficulty for a Tetris-like video game. */ public interface PlayLevel { /** * Returns the time in milliseconds between frames or * steps of the game. This value may depend on the current * score. * @param currentScore current score for the game * @return time in milliseconds */ int speed(int currentScore); /** * Time in milliseconds between frames or steps of the game * when the dropping of a shape is accelerated. This value * may depend on the current score. * @param currentScore current score for the game * @return time in milliseconds */ int fastDropSpeed(int currentScore); }
Position Class
package api;
/** * Data container for a row and column. */ public class Position { /** * The row. */ private int row; /** * The column. */ private int col; /** * Constructs a Position with the given row and column. * @param givenRow * @param givenCol */ public Position(int givenRow, int givenCol) { row = givenRow; col = givenCol; } /** * Constructs a copy of the given Position. * @param existing * a given Position object */ public Position(Position existing) { row = existing.row; col = existing.col; } /** * Returns the row for this position. * @return * row for this position */ public int row() { return row; } /** * Returns the column for this position. * @return * column * for this position */ public int col() { return col; } /** * Sets the row for this position. * @param newRow * new row value */ public void setRow(int newRow) { row = newRow; } /** * Sets the column for this position. * @param newCol * new column value */ public void setCol(int newCol) { col = newCol; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof api.Position)) { return false; } Position other = (Position) obj; return row == other.row && col == other.col; } @Override public String toString() { return "(" + row + ", " + col + ")"; }
@Override public int hashCode() { int result = 31 + row; result = 31 * result + row; return result; } }
Shape Class
package api;
/** * Interface for shapes used by Tetris-like games. Each shape * has a position and, implicitly, a set of Cells. The initial position and cell * locations are assigned in a constructor, and thereafter the * position can be modified by the shiftXXX() methods. The constructor also * establishes a relative ordering of the cells. The getCells() method always returns the * cells in this ordering, and the cycle() method always uses this ordering. * No bounds checking is ever done in implementations of this interface; * therefore, the position and the cell positions can have negative coordinates. */ public interface Shape extends Cloneable { /** * Returns a new array of Cell objects representing the blocks * in this shape along with their absolute positions. * (Note that modifications to the array or Cell objects returned * by this method should NOT affect this shape.) * @return * the cells occupied by this shape */ Cell[] getCells(); /** * Shifts the position of this shape down (increasing the row) * by one. No bounds checking is done. */ void shiftDown(); /** * Shifts the position of this shape left (decreasing the column) * by one. No bounds checking is done. */ void shiftLeft(); /** * Shifts the position of this shape right (increasing the column) * by one. No bounds checking is done. */ void shiftRight(); /** * Transforms this shape without altering its position * according to the rules of the game to be implemented. * Typical operations are rotation and reflection. * No bounds checking is done. */ void transform(); /** * Cycles the blocks within the cells of this shape. Each * block is shifted forward to the next cell (in the original ordering * of the cells). The last block wraps around to the first cell. */ void cycle(); /** * Returns a deep copy of this object having the correct runtime type. * @return * a deep copy of this object */ Shape clone(); }
GameMain Class
package ui;
import java.awt.Color; import java.awt.Dimension;
import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities;
import api.BasicPlayLevel; import api.Game; import api.PlayLevel; import hw4.MagicTetris;
/** * Main class for a GUI for a Tetris game sets up a * GamePanel instance in a frame. */ public class GameMain { /** * Cell size in pixels. */ public static final int SIZE = 25; /** * Font for displaying score. */ public static final int SCORE_FONT = 24; /** * Grid background color. */ public static final Color BACKGROUND_COLOR = Color.LIGHT_GRAY; /** * Helper method for instantiating the components. This * method should be executed in the context of the Swing * event thread only. */ private static void create() { // EDIT HERE TO CHANGE THE GAME //Game game = new MagicTetris(12, 20); Game game = new examples.SampleGame();
// create the two panels for the game PlayLevel level = new BasicPlayLevel(); ScorePanel scorePanel = new ScorePanel(); GamePanel panel = new GamePanel(game, scorePanel, level); // arrange the two panels JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); mainPanel.add(scorePanel); mainPanel.add(panel); // put main panel in a window JFrame frame = new JFrame("Com S 227 Magic Tetris"); frame.getContentPane().add(mainPanel);
// give panels a nonzero size Dimension d = new Dimension(game.getWidth() * GameMain.SIZE, game.getHeight() * GameMain.SIZE); panel.setPreferredSize(d); d = new Dimension(game.getWidth() * GameMain.SIZE, 3 * GameMain.SIZE); scorePanel.setPreferredSize(d); frame.pack(); // we want to shut down the application if the // "close" button is pressed on the frame frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // be sure key events get to the panel panel.requestFocus(); // rock and roll... frame.setVisible(true); } /** * Entry point. Main thread passed control immediately * to the Swing event thread. * @param args not used */ public static void main(String[] args) { Runnable r = new Runnable() { public void run() { create(); } }; SwingUtilities.invokeLater(r); } }
GamePanel Class
package ui; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.List;
import javax.swing.JPanel; import javax.swing.Timer;
import api.Block; import api.Shape; import api.Cell; import api.Game; import api.GameStatus; import api.PlayLevel; import api.Position;
/** * User interface for the main grid of a Tetris-like game. */ public class GamePanel extends JPanel { /** * The javax.swing.Timer instance used to animate the UI. */ private Timer timer; /** * The IGame instance for which this is the UI. */ private Game game; /** * Score panel associated with the game. */ private ScorePanel scorePanel; /** * State variable indicating when the timer frequency is increased * for dropping a polyomino to the bottom of the grid. */ private boolean fastDrop; /** * State variable counts down to zero while animating * the cells to be collapsed. */ private int animationState = 0; private int animationFrames = 10; /** * The difficulty level of the game, which determines the * speed of the animation. */ private PlayLevel level; /** * When the IGame object is in the COLLAPSING state, this * field stores the the cells to be collapsed in the * next step. This value can be used to apply special rendering * or animation to the collapsing cells. An invariant is maintained * that this variable is non-null if and only if the IGame state * is COLLAPSING. */ private List blocksToCollapse = null; /** * Constructs a GamePanel with the given game and play level. * @param pGame the IGame instance for which this is the UI * @param pLevel the IPlayLevel that will determine the * animation speed for this UI */ public GamePanel(Game pGame, ScorePanel pPanel, PlayLevel pLevel) { scorePanel = pPanel; game = pGame; level = pLevel; addKeyListener(new MyKeyListener()); timer = new Timer(level.speed(0) , new TimerCallback()); timer.start(); } // The paintComponent is invoked by the Swing framework whenever // the panel needs to be rendered on the screen. In this application, // repainting is normally triggered by the calls to the repaint() // method in the timer callback and the keyboard event handler (see below). @Override public void paintComponent(Graphics g) { // clear background g.setColor(GameMain.BACKGROUND_COLOR); g.fillRect(0, 0, getWidth(), getHeight()); // paint occupied cells of the grid for (int row = 0; row 0) { g.setColor(Color.DARK_GRAY);
for (int i = 0; i
// draw the cell smaller depending on the flashing state double percent = ((double) animationState) / (animationFrames); int cellSize = (int) Math.round(percent * GameMain.SIZE); int offset = (GameMain.SIZE - cellSize) / 2; Color c = t == null ? Color.YELLOW : t.getColorHint(); // scale everything up by the SIZE x = GameMain.SIZE * col; y = GameMain.SIZE * row; g.setColor(c); g.fillRect(x + offset, y + offset, cellSize, cellSize); //g.setColor(Color.GRAY);; //g.drawRect(x, y, GameMain.SIZE - 1, GameMain.SIZE - 1); } /** * Method invoked each time the timer fires. */ private void doOneStep() { // transition the game through one step, and interpret the status GameStatus state = game.step(); if (state == GameStatus.GAME_OVER) { timer.stop(); } else { if (state == GameStatus.NEW_SHAPE) { // if we were in the collapsing state, we're done blocksToCollapse = null; // TODO only do this if we were animating int speed = level.speed(game.getScore()); timer.setDelay(speed); timer.setInitialDelay(speed); timer.restart(); } if (state == GameStatus.COLLAPSING || state == GameStatus.STOPPED) { // current polygon has reached the bottom, so if we were doing // a fast drop, reset the timer to normal if (fastDrop) { normalSpeed(); fastDrop = false; } if (state == GameStatus.COLLAPSING) { // indicates that next call to step() will collapse cells, // so we want to animate them before invoking step() again. // Use the fast drop rate for animation blocksToCollapse = game.getPositionsToCollapse(); animationState = animationFrames; fastSpeed(); } } // else state is FALLING, nothing to do but repaint } } private void normalSpeed() { int speed = level.speed(game.getScore()); timer.setDelay(speed); timer.setInitialDelay(speed); timer.restart(); } private void fastSpeed() { int speed = level.fastDropSpeed(game.getScore()); timer.setDelay(speed); timer.setInitialDelay(0); timer.restart(); } /** * Listener for timer events. The actionPerformed method * is invoked each time the timer fires. */ private class TimerCallback implements ActionListener { @Override public void actionPerformed(ActionEvent arg0) { if (animationState == 0) { doOneStep(); scorePanel.updateScore(game.getScore()); repaint(); } else { repaint(); animationState--; } } } /** * Listener for keyboard events. */ private class MyKeyListener implements KeyListener { @Override public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); if (code == KeyEvent.VK_RIGHT) { if (game.shiftRight()) { repaint(); } } else if (code == KeyEvent.VK_LEFT) { if (game.shiftLeft()) { repaint(); } } else if (code == KeyEvent.VK_UP) { if (game.transform()) { repaint(); } } else if (code == KeyEvent.VK_SPACE) { game.cycle(); repaint(); } else if (code == KeyEvent.VK_DOWN) { if (!fastDrop) { // reset timer for the fast drop frame rate fastSpeed(); fastDrop = true; } } }
@Override public void keyReleased(KeyEvent e) { int code = e.getKeyCode(); if (code == KeyEvent.VK_DOWN) { // turn off fast drop mode when downarrow is released, // but not if we're animating if (fastDrop && animationState == 0) { normalSpeed(); } if (fastDrop) { fastDrop = false; } } }
@Override public void keyTyped(KeyEvent e) { // not used } } }
ScorePanel Class
package ui; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D;
import javax.swing.JPanel;
/** * Panel for displaying the score in a simple video game. */ public class ScorePanel extends JPanel { /** * Format string for displaying score. */ private static final String SCORE_FORMAT = "Score: %1d";
/** * Score to be displayed. */ private int score;
/** * Sets the score to be displayed in this panel. * @param newScore * score to be displayed */ public void updateScore(int newScore) { this.score = newScore; repaint(); }
@Override public void paintComponent(Graphics g) { Dimension d = getPreferredSize(); ((Graphics2D) g).setBackground(Color.WHITE); g.clearRect(0, 0, d.width, d.height); Font font = new Font(Font.SANS_SERIF, Font.PLAIN, GameMain.SCORE_FONT); g.setFont(font); FontMetrics metrics = g.getFontMetrics(font); String text = String.format(SCORE_FORMAT, score); int width = metrics.stringWidth(text); int x = (d.width - width) / 2; int y = (d.height) / 2;
g.drawString(text, x, y); } }
THESE ARE THE CLASSES I NEED MODIFIED (BELOW)
AbstractShape Class
package hw4;
import api.Shape;
/** * Abstract superclass for implementations of the Shape interface. */ public abstract class AbstractShape implements Shape { // TODO - add the methods and constructors you want // (constructors must be declared protected) @Override public Shape clone() { try { AbstractShape s = (AbstractShape) super.clone();
// TODO: make it into a deep copy return s; } catch (CloneNotSupportedException e) { // can't happen return null; } } }
BasicGenerator Class package hw4;
import api.Generator; import api.Shape;
/** * Generator for Shape objects in MagicTetris. All six shapes * are equally likely, and the generated shape is magic with * 20% probability. */ public class BasicGenerator implements Generator { @Override public Shape getNext(int width) { // TODO return null; } }
MagicTetris Class package hw4;
import java.util.List;
import api.AbstractGame; import api.Position;
/** * MagicTetris implementation. */ public class MagicTetris extends AbstractGame { /** * Constructs a game with the given width (columns) and height (rows). * This game will use a new instance of BasicGenerator to * generate new shapes. * @param width * width of the game grid (number of columns) * @param height * height of the game grid (number of rows) */ public MagicTetris(int width, int height) { super(width, height, new BasicGenerator()); }
@Override public List determinePositionsToCollapse() { // TODO return null; }
@Override protected int determineScore() { // TODO return 0; }
}
I also need 6 shape classes created according to the specifications - JShape, LShape, IShape, SZShape, OShape, and TShape
Summary of tasks 1. Create implementations of six concrete subtypes of the shape interface: o Ishape o JShape o LShape o OShape O SZShape o TShape Implement the abstract class AbstractShape containing the common code for the concrete shape classes above (optionally, you can implement additional abstract classes extending Abstractshape, if you find that doing so improves your design). 2. 3. Implement a class BasicGenerator that implements the Generator interface 4. Implement a clasS MagicTetris extending the AbstractGame class, in which you provide implementations of the methods determinePositionsToCollapse ) and determineScore, and the constructor All of your code goes in the package hw4 Overview In this project you will complete the implementation of a simplified Tetris-style or "falling blocks" type of video game. This particular game, which we'll call MagicTetris, is a variation of Tetris. If you are not familiar with such games, examples are not hard to find on the internet. The basic idea is as follows. The game is played on a 2D grid. Each position in this grid can be represented as a (row, column) pair. We typically represent these positions using the simple class api.Position, which you'll find in the sample code. At any stage in the game, a grid position may be empty or may be occupied by a block. In addition, a shape made up of a combination of blocks (often called a tetromino), falls from the top of the grid. This is referred to as the current shape. As it falls, the current shape can be shifted from side to side transformed, which may rotate or flip it, cycled, which will change the relative positions of the blocks within the shape, without changing the cells it occupies (for MagicTetris, this is only noticcable for "magic" blocks, described later) e When the currently falling shape can't fall any further, its blocks are added to the grid, and the game checks whether it has completed a row (or more generally, a collapsible set). All blocks in Summary of tasks 1. Create implementations of six concrete subtypes of the shape interface: o Ishape o JShape o LShape o OShape O SZShape o TShape Implement the abstract class AbstractShape containing the common code for the concrete shape classes above (optionally, you can implement additional abstract classes extending Abstractshape, if you find that doing so improves your design). 2. 3. Implement a class BasicGenerator that implements the Generator interface 4. Implement a clasS MagicTetris extending the AbstractGame class, in which you provide implementations of the methods determinePositionsToCollapse ) and determineScore, and the constructor All of your code goes in the package hw4 Overview In this project you will complete the implementation of a simplified Tetris-style or "falling blocks" type of video game. This particular game, which we'll call MagicTetris, is a variation of Tetris. If you are not familiar with such games, examples are not hard to find on the internet. The basic idea is as follows. The game is played on a 2D grid. Each position in this grid can be represented as a (row, column) pair. We typically represent these positions using the simple class api.Position, which you'll find in the sample code. At any stage in the game, a grid position may be empty or may be occupied by a block. In addition, a shape made up of a combination of blocks (often called a tetromino), falls from the top of the grid. This is referred to as the current shape. As it falls, the current shape can be shifted from side to side transformed, which may rotate or flip it, cycled, which will change the relative positions of the blocks within the shape, without changing the cells it occupies (for MagicTetris, this is only noticcable for "magic" blocks, described later) e When the currently falling shape can't fall any further, its blocks are added to the grid, and the game checks whether it has completed a row (or more generally, a collapsible set). All blocks inStep by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started