Jump to content
  • Advertisement
Sign in to follow this  
xanthmode

Java Tetris Problem... Possibly an issue with my threading?

This topic is 3487 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to write my first Tetris clone and have run into a dead end. The game starts, I can move the pieces around, complete lines, earn points, and increase the difficulty level. Everything is working great until the game ends or you try to start a new game while the game is currently running. The new game seems to be working okay but when a piece lands on the bottom there are suddenly two pieces on the bottom. If you start three new games in a row there will be three pieces and so on. I think that my GameLoop thread is still interacting with the GamePanel but I can't figure out what the issue is. I assume that when a Thread reaches the end of its Run method that the Thread terminates and would no longer be accessible. Is that not correct? I would really appreciate it if anyone could take a look at my code and give me hint at what is going on. BlocksGame.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
  * BlocksGame is a puzzle game that is played by dropping blocks of various
  * shapes in order to form horizontal lines.  When a line is formed it is cleared
  * from the game board and all rows above it are dropped down to fill up the
  * empty space.  You play until the blocks stack up high enough to overflow
  * the top edge.  When this happens you lose.  You gain points for completing
  * lines.  The more lines you complete the more points you gain.
  */
public class BlocksGame extends JFrame implements ActionListener
{
    private static final String GAME_TITLE = "Blocks Game";

    public static int BLOCK_SIZE;
    public static int GAME_WIDTH;
    public static int GAME_HEIGHT;
    public static int STATUS_WIDTH;
    public static Dimension GAME_PANEL_SIZE;
    public static Dimension STATUS_PANEL_SIZE;
    public static GamePanel gamePanel;
    public static StatusPanel statusPanel;

    /**
      * The main method.
      *
      * @param args An String array which is made up of the arguments on the command line.
      */
    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() {
                BlocksGame f = new BlocksGame(); 
            }
        });
    }

    /**
      * The constructor for BlocksGame.
      */
    public BlocksGame()
    {
        initializeProgram();

        setTitle( GAME_TITLE );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        //f.setSize( WINDOW_SIZE );
        setResizable( false );

        setLayout( new BorderLayout() );

        add( createMenuBar(),     BorderLayout.PAGE_START );
        add( createStatusPanel(), BorderLayout.LINE_END );
        add( createGamePanel(),   BorderLayout.LINE_START );

        pack();

        setVisible(true);
    } 

    /**
      * Sets up initial values for the program.
      */
    private void initializeProgram()
    {
        BLOCK_SIZE   = 32;
        GAME_WIDTH   = BLOCK_SIZE * 10;
        GAME_HEIGHT  = BLOCK_SIZE * 20;
        STATUS_WIDTH = BLOCK_SIZE * 5;

        GAME_PANEL_SIZE   = new Dimension( GAME_WIDTH, GAME_HEIGHT );
        STATUS_PANEL_SIZE = new Dimension( STATUS_WIDTH, GAME_HEIGHT );
    }

    /**
      * Creates the menu at the top of the screen and all of the menu items.
      */
    private JMenuBar createMenuBar()
    {
        JMenuBar menuBar;
        JMenu menu;
        JMenuItem menuItem;

        // create a new menu bar
        menuBar  = new JMenuBar();

        // add the File menu to the menu bar
        menu     = new JMenu( "File" );
        menuItem = new JMenuItem( "New Game" );
        menuItem.addActionListener(this);
        menuItem.setActionCommand( "NewGame" );

        menu.add( menuItem );
        menuBar.add( menu );

        // add the Help menu to the menu bar
        menu     = new JMenu( "Help" );
        menuItem = new JMenuItem( "About" );
        menuItem.addActionListener(this);
        menuItem.setActionCommand( "About" );

        menu.add( menuItem );
        menuBar.add( menu );

        return menuBar;
    }

    /**
      * Creates the GamePanel where all of the action takes place.
      *
      * @return the GamePanel.
      */
    private GamePanel createGamePanel()
    {
        gamePanel = new GamePanel( GAME_PANEL_SIZE, BLOCK_SIZE, statusPanel );

        return gamePanel;
    }

    /**
      * Creates the StatusPanel which displays useful information to the player.
      *
      * @return the StatusPanel.
      */
    private StatusPanel createStatusPanel()
    {
        statusPanel = new StatusPanel( STATUS_PANEL_SIZE );

        return statusPanel;
    }

    /**
      * Handles the actions for the menu bar.
      *
      * @param e the ActionEvent that triggered this method call.
      */
    public void actionPerformed( ActionEvent e )
    {
        if ( e.getActionCommand().equals( "NewGame" ) )
        {
            if ( gamePanel.isGameRunning() )
            {
                gamePanel.startGame();
            }
            else
            {
                gamePanel.startGame();
            }
        }
        else if ( e.getActionCommand().equals( "About" ) )
        {
        }
    }
}


