Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在俄罗斯方块项目中添加其他形状。循环逻辑辅助_Java_Swing_Tetris - Fatal编程技术网

Java 在俄罗斯方块项目中添加其他形状。循环逻辑辅助

Java 在俄罗斯方块项目中添加其他形状。循环逻辑辅助,java,swing,tetris,Java,Swing,Tetris,我正在创建一个俄罗斯方块克隆作为个人项目,以帮助我更好地绘制图像,移动它们,并学习碰撞检测 一切都进行得很顺利,但当第一个物体停止移动时,让程序在画面上添加一个新的tetrimino形状背后的逻辑让我感到困惑。到目前为止,我使用一个随机数生成器随机创建一个tetrimino,并可以将其添加到帧中。我只是不知道如何循环它,一旦那个形状停止移动,它就会在屏幕顶部添加另一个形状 这是一个预alpha构建,在它当前的实现中,我还没有添加碰撞检测、任何评分、背景、旋转形状的能力等等。我只是无法通过这个逻辑

我正在创建一个俄罗斯方块克隆作为个人项目,以帮助我更好地绘制图像,移动它们,并学习碰撞检测

一切都进行得很顺利,但当第一个物体停止移动时,让程序在画面上添加一个新的tetrimino形状背后的逻辑让我感到困惑。到目前为止,我使用一个随机数生成器随机创建一个tetrimino,并可以将其添加到帧中。我只是不知道如何循环它,一旦那个形状停止移动,它就会在屏幕顶部添加另一个形状

这是一个预alpha构建,在它当前的实现中,我还没有添加碰撞检测、任何评分、背景、旋转形状的能力等等。我只是无法通过这个逻辑障碍。请帮忙

一些代码:

    public class tetrisGame extends JFrame
{
    //Frame dimensions
    private static final int FRAME_WIDTH = 600;
    private static final int FRAME_HEIGHT = 600;

    private final int MAX_VALUE = 7; //RNG MAX VALUE
    private final int MIN_VALUE = 1; //RNG MIN VALUE
    private static int dy = 10;
    private static int dx = 0;

    private JLabel welcomeLabel, imageLabel, blankLabel, blankLabel2, creditsLabel1, creditsLabel2, creditsLabel3;
    private JButton startButton, creditsButton, exitButton, returnButton, leftButton, rightButton;
    private Shapes component; //Tetrimino Shape

    private JPanel totalGUI, buttonPanel, startPanel, creditsPanel, gamePanel, movePanel;

    public tetrisGame()
    {
        createComponents();
        setSize(FRAME_WIDTH, FRAME_HEIGHT);
        setTitle("Tetris");
    }