GamePanel.java
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Rectangle2D;

/**
  * The GamePanel is the surface where BlocksGame is played.  The GamePanel
  * is represented by an array[20][11] which allocates 20 rows and 10 columns
  * for displaying blocks.  The 11th column is used to mark lines which are 
  * full and need to be cleared.
  *
  */
public class GamePanel extends JPanel
{
    private Dimension PANEL_SIZE;
    private int BLOCK_SIZE;

    private int[][] cells = new int[20][11];

    public Tetrad currentPiece;
    public Tetrad nextPiece;
    private Random generator;
    private GameLoop gameLoop;
    private StatusPanel sp;

    private boolean gameRunning;

    /**
      * The constructor for the GamePanel.
      *
      * @param size a Dimension that defines the width and height of the GamePanel.
      * @param blockSize the length of one side of an individual Block.
      */
    public GamePanel( Dimension size, int blockSize, StatusPanel sPanel )
    {
        sp = sPanel;

        setBorder( BorderFactory.createLineBorder( Color.black ) );
        setBackground( Color.WHITE );

        PANEL_SIZE  = size;
        BLOCK_SIZE  = blockSize;
        generator   = new Random();
        nextPiece   = getNextPiece();
        gameRunning = false;

        setFocusable( true );

        init();
    }

    /**
      * Initializes the GamePanel so that it is ready to start playing the game.
      */
    public void init()
    {
        for ( int row = 0; row < 20; row++ )
        {
            for ( int col = 0; col < 11; col++ )
            {
                try
                {
                    cells[row][col] = 0;
                }
                catch ( NullPointerException e )
                {
                    System.out.println( "NullPointerException caught!" );
                }
            }
        }
    }

    /**
      * Starts the game by calling the start method of gameLoop.
      */
    public void startGame()
    {
        if ( gameRunning )
        {
            System.out.println( "Sending interrupt..." );
            gameLoop.interrupt();
            gameLoop = null;
        }

        gameRunning = true;

        gameLoop = new GameLoop( this, sp );  
        addKeyListener( gameLoop );
        gameLoop.start();
        System.out.println( "Game started" );
    }

    /**
      * Checks to see if the game is currently running or not.
      *
      * @return true if the game is running.
      */
    public boolean isGameRunning()
    {
        return gameRunning;
    }

    /**
      * Sets the gameRunning flag to false.
      */
    public void setGameOver()
    {
        gameRunning = false;
    }

    /**
      * Creates a new random Tetrad.
      *
      * @return the newly created Tetrad.
      */
    public Tetrad getNextPiece()
    {
        int style       = generator.nextInt(7) + 1;
        int orientation = generator.nextInt(4) + 1;

        return( new Tetrad( BLOCK_SIZE, style, orientation, this ) );
    }

    /** 
      * Checks to see if a cell on the GamePanel is already occupied.
      *
      * @param row the row value for the cell.
      * @param col the column value for the cell.
      * @return true if the cell is occupied and false if it is empty.
      */
    public boolean isOccupied( int row, int col )
    {
        if ( row < 0 )
        {
            return false;
        }

        if ( cells[row][col] == 0 )
        {
            return false;
        }

        return true;
    }

    /**
      * Sets the style of the Block for a specific cell.
      *
      * @param row the row value for the cell.
      * @param col the column value for the cell.
      * @param style the style of the block.
      */
    public boolean setBlock( int row, int col, int style )
    {
        if ( row < 0  ||
             row > 19 || 
             col < 0  || 
             col > 9     )
        {
            return false;
        }

        cells[row][col] = style;
        return true;
    }

    /**
      * Retrieves the style of the Block in a specific cell.
      *
      * @param row the row value for the cell.
      * @param col the column value for the cell.
      * @return the style of the block as an integer.
      */
    public int getBlock( int row, int col )
    {
        return cells[row][col];
    }

    /**
      * Marks a row in the GamePanel so that it will be cleared.
      *
      * @param line an integer referring to a row in the GamePanel.
      */
    public void markLine ( int line )
    {
        cells[line][10] = 1;
    }

    /**
      * Checks if a particular row has been marked.
      *
      * @param line an integer referring to a row in the GamePanel.
      * @return true if the row is marked and false if it has not.
      */
    public boolean isMarked( int line )
    {
        if ( cells[line][10] == 1 )
        {
            return true;
        }

        return false;
    }

    public void eraseRow( int row )
    {
        for ( int i = 0; i < 11; i++ )
        {
            cells[row] = 0;
        }
    }

    /**
      * Copies the cells from the src row to the dest row.
      *
      * @param src the row to copy from.
      * @param dest the row to copy to.
      */
    public void copyRow( int src, int dest )
    {
        if ( dest == 0 )
        {
            eraseRow( dest );
            return;
        }

        for ( int i = 0; i < 11; i++ )
        {
            cells[dest] = cells[src];
        }
    }

    /**
      * Retrieves the preferredSize of the GamePanel.
      *
      * @return a Dimension object holding the preferredSize.
      */
    public Dimension getPreferredSize() 
    {
        return PANEL_SIZE;
    }

    /**
      * The overridden paintComponent method for the GamePanel.
      *
      * @param g the Graphics context for the GamePanel.
      */
    public void paintComponent( Graphics g ) 
    {
        super.paintComponent( g );

        Block block;

        for ( int row = 0; row < 20; row++ )
        {
            for ( int col = 0; col < 10; col++ )
            {
                block = new Block( BLOCK_SIZE, cells[row][col], row, col );
                block.draw( g );
            }
        }

        if ( currentPiece != null )
        {
            currentPiece.draw( g );
        }

        if ( ! isGameRunning() )
        {
            AlphaComposite ac = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.50f );

            BufferedImage buffImg = new BufferedImage( (int) PANEL_SIZE.getWidth(), (int) PANEL_SIZE.getHeight(), BufferedImage.TYPE_INT_ARGB );
            Graphics2D gbi = buffImg.createGraphics();

            gbi.setColor( Color.WHITE );
            gbi.setComposite( ac );
            gbi.fill( new Rectangle2D.Double( 0, 0, (int) PANEL_SIZE.getWidth(), (int) PANEL_SIZE.getHeight() ) );

            g.drawImage( buffImg, 0, 0, null );

            String text = "GAME OVER";

            Font font = new Font( "Monospaced", Font.BOLD, 42 );
            
            g.setColor( Color.BLACK );
            g.setFont( font );
            
            FontMetrics metrics = g.getFontMetrics();
            
            int strx = getWidth() / 2 - metrics.stringWidth( text ) / 2;
            int stry = getHeight() / 2 - metrics.getHeight() / 2;

            g.drawString( text, strx, stry );
        }
    }  
}


GameLoop.java
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Rectangle2D;

/**
  * The GamePanel is the surface where BlocksGame is played.  The GamePanel
  * is represented by an array[20][11] which allocates 20 rows and 10 columns
  * for displaying blocks.  The 11th column is used to mark lines which are 
  * full and need to be cleared.
  *
  */
public class GamePanel extends JPanel
{
    private Dimension PANEL_SIZE;
    private int BLOCK_SIZE;

    private int[][] cells = new int[20][11];

    public Tetrad currentPiece;
    public Tetrad nextPiece;
    private Random generator;
    private GameLoop gameLoop;
    private StatusPanel sp;

    private boolean gameRunning;

    /**
      * The constructor for the GamePanel.
      *
      * @param size a Dimension that defines the width and height of the GamePanel.
      * @param blockSize the length of one side of an individual Block.
      */
    public GamePanel( Dimension size, int blockSize, StatusPanel sPanel )
    {
        sp = sPanel;

        setBorder( BorderFactory.createLineBorder( Color.black ) );
        setBackground( Color.WHITE );

        PANEL_SIZE  = size;
        BLOCK_SIZE  = blockSize;
        generator   = new Random();
        nextPiece   = getNextPiece();
        gameRunning = false;

        setFocusable( true );

        init();
    }

    /**
      * Initializes the GamePanel so that it is ready to start playing the game.
      */
    public void init()
    {
        for ( int row = 0; row < 20; row++ )
        {
            for ( int col = 0; col < 11; col++ )
            {
                try
                {
                    cells[row][col] = 0;
                }
                catch ( NullPointerException e )
                {
                    System.out.println( "NullPointerException caught!" );
                }
            }
        }
    }

    /**
      * Starts the game by calling the start method of gameLoop.
      */
    public void startGame()
    {
        if ( gameRunning )
        {
            System.out.println( "Sending interrupt..." );
            gameLoop.interrupt();
            gameLoop = null;
        }

        gameRunning = true;

        gameLoop = new GameLoop( this, sp );  
        addKeyListener( gameLoop );
        gameLoop.start();
        System.out.println( "Game started" );
    }

    /**
      * Checks to see if the game is currently running or not.
      *
      * @return true if the game is running.
      */
    public boolean isGameRunning()
    {
        return gameRunning;
    }

    /**
      * Sets the gameRunning flag to false.
      */
    public void setGameOver()
    {
        gameRunning = false;
    }

    /**
      * Creates a new random Tetrad.
      *
      * @return the newly created Tetrad.
      */
    public Tetrad getNextPiece()
    {
        int style       = generator.nextInt(7) + 1;
        int orientation = generator.nextInt(4) + 1;

        return( new Tetrad( BLOCK_SIZE, style, orientation, this ) );
    }