    //Moves tetrimino's down using a timer
    class TimerListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            component.moveRectangleBy(dx,dy);
        }
    }

    //Moves the tetrimino to the right 
    class moveRightListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            dy = 0;
            component.moveRectangleBy(dx+10,dy);
            dy = 10;
        }
    }

    //Moves the tetrimino to the left.
    class moveLeftListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            dy = 0;
            component.moveRectangleBy(dx-10,dy);
            dy = 10;
        }
    }

    //Executed when a new game is started.  The heart of the program.
    class newGameListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            int  randomNum = createRNG(MAX_VALUE, MIN_VALUE);

            if (randomNum == 1)
            {
                component = new SquareShape();
            }
            else if (randomNum == 2)
            {
                component = new RectangleShape();
            }
            else if (randomNum == 3)
            {
                component = new JShape();
            }
            else if (randomNum == 4)
            {
                component = new SShape();
            }
            else if (randomNum == 5)
            {
                component = new TShape();
            }
            else if (randomNum == 6)
            {
                component = new LShape();
            }
            else
            {
                component = new ZShape();
            }

            //Creates and starts timer that moves shapes
            int delay = 1000;
            ActionListener timerListener = new TimerListener();
            javax.swing.Timer t = new javax.swing.Timer(delay, timerListener);
            t.start();

            remove(totalGUI);
            add(component, BorderLayout.CENTER);
            add(movePanel, BorderLayout.SOUTH);
            repaint();
            revalidate();

        }   
    }

    //Adds components of the credit screen when button is pressed
    class creditsListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            totalGUI.remove(startPanel);
            totalGUI.add(creditsPanel);
            repaint();
            revalidate();
        }
    }

    //Exits the program
    class exitListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.exit(0);
        }
    }

    //returns to the main menu screen. 
    class returnListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            totalGUI.remove(creditsPanel);
            totalGUI.add(startPanel);
            repaint();
        }
    }

    //Creates all components of the GUI
    private void createComponents()
    {
        //Imports Tetris image
        try
        {
            String path = "http://static3.gamespot.com/uploads/screen_kubrick/1179/11799911/2550560-tetris.jpg";
            URL url = new URL(path);
            BufferedImage image = ImageIO.read(url);
            Image newImage = image.getScaledInstance(300,120,java.awt.Image.SCALE_SMOOTH);
            imageLabel = new JLabel(new ImageIcon(newImage));
        } catch(Exception e){}
        //Creates welcome prompt and new game buttons
        welcomeLabel = new JLabel("                                Welcome to Tetris!");
        Font boldFont = welcomeLabel.getFont();
        welcomeLabel.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        welcomeLabel.setForeground(Color.orange);
        blankLabel = new JLabel("");
        blankLabel2 = new JLabel("");
        startButton = new JButton("New Game");
        creditsButton = new JButton("Credits");
        exitButton = new JButton("Exit");

        //Adds action listeners to new game buttons
        ActionListener newGameListener = new newGameListener();
        startButton.addActionListener(newGameListener);
        ActionListener creditsListener = new creditsListener();
        creditsButton.addActionListener(creditsListener);
        ActionListener exitListener = new exitListener();
        exitButton.addActionListener(exitListener);

        //Adds new game buttons to panel
        buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(6,1));
        buttonPanel.setBackground(Color.black);
        buttonPanel.add(blankLabel);
        buttonPanel.add(blankLabel2);
        buttonPanel.add(welcomeLabel);
        buttonPanel.add(startButton);
        buttonPanel.add(creditsButton);
        buttonPanel.add(exitButton);

        //Buttons that move the tetrimino's
        leftButton = new JButton("<--");
        ActionListener leftListener = new moveLeftListener();
        leftButton.addActionListener(leftListener);
        rightButton = new JButton("-->");
        ActionListener rightListener = new moveRightListener();
        rightButton.addActionListener(rightListener);
        //Panel that contains movement buttons
        movePanel = new JPanel();
        movePanel.add(leftButton);
        movePanel.add(rightButton);

        //Continue to add elements to panel
        startPanel = new JPanel();
        startPanel.setLayout(new BorderLayout());
        startPanel.add(imageLabel, BorderLayout.NORTH);
        startPanel.add(buttonPanel, BorderLayout.CENTER);

        //Create elements of credits screen
        creditsLabel1 = new JLabel("The Tetris logo, block shapes, and dimensions are registered trademarks of The Tetris Company.");
        creditsLabel1.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        creditsLabel1.setForeground(Color.orange);
        creditsLabel2 = new JLabel("                   This product is an academic work intended for individual use only.");
        creditsLabel2.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        creditsLabel2.setForeground(Color.orange);
        creditsLabel3 = new JLabel("                         All programming written in the Java language by NAME REMOVED.");
        creditsLabel3.setFont(boldFont.deriveFont(boldFont.getStyle() ^ Font.BOLD));
        creditsLabel3.setForeground(Color.orange);
        returnButton = new JButton("Return");
        ActionListener returnListener = new returnListener();
        returnButton.addActionListener(returnListener);
        creditsPanel = new JPanel();
        creditsPanel.setLayout(new GridLayout(5,1));
        creditsPanel.setBackground(Color.black);
        creditsPanel.add(creditsLabel1);
        creditsPanel.add(creditsLabel2);
        creditsPanel.add(blankLabel);
        creditsPanel.add(creditsLabel3);
        creditsPanel.add(returnButton);

        //Initial game panel
        totalGUI = new JPanel();
        totalGUI.add(startPanel);
        totalGUI.setBackground(Color.black);

        add(totalGUI, BorderLayout.CENTER);
    }

    //generates a random number.
    private int createRNG(int MAX_VALUE, int MIN_VALUE)
    {
        Random rand = new Random();
        int randomNum = rand.nextInt(MAX_VALUE - MIN_VALUE + 1) + MIN_VALUE;

        return randomNum;
    }
}
公共类tetrisGame扩展JFrame
{
//框架尺寸
专用静态最终整数帧_宽度=600;
专用静态最终整型框架高度=600;
私有最终整数最大值=7;//RNG最大值
私有最终整数最小值=1;//RNG最小值
私有静态int dy=10;
私有静态int dx=0;
私人JLabel welcomeLabel、imageLabel、blankLabel、blankLabel2、creditsLabel1、creditsLabel2、creditsLabel3;
私有JButton开始按钮、信用按钮、退出按钮、返回按钮、左按钮、右按钮;
私有形状组件;//Tetrimino形状
私有JPanel totalGUI、buttonPanel、startPanel、creditsPanel、gamePanel、movePanel;
公共俄罗斯方块游戏()
{
createComponents();
设置尺寸(框宽、框高);
setTitle(“俄罗斯方块”);
}
//用定时器把提特里米诺的手放下
类TimerListener实现ActionListener
{
已执行的公共无效操作(操作事件e)
{
组件。移动矩形比(dx,dy);
}
}
//将tetrimino移动到右侧
类moveRightListener实现ActionListener
{
已执行的公共无效操作(操作事件e)
{
dy=0;
组件。移动矩形(dx+10,dy);
dy=10;
}
}
//将tetrimino移动到左侧。
类moveLeftListener实现ActionListener
{
已执行的公共无效操作(操作事件e)
{
dy=0;
组件。移动矩形(dx-10,dy);
dy=10;
}
}
//在新游戏开始时执行。程序的核心。
类newGameListener实现ActionListener
{
已执行的公共无效操作(操作事件e)
{
int randomNum=createRNG(最大值,最小值);
if(randomNum==1)
{
组件=新的方形形状();
}
else if(randomNum==2)
{
组件=新矩形形状();
}
else if(randomNum==3)
{
组件=新的JShape();
}
else if(randomNum==4)
{
组件=新的形状();
}
else if(randomNum==5)
{
组件=新的TShape();
}
else if(randomNum==6)
{
组件=新的LShape();
}
其他的
{
组件=新ZShape();
}
//创建并启动移动形状的计时器
int延迟=1000;
ActionListener timerListener=新timerListener();
javax.swing.Timer t=新的javax.swing.Timer(延迟,timerListener);
t、 start();
移除(totalGUI);
添加(组件、边框布局、中心);
添加(movePanel,BorderLayout.SOUTH);
重新油漆();
重新验证();
}   
}
//按下按钮时添加信用屏幕的组件
类creditsListener实现ActionListener
{
已执行的公共无效操作(操作事件e)
{
totalGUI.remove(startPanel);
totalGUI.add(creditsPanel);
重新油漆();
重新验证();
}
}
//退出程序
类exitListener实现ActionListener
{
已执行的公共无效操作(操作事件e)
{
系统出口(0);
}
}
//返回主菜单屏幕。
类returnListener实现ActionListener
{
已执行的公共无效操作(操作事件e)
{
totalGUI.remove(creditsPanel);
添加(startPanel);
重新油漆();
}
}
//创建GUI的所有组件
私有void createComponents()
{
//导入俄罗斯方块图像
尝试
{
字符串路径=”http://static3.gamespot.com/uploads/screen_kubrick/1179/11799911/2550560-tetris.jpg";
URL=新URL(路径);
BuffereImage image=ImageIO.read(url);
Image newImage=Image.getScaledInstance(300120,java.awt.Image.SCALE\u-SMOOTH);
imageLabel=newjLabel(newImageIcon(newImage));
}捕获(例外e){}
//创建欢迎提示和新游戏按钮
welcomeLabel=new JLabel(“欢迎来到俄罗斯方块!”);
Font boldFont=welcomeLabel.getFont();
welcomeLabel.setFont(boldFont.deriveFont(boldFont.getStyle()^Font.BOLD));
welcomeLabel.setForeground(颜色为橙色);
blankLabel=新的JLabel(“”);
blankLabel2=新的JLabel(“”);
startButton=新的JButton(“新游戏”);
creditsButton=新的JButton(“Credits”);
exitButton=新JButton(“退出”);
//将动作侦听器添加到新游戏按钮
ActionListener newGameListener=new newGameListener();
addActionListener(newGameListener);
ActionListener creditsListener=新的creditsListener();
creditsButton.addActionListen
public class SquareShape extends Shapes
{
    private static final int RECTANGLE_WIDTH = 40;
    private static final int RECTANGLE_HEIGHT = 40;

    private int xLeft;
    private int yTop;
    boolean stopped = false;

    public SquareShape()
    {
        xLeft = 280;
        yTop = 0;
    }

    public void paintComponent(Graphics g)
    {
        //draws 1 large square
        g.setColor(Color.cyan);
        g.fillRect(xLeft,yTop,RECTANGLE_WIDTH,RECTANGLE_HEIGHT);

        //Divides the square into parts
        g.setColor(Color.black);
        g.drawLine(xLeft,yTop,xLeft+40,yTop);
        g.drawLine(xLeft,yTop,xLeft,yTop+40);
        g.drawLine(xLeft,yTop+40,xLeft+40,yTop+40);
        g.drawLine(xLeft+40,yTop+40,xLeft+40,yTop);
        g.drawLine(xLeft,yTop+20,xLeft+40,yTop+20);
        g.drawLine(xLeft+20,yTop,xLeft+20,yTop+40);        
    }

    public void moveRectangleBy(int dx, int dy)
    { 
        if (yTop < 450)
        {
            xLeft += dx;
            yTop += dy;
            if (xLeft < 0)
            {
                xLeft = 0;
            }
            if (xLeft > 500)
            {
                xLeft = 500;
            }
        }
        repaint();
    }


}
component.moveRectangleBy(dx,dy);
if (component == null)
    component = // a new random shape
else
{
    component.moveRectangleBy(...);

    if (component.isAtBottom()) // a method you will need to write
        component == null;
}
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.awt.geom.*;

public class Tetris extends JPanel
{
    private final static int TETRIS_ICON_SIZE = 20;

    private List<TetrisPiece> tetrisPieces = new ArrayList<TetrisPiece>();
    private TetrisBoard board;
    private Random random = new Random();

    public Tetris()
    {
        setLayout( new BorderLayout() );

        createTetrisPieces();

        board = new TetrisBoard(20, 10, 20);
        add(board, BorderLayout.LINE_START);
/*
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 5, 5);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 5, 6);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 6, 5);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 0, 0);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 0, 19);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 9, 0);
        board.setTetrisIconAt(new TetrisIcon(Color.RED, TETRIS_ICON_SIZE), 9, 19);

        board.setTetrisPiece( tetrisPieces.get(1) );
*/
        JButton start = new JButton( new StartAction() );
        add(start, BorderLayout.PAGE_END);
    }

    private void createTetrisPieces()
    {
        int[][] shape =
        {
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.RED, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.YELLOW, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 1, 0},
            {0, 0, 1, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.MAGENTA, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {0, 1, 1, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.CYAN, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {0, 1, 0, 0},
            {1, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.WHITE, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {0, 1, 1, 0},
            {1, 1, 0, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.BLUE, TETRIS_ICON_SIZE)) );

        shape = new int[][]
        {
            {0, 0, 0, 0},
            {1, 1, 0, 0},
            {0, 1, 1, 0},
            {0, 0, 0, 0}
        };

        tetrisPieces.add( new TetrisPiece(shape, new TetrisIcon(Color.GREEN, TETRIS_ICON_SIZE)) );
    }

    class StartAction extends AbstractAction
    {
        public StartAction()
        {
            super("Start Game");
        }

        @Override
        public void actionPerformed(ActionEvent e)
        {
            new Timer(1000, new AbstractAction()
            {
                @Override
                public void actionPerformed(ActionEvent e2)
                {
                    if (board.getTetrisPiece() == null)
                    {
                        int piece = random.nextInt( tetrisPieces.size() );
                        board.setTetrisPiece( tetrisPieces.get( piece ) );
                    }
                    else
                    {
                        board.moveShapeDown();
                    }
                }
            }).start();
        }
    }


    private static void createAndShowGUI()
    {

        JFrame frame = new JFrame("Tetris");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Tetris());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;

class TetrisBoard extends JPanel
{
    private List<TetrisIcon[]> board;

    private int rows;
    private int columns;
    private int size;

    private TetrisPiece tetrisPiece;

    public TetrisBoard(int rows, int columns, int size)
    {
        this.rows = rows;
        this.columns = columns;
        this.size = size;

        board = new ArrayList<TetrisIcon[]>(rows);

        for (int i = 0; i < rows; i++)
            board.add( new TetrisIcon[columns] );

        setBackground( Color.BLACK );

        addKeyBindings();
    }

    private void addKeyBindings()
    {
        InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = getActionMap();

        String leftName = "LEFT";
        KeyStroke leftKeyStroke = KeyStroke.getKeyStroke( leftName );
        inputMap.put(leftKeyStroke, leftName);
        actionMap.put(leftName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                moveShapeLeft();
            }
        });

        String rightName = "RIGHT";
        KeyStroke rightKeyStroke = KeyStroke.getKeyStroke( rightName );
        inputMap.put(rightKeyStroke, rightName);
        actionMap.put(rightName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                moveShapeRight();
            }
        });

        String downName = "DOWN";
        KeyStroke downKeyStroke = KeyStroke.getKeyStroke( downName );
        inputMap.put(downKeyStroke, downName);
        actionMap.put(downName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
//              moveShapeDown();
                dropShape();
            }
        });

        String upName = "UP";
        KeyStroke upKeyStroke = KeyStroke.getKeyStroke( upName );
        inputMap.put(upKeyStroke, upName);
        actionMap.put(upName, new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                rotateShape();
            }
        });
    }

    public TetrisPiece getTetrisPiece()
    {
        return tetrisPiece;
    }

    public void setTetrisPiece(TetrisPiece tetrisPiece)
    {
        this.tetrisPiece = new TetrisPiece(tetrisPiece.getShape(), tetrisPiece.getIcon());
        this.tetrisPiece.setLocation( new Point(4, 0) );
        repaint();
    }

    public void setTetrisIconAt(TetrisIcon icon, int x, int y)
    {
        TetrisIcon[] row = board.get(y);
        row[x] = icon;
    }

    public TetrisIcon getTetrisIconAt(int x, int y)
    {
        TetrisIcon[] row = board.get(y);

        return row[x];
    }

    public void moveShapeLeft()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX() - 1, tetrisPiece.getY());

        if ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            tetrisPiece.setLocation( possibleLocation );
            repaint();
        }
    }

    public void moveShapeRight()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX() + 1, tetrisPiece.getY());

        if ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            tetrisPiece.setLocation( possibleLocation );
            repaint();
        }
    }

    public void dropShape()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX(), tetrisPiece.getY() + 1);

        while ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            moveShapeDown();
            possibleLocation = new Point(tetrisPiece.getX(), tetrisPiece.getY() + 1);
        }