    /** 
      * Checks to see if a cell on the GamePanel is already occupied.
      *
      * @param row the row value for the cell.
      * @param col the column value for the cell.
      * @return true if the cell is occupied and false if it is empty.
      */
    public boolean isOccupied( int row, int col )
    {
        if ( row < 0 )
        {
            return false;
        }

        if ( cells[row][col] == 0 )
        {
            return false;
        }

        return true;
    }

    /**
      * Sets the style of the Block for a specific cell.
      *
      * @param row the row value for the cell.
      * @param col the column value for the cell.
      * @param style the style of the block.
      */
    public boolean setBlock( int row, int col, int style )
    {
        if ( row < 0  ||
             row > 19 || 
             col < 0  || 
             col > 9     )
        {
            return false;
        }

        cells[row][col] = style;
        return true;
    }

    /**
      * Retrieves the style of the Block in a specific cell.
      *
      * @param row the row value for the cell.
      * @param col the column value for the cell.
      * @return the style of the block as an integer.
      */
    public int getBlock( int row, int col )
    {
        return cells[row][col];
    }

    /**
      * Marks a row in the GamePanel so that it will be cleared.
      *
      * @param line an integer referring to a row in the GamePanel.
      */
    public void markLine ( int line )
    {
        cells[line][10] = 1;
    }

    /**
      * Checks if a particular row has been marked.
      *
      * @param line an integer referring to a row in the GamePanel.
      * @return true if the row is marked and false if it has not.
      */
    public boolean isMarked( int line )
    {
        if ( cells[line][10] == 1 )
        {
            return true;
        }

        return false;
    }

    public void eraseRow( int row )
    {
        for ( int i = 0; i < 11; i++ )
        {
            cells[row] = 0;
        }
    }

    /**
      * Copies the cells from the src row to the dest row.
      *
      * @param src the row to copy from.
      * @param dest the row to copy to.
      */
    public void copyRow( int src, int dest )
    {
        if ( dest == 0 )
        {
            eraseRow( dest );
            return;
        }

        for ( int i = 0; i < 11; i++ )
        {
            cells[dest] = cells[src];
        }
    }

    /**
      * Retrieves the preferredSize of the GamePanel.
      *
      * @return a Dimension object holding the preferredSize.
      */
    public Dimension getPreferredSize() 
    {
        return PANEL_SIZE;
    }

    /**
      * The overridden paintComponent method for the GamePanel.
      *
      * @param g the Graphics context for the GamePanel.
      */
    public void paintComponent( Graphics g ) 
    {
        super.paintComponent( g );

        Block block;

        for ( int row = 0; row < 20; row++ )
        {
            for ( int col = 0; col < 10; col++ )
            {
                block = new Block( BLOCK_SIZE, cells[row][col], row, col );
                block.draw( g );
            }
        }

        if ( currentPiece != null )
        {
            currentPiece.draw( g );
        }

        if ( ! isGameRunning() )
        {
            AlphaComposite ac = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.50f );

            BufferedImage buffImg = new BufferedImage( (int) PANEL_SIZE.getWidth(), (int) PANEL_SIZE.getHeight(), BufferedImage.TYPE_INT_ARGB );
            Graphics2D gbi = buffImg.createGraphics();

            gbi.setColor( Color.WHITE );
            gbi.setComposite( ac );
            gbi.fill( new Rectangle2D.Double( 0, 0, (int) PANEL_SIZE.getWidth(), (int) PANEL_SIZE.getHeight() ) );

            g.drawImage( buffImg, 0, 0, null );

            String text = "GAME OVER";

            Font font = new Font( "Monospaced", Font.BOLD, 42 );
            
            g.setColor( Color.BLACK );
            g.setFont( font );
            
            FontMetrics metrics = g.getFontMetrics();
            
            int strx = getWidth() / 2 - metrics.stringWidth( text ) / 2;
            int stry = getHeight() / 2 - metrics.getHeight() / 2;

            g.drawString( text, strx, stry );
        }
    }  
}


StatusPanel.java
import javax.swing.*;
import java.awt.*;

/**
  * Displays status information about the game to the player.
  * This information is kept up to date by GameLoop.
  */
public class StatusPanel extends JPanel
{
    private JLabel lblNext;
    private JLabel lblLevel;
    private JLabel lblCleared;
    private JLabel lblPoints;

    /**
      * The constructor for the StatusPanel.
      *
      * @param size the preferred dimensions of the StatusPanel.
      */
    public StatusPanel( Dimension size )
    {
        setLayout( new FlowLayout( FlowLayout.CENTER ) );

        setPreferredSize( size );

        lblNext = new JLabel( "NEXT", setNextIcon(0), JLabel.CENTER );
        lblNext.setVerticalTextPosition( JLabel.BOTTOM );
        lblNext.setHorizontalTextPosition( JLabel.CENTER );
        lblNext.setMinimumSize( new Dimension( (int) size.getWidth(), 120  ) );
        lblNext.setPreferredSize( new Dimension( (int) size.getWidth(), 120 ) );

        lblLevel = new JLabel( "   Level: ", JLabel.LEFT );
        lblLevel.setMinimumSize( new Dimension( (int) size.getWidth(), 20 ) );
        lblLevel.setPreferredSize( new Dimension( (int) size.getWidth(), 20 ) );

        lblCleared = new JLabel( "   Cleared: ", JLabel.LEFT );
        lblCleared.setMinimumSize( new Dimension( (int) size.getWidth(), 20 ) );
        lblCleared.setPreferredSize( new Dimension( (int) size.getWidth(), 20 ) );
        
        lblPoints = new JLabel( "   Points: ", JLabel.LEFT );
        lblPoints.setMinimumSize( new Dimension( (int) size.getWidth(), 20 ) );
        lblPoints.setPreferredSize( new Dimension( (int) size.getWidth(), 20 ) );

        add( lblNext );
        add( lblLevel );
        add( lblCleared );
        add( lblPoints );
    }

    /**
      * Sets the initial values in the StatusPanel.
      */
    public void init()
    {
        setNextIcon( 0 );
        setPoints( 0 );
        setLevel( 1 );
        setCleared( 0 );
    }

    /**
      * Sets the text for the Points label.
      *
      * @param points the current number of points.
      */
    public void setPoints( int points )
    {
        lblPoints.setText( "   Points: " + points );
    }

    /**
      * Sets the text for the Level label.
      *
      * @param level the current level.
      */
    public void setLevel( int level )
    {
        lblLevel.setText( "   Level: " + level );
    }

    /**
      * Sets the text for the Cleared label.
      * 
      * @param cleared the number of lines that have been cleared.
      */
    public void setCleared( int cleared )
    {
        lblCleared.setText( "   Cleared: " + cleared );
    }

    /**
      * Sets the icon that is displayed for the NEXT piece preview.
      *
      * @param style the style of the icon.  These are the same styles as defined in Tetrad.
      *
      * @return the ImageIcon that corresponds to the style.
      */
    public ImageIcon setNextIcon( int style )
    {
        switch ( style )
        {
            case 1: return new ImageIcon( "empty.png" );
            case 2: return new ImageIcon( "empty.png" );
            case 3: return new ImageIcon( "empty.png" );
            case 4: return new ImageIcon( "empty.png" );
            case 5: return new ImageIcon( "empty.png" );
            case 6: return new ImageIcon( "empty.png" );
            case 7: return new ImageIcon( "empty.png" );
            default: return new ImageIcon( "empty.png" );
        }
    }
}


Tetrad.java
import java.awt.*;

/**
  * Represents a collection of Blocks called a Tetrad.  Each Tetrad is
  * composed of four Blocks.  The Tetrad can be moved left, right, and down.
  * It can also be spun left and right to make it fit with other Tetrads on
  * the GamePanel.
  *
  * There are seven different styles of Tetrads which are specified by an
  * integer style.  Each Tetrad is anchored to the GamePanel via its second
  * Block, or block2.  The position of the other Blocks is determined from
  * the position of block2 and the current orientation.  There are four
  * possible orientations for each Tetrad.
  *
  */
public class Tetrad
{
    private int style;
    private int orientation;
    private int row;
    private int col;

    private GamePanel gp;

    public Block block1;
    public Block block2;
    public Block block3;
    public Block block4;

    /**
      * A constructor to create a new Tetrad.
      *
      * @param z the size of an individual Block.
      * @param s the style for this Tetrad.
      * @param o the orientation for this Tetrad.
      * @param gPanel the GamePanel object where the Tetrads will be drawn.
      */
    public Tetrad( int z, int s, int o, GamePanel gPanel )
    {
        gp          = gPanel;
        style       = s;
        orientation = o;
        row         = 0;
        col         = 4;

        block2 = new Block( z, s, row, col );
        block1 = new Block( z, s, row, col );
        block3 = new Block( z, s, row, col );
        block4 = new Block( z, s, row, col );
        
        setOrientation( o );
    }

    /**
      * Retrieves the style of this Tetrad.
      *
      * @return the style of this Tetrad.
      */
    public int getStyle()
    {
        return style;
    }

    /**
      * Draws the individual Blocks of the Tetrad on to the GamePanel.
      *
      * @param g the Graphics context for the GamePanel.
      */
    public void draw( Graphics g )
    {
        block1.draw( g );
        block2.draw( g );
        block3.draw( g );
        block4.draw( g );
    }

    /**
      * Attempts to change the orientation by spinning the Tetrad to the counter clockwise.
      */
    public void spinLeft()
    {
        switch ( orientation )
        {
            case 1: setOrientation( 2 ); break;
            case 2: setOrientation( 3 ); break;
            case 3: setOrientation( 4 ); break;
            case 4: setOrientation( 1 ); break;
            default: break;
        }
    }