//      addTetrisPieceToBoard();
//      tetrisPiece = null;
    }

    public void moveShapeDown()
    {
        if (tetrisPiece == null) return;

        Point possibleLocation = new Point(tetrisPiece.getX(), tetrisPiece.getY() + 1);

        if ( canMoveShape(possibleLocation, tetrisPiece.getShape()) )
        {
            tetrisPiece.setLocation( possibleLocation );
            repaint();
        }
        else
        {
            tetrisPieceAtBottom();
        }
    }

    private void tetrisPieceAtBottom()
    {
        Point location = tetrisPiece.getLocation();
        int row = Math.min(rows, location.y + 4);
        row--;

        addTetrisPieceToBoard();

        int rowsRemoved = 0;


        for (; row >= location.y; row--)
        {
//          System.out.println(row);
            TetrisIcon[] icons = board.get(row);

            if ( fullRow(row) )
            {
                board.remove(row);
                rowsRemoved++;
            }
        }

        for (int i = 0; i < rowsRemoved; i++)
            board.add(0, new TetrisIcon[columns]);

        if (rowsRemoved > 0)
            repaint();
    }

    private boolean fullRow(int row)
    {
        for (int column = 0; column < columns; column++)
        {
//          System.out.println(row + " : " + column);
            if ( getTetrisIconAt(column, row) == null)
                return false;
        }

        return true;
    }

    private void addTetrisPieceToBoard()
    {
        int x = tetrisPiece.getX();
        int y = tetrisPiece.getY();

        for (int r = 0; r < tetrisPiece.getRows(); r++)
        {
            for (int c = 0; c < tetrisPiece.getColumns(); c++)
            {
                TetrisIcon icon = tetrisPiece.getIconAt(r, c);

                if (icon != null)
                {
                    setTetrisIconAt(icon, x, y);
                }

                x++;
            }

            x = tetrisPiece.getX();
            y++;
        }

        tetrisPiece = null;
    }

    public void rotateShape()
    {
        if (tetrisPiece == null) return;

        int[][] rotatedShape = tetrisPiece.getRotatedShape();

        if ( canMoveShape(tetrisPiece.getLocation(), rotatedShape) )
        {
            tetrisPiece.setShape( rotatedShape );
            repaint();
        }
    }

    private boolean canMoveShape(Point location, int[][] shape)
    {
        for (int r = 0; r < shape.length; r ++)
        {
            for (int c = 0; c < shape.length; c++)
            {
                if (shape[r][c] == 1)
                {
                    int x = location.x + c;
                    int y = location.y + r;

                    //  Past left edge

                    if (x < 0) return false;

                    //  Past right edge

                    if (x >= columns) return false;

                    //  Past bottom edge

                    if (y >= rows) return false;

                    //  Collision with TetrisIcon

                    if (getTetrisIconAt(x, y) != null) return false;
                }
            }
        }

        return true;
    }

    @Override
    public Dimension getPreferredSize()
    {
        int width = (columns * size) + columns - 1;
        int height = (rows * size) + rows - 1;

        return new Dimension(width, height);
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent( g );

        int x = 0;
        int y = 0;
        int offset = size + 1;

        for (int r = 0; r < rows; r++)
        {
            TetrisIcon[] row = board.get(r);

            for (int c = 0; c < row.length; c++)
            {
                TetrisIcon icon = row[c];

                if (icon != null)
                {
                    icon.paintIcon(this, g, x, y);
                }

                x += offset;
            }

            x = 0;
            y += offset;
        }

        // paint shape

        if (tetrisPiece != null)
        {
            paintShape(g, offset);
        }
    }

    private void paintShape(Graphics g, int offset)
    {
        int x = tetrisPiece.getX() * offset;
        int y = tetrisPiece.getY() * offset;

        for (int r = 0; r < tetrisPiece.getRows(); r++)
        {
            for (int c = 0; c < tetrisPiece.getColumns(); c++)
            {
                TetrisIcon icon = tetrisPiece.getIconAt(r, c);

                if (icon != null)
                {
                    icon.paintIcon(this, g, x, y);
                }

                x += offset;
            }

            x = tetrisPiece.getX() * offset;
            y += offset;
        }
    }
}
import java.awt.Point;