    /**
      * Attempts to change the orientation by spinning the Tetrad to the clockwise.
      */
    public void spinRight()
    {
        switch ( orientation )
        {
            case 1: setOrientation( 4 ); break;
            case 2: setOrientation( 1 ); break;
            case 3: setOrientation( 2 ); break;
            case 4: setOrientation( 3 ); break;
            default: break;
        }
    }

    /**
      * Attempts to move the entire Tetrad to the left.  Four new Blocks
      * are created as a temporary Tetrad to verify that the left movement
      * would be valid.  If it works then the temporary Blocks are copied
      * over the old Blocks and the Tetrad is therefore moved to the new
      * position.
      */
    public void moveLeft()
    {
        Block tmpBlock1 = new Block( block1 );
        Block tmpBlock2 = new Block( block2 );
        Block tmpBlock3 = new Block( block3 );
        Block tmpBlock4 = new Block( block4 );

        tmpBlock1.adjustCol( -1 );
        tmpBlock2.adjustCol( -1 );
        tmpBlock3.adjustCol( -1 );
        tmpBlock4.adjustCol( -1 );

        if ( isPlacementOK( tmpBlock1 ) &&
             isPlacementOK( tmpBlock2 ) &&
             isPlacementOK( tmpBlock3 ) &&
             isPlacementOK( tmpBlock4 ) )
        {
            block1 = tmpBlock1;
            block2 = tmpBlock2;
            block3 = tmpBlock3;
            block4 = tmpBlock4;
        }
    }

    /**
      * Attempts to move the entire Tetrad to the right.  Four new Blocks
      * are created as a temporary Tetrad to verify that the right movement
      * would be valid.  If it works then the temporary Blocks are copied
      * over the old Blocks and the Tetrad is therefore moved to the new
      * position.
      */
    public void moveRight()
    {
        Block tmpBlock1 = new Block( block1 );
        Block tmpBlock2 = new Block( block2 );
        Block tmpBlock3 = new Block( block3 );
        Block tmpBlock4 = new Block( block4 );

        tmpBlock1.adjustCol( 1 );
        tmpBlock2.adjustCol( 1 );
        tmpBlock3.adjustCol( 1 );
        tmpBlock4.adjustCol( 1 );

        if ( isPlacementOK( tmpBlock1 ) &&
             isPlacementOK( tmpBlock2 ) &&
             isPlacementOK( tmpBlock3 ) &&
             isPlacementOK( tmpBlock4 ) )
        {
            block1 = tmpBlock1;
            block2 = tmpBlock2;
            block3 = tmpBlock3;
            block4 = tmpBlock4;
        }
    }

    /**
      * Attempts to move the entire Tetrad downward.  Four new Blocks
      * are created as a temporary Tetrad to verify that the downward movement
      * would be valid.  If it works then the temporary Blocks are copied
      * over the old Blocks and the Tetrad is therefore moved to the new
      * position.
      *
      * @return true if the movement was successful.
      */
    public boolean moveDown()
    {
        Block tmpBlock1 = new Block( block1 );
        Block tmpBlock2 = new Block( block2 );
        Block tmpBlock3 = new Block( block3 );
        Block tmpBlock4 = new Block( block4 );

        tmpBlock1.adjustRow( 1 );
        tmpBlock2.adjustRow( 1 );
        tmpBlock3.adjustRow( 1 );
        tmpBlock4.adjustRow( 1 );

        if ( isPlacementOK( tmpBlock1 ) &&
             isPlacementOK( tmpBlock2 ) &&
             isPlacementOK( tmpBlock3 ) &&
             isPlacementOK( tmpBlock4 ) )
        {
            block1 = tmpBlock1;
            block2 = tmpBlock2;
            block3 = tmpBlock3;
            block4 = tmpBlock4;

            return true;
        }
        
        return false;
    }

    /**
      * Checks to see if the bottom of any of the Blocks in the Tetrad are 
      * touching the top of any other Tetrad or the bottom of the GamePanel.
      * If any of them are the Tetrad is said to be ready to land and will
      * land in that position on the next game initiated downward movement.
      *
      * @return a boolean value indicating whether the Tetrad is ready to land or not.
      */
    public boolean isReadyToLand()
    {
        if ( isReadyToLand( block1 ) ||
             isReadyToLand( block2 ) ||
             isReadyToLand( block3 ) ||
             isReadyToLand( block4 )    )
        {
            return true;
        }

        return false;
    }

    /**
      * Checks to see if the Block is ready to land.
      *
      * @param b the Block to check.
      * @return a boolean value indicating whether the Block is ready to land or not.
      */
    public boolean isReadyToLand( Block b )
    {
        if ( b.getRow() == 19 )
        {
            return true;
        }

        if ( gp.isOccupied( b.getRow() + 1, b.getCol() ) )
        {
            return true;
        }

        return false;
    }

    /**
      * Checks to see if the current placement of the Block is valid.
      *
      * @param b the block to check.
      * @return true if the placement is valid and false otherwise.
      */
    private boolean isPlacementOK( Block b )
    {
        /* foreach block verify that it is on the screen
           and that it is not covering any other block */

        if ( b.getRow() > 19 )
        {
            return false;
        }

        if ( b.getCol() > 9 )
        {
            return false;
        }

        if ( b.getCol() < 0 )
        {
            return false;
        }
        
        if ( gp.isOccupied( b.getRow(), b.getCol() ) )
        {
            return false;
        }
        
        return true;
    }

    /**
      * Sets the orientation of the Tetrad.  The Blocks are first
      * copied to new temporary Blocks which are then arranged in 
      * new orientation.  If the temporary Blocks are all placed
      * in valid locations then the orientation is considered valid
      * and the real Blocks are updated with the new positions.
      *
      * @param o an integer indicating the new orientation.
      */
    public void setOrientation( int o )
    {
        Block tmpBlock1 = new Block( block2 );
        Block tmpBlock3 = new Block( block2 );
        Block tmpBlock4 = new Block( block2 );

        // line
        if ( style == 1 )
        {
            switch ( o )
            {
                case 1: tmpBlock1.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() + 2, block2.getCol() );
                    
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 2: tmpBlock1.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock4.setCoords( block2.getRow(), block2.getCol() + 2 );

                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 3: tmpBlock1.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() - 2, block2.getCol() );

                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 4: tmpBlock1.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() - 1);
                        tmpBlock4.setCoords( block2.getRow(), block2.getCol() - 2 );

                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                default: break;
            }
        }
        // L Block
        else if ( style == 2 )
        {
            switch ( o )
            {
                case 1: tmpBlock1.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() + 1 );

                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 2: tmpBlock1.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 3: tmpBlock1.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() - 1);
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 4: tmpBlock1.setCoords( block2.getRow(), block2.getCol() + 1);
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() -1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                default: break;
            }
        }
        //reverse L block
        else if ( style == 3 )
        {
            switch ( o )
            {
                case 1: tmpBlock1.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() - 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 2: tmpBlock1.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 3: tmpBlock1.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 4: tmpBlock1.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() - 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                default: break;
            }
        }
        // T block
        else if ( style == 4 )
        {
            switch ( o )
            {
                case 1: tmpBlock1.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 2: tmpBlock1.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock3.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow(), block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 3: tmpBlock1.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 4: tmpBlock1.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock3.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow(), block2.getCol() - 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                default: break;
            }
        }
        // square block
        // only really has one orientation since it is square.
        else if ( style == 5 )
        {
            tmpBlock1.setCoords( block2.getRow(), block2.getCol() - 1 );
            tmpBlock3.setCoords( block2.getRow() + 1, block2.getCol() - 1 );
            tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() );
                        
            if ( isPlacementOK( tmpBlock1 ) &&
                 isPlacementOK( tmpBlock3 ) &&
                 isPlacementOK( tmpBlock4 ) )
            {
                 block1 = tmpBlock1;
                 block3 = tmpBlock3;
                 block4 = tmpBlock4;
                 orientation = o;
            }
        }
        // S block
        else if ( style == 6 )
        {
            switch ( o )
            {
                case 1: tmpBlock1.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 2: tmpBlock1.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock3.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 3: tmpBlock1.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() - 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 4: tmpBlock1.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock3.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() - 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                default: break;
            }
        }
        // reverse S block
        else if ( style == 7 )
        {
            switch ( o )
            {
                case 1: tmpBlock1.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() - 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 2: tmpBlock1.setCoords( block2.getRow(), block2.getCol() - 1 );
                        tmpBlock3.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() + 1, block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 3: tmpBlock1.setCoords( block2.getRow() + 1, block2.getCol() );
                        tmpBlock3.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() + 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                case 4: tmpBlock1.setCoords( block2.getRow(), block2.getCol() + 1 );
                        tmpBlock3.setCoords( block2.getRow() - 1, block2.getCol() );
                        tmpBlock4.setCoords( block2.getRow() - 1, block2.getCol() - 1 );
                        
                        if ( isPlacementOK( tmpBlock1 ) &&
                             isPlacementOK( tmpBlock3 ) &&
                             isPlacementOK( tmpBlock4 ) )
                        {
                            block1 = tmpBlock1;
                            block3 = tmpBlock3;
                            block4 = tmpBlock4;
                            orientation = o;
                        }
                        break;
                default: break;
            }
        }
    }

    public String toString()
    {
        String str = "block1 (" + block1.getCoords() + ")\n" 
                   + "block2 (" + block2.getCoords() + ")\n" 
                   + "block3 (" + block3.getCoords() + ")\n"
                   + "block4 (" + block4.getCoords() + ")";

        return str;
    }
}