public class TetrisPiece
{
    private int[][] shape;
    private TetrisIcon icon;
    private Point location = new Point();

    public TetrisPiece(int[][] shape, TetrisIcon icon)
    {
        setShape(shape);
        this.icon = icon;
    }

    public TetrisIcon getIcon()
    {
        return icon;
    }

    public int[][] getShape()
    {
        return shape;
    }

    public void setShape(int[][] shape)
    {
        this.shape = shape;
    }

    public TetrisIcon getIconAt(int x, int y)
    {
        return  (shape[x][y] == 1) ? icon : null;
    }

    public Point getLocation()
    {
        return location;
    }

    public void setLocation(Point location)
    {
        this.location = location;
    }

    public int getX()
    {
        return location.x;
    }

    public int getY()
    {
        return location.y;
    }

    public int getRows()
    {
        return shape.length;
    }

    public int getColumns()
    {
        return shape[0].length;
    }

    public int[][] getRotatedShape()
    {
        int[][] rotatedShape = new int[shape.length][shape[0].length];

        int x = 0;
        int y = 0;

        for (int c = shape.length - 1; c >= 0; c--)
        {
            for (int r = 0; r < shape[0].length; r++)
            {
                rotatedShape[x][y] = shape[r][c];
                y++;
            }

            x++;
            y = 0;
        }

        return rotatedShape;
    }

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

public class TetrisIcon implements Icon
{
    private Color color;
    private int size;

    public TetrisIcon(Color color, int size)
    {
        this.color = color;
        this.size = size;
    }

    public int getIconWidth()
    {
        return size;
    }

    public int getIconHeight()
    {
        return size;
    }

    public void paintIcon(Component c, Graphics g, int x, int y)
    {
        int width = getIconWidth() - 1;
        int height = getIconHeight() - 1;

        g.translate(x, y);

        g.setColor(color);
        g.fillRect(0, 0, width, height);

        g.setColor(Color.LIGHT_GRAY);
        g.drawLine(0, 0, width, 0);
        g.drawLine(0, 0, 0, height);

        g.setColor(Color.DARK_GRAY);
        g.drawLine(width, 0, width, height);
        g.drawLine(0, height, width, height);

        g.translate(-x, -y);
    }
}