Block.java
import java.awt.*;

/**
  * Represents a single game block on the screen.  Each game block has
  * a size, style, and row and column coordinates associated with it.
  * The style controls the color and border type.  Blank squares on the
  * GamePanel are actually Blocks with style 0.
  *
  */
public class Block
{
    private int size;
    private int style;
    private Color color;
    private Color border;
    private int row;
    private int col;

    /**
      * A constructor that takes individual arguments to define a Block.
      *
      * @param z the size of the Block.
      * @param s the style of the Block.
      * @param r the row coordinate of the Block.
      * @param c the column coordinate of the Block.
      */
    public Block( int z, int s, int r, int c)
    {
        size = z;
        setRow( r );
        setCol( c );
        setStyle( s );
    }

    /**
      * A constructor which creates a new Block with the same values as another Block.
      *
      * @param b the Block from which to copy the values.
      */
    public Block( Block b )
    {
        size = b.getSize();
        setRow( b.getRow() );
        setCol( b.getCol() );
        setStyle( b.getStyle() );
    }

    /**
      * Sets the style of this Block.  The style is simply an integer from 0-7 which is
      * used to define the color and border style of the block.
      *
      * The styles for the blocks are as follows:
      * 0 - An empty block.
      * 1 - Part of a Line Tetrad.
      * 2 - Part of an L shape Tetrad.
      * 3 - Part of a reverse L shape Tetrad.
      * 4 - Part of a T Tetrad.
      * 5 - Part of a Square Tetrad.
      * 6 - Part of an S shape Tetrad.
      * 7 - Part of a reverse S shape Tetrad.
      *
      * @param s the style to set.
      * @see setColor
      */
    public void setStyle( int s )
    {
        style  = s;
        color  = setColor( s );
        border = setBorder( s );
    }

    /**
      * Sets the color for the given style.
      *
      * @param s the style of this Block.
      * @return the Color value indicated by s.
      */
    private Color setColor( int s )
    {
        switch ( s )
        {
            case 1: return Color.CYAN;
            case 2: return Color.BLUE;
            case 3: return Color.ORANGE;
            case 4: return Color.YELLOW;
            case 5: return Color.GREEN;
            case 6: return Color.MAGENTA;
            case 7: return Color.RED;
            default: return Color.WHITE; 
        }
    }

    /**
      * Sets the color of the border around the Block.
      *
      * @param s the style of this Block.
      * @return the Color value indicated by s.
      */
    private Color setBorder( int s )
    {
        switch ( s )
        {
            case 0: return Color.GRAY;
            default: return Color.BLACK; 
        }
    }

    /**
      * Sets the row value for this Block.
      *
      * @param r the new row value.
      */
    public void setRow( int r )
    {
        row = r;
    }

    /**
      * Sets the column value for this Block.
      *
      * @param c the new column value.
      */
    public void setCol( int c )
    {
        col = c;
    }

    /**
      * Adjusts the the row value for this Block.
      *
      * @param a the amount to adjust the row value.  Can be positive or negative.
      */
    public void adjustRow( int a )
    {
        row += a;
    }

    /**
      * Adjusts the the column value for this Block.
      *
      * @param a the amount to adjust the column value.  Can be positive or negative.
      */
    public void adjustCol( int a )
    {
        col += a;
    }

    /**
      * Sets the row and column values at the same time.
      *
      * @param r the new row value.
      * @param c the new column value.
      */
    public void setCoords( int r, int c )
    {
        setRow( r );
        setCol( c );
    }

    /**
      * Retrieves a string version of the coordinates for this Block.
      *
      * @return the coordinates of this block.
      */
    public String getCoords()
    {
        return row + "," + col;
    }

    /**
      * Retrieves the style for this Block.
      *
      * @return the current style.
      */
    public int getStyle()
    {
        return style;
    }

    /**
      * Retrieves the row value for this Block.
      *
      * @return the current row.
      */
    public int getRow()
    {
        return row;
    }

    /**
      * Retrieves the column for this Block.
      *
      * @return the current column.
      */
    public int getCol()
    {
        return col;
    }

    /**
      * Retrieves the size for this Block.
      *
      * @return the current size.
      */
    public int getSize()
    {
        return size;
    }

    /**
      * Draws the Block onto the GamePanel.
      *
      * @param g the Graphics context for the GamePanel.
      */
    public void draw( Graphics g )
    {
        int startX = col * size;
        int startY = row * size;

        g.setColor( color );
        g.fillRect( startX, startY, size, size );
        g.setColor( border );
        g.drawRect( startX, startY, size, size );
    }

    /**
      * Returns the String version of this Block.
      *
      * @return this Block as a String.
      */
    public String toString()
    {
        return "Block defined as " + size + " color " + color + " style " + style + " row " + row + " col " + col;
    }
}


Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!