{"id":88098,"date":"2023-07-24T19:09:10","date_gmt":"2023-07-24T13:39:10","guid":{"rendered":"https:\/\/techvidvan.com\/tutorials\/?p=88098"},"modified":"2026-06-03T15:03:35","modified_gmt":"2026-06-03T09:33:35","slug":"java-tetris-game","status":"publish","type":"post","link":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/","title":{"rendered":"Java Tetris Game &#8211; Thrilling Blocks &amp; Endless Joy!"},"content":{"rendered":"<p>A well-known game&#8217;s Java adaptation is the Tetris game project. It demonstrates how to develop a graphical user interface using the AWT and Swing libraries. Players must arrange falling blocks to form entire lines in order to win the game. The project presents key ideas in Java GUI programming and game creation.<\/p>\n<h3>About Java Tetris Game<\/h3>\n<ul>\n<li>The objective of the game is to arrange falling Tetriminoes (block shapes) to create horizontal lines without any gaps.<\/li>\n<li>When a complete line is formed, it clears from the board, and you earn points.<\/li>\n<li>If the stack of Tetriminoes reaches the top of the board, the game ends.<\/li>\n<li>The goal is to achieve the highest score possible by clearing lines and surviving as long as you can.<\/li>\n<li>The user can use the left and right keys to move the Tetriminoes left and right. The upward key can be used to rotate the shape, and the downward key helps in dropping the Tetrominoes faster.<\/li>\n<\/ul>\n<h3>Prerequisites For Tetris Game Using Java<\/h3>\n<ul>\n<li>IDE Used: IntelliJ<\/li>\n<li>Java 1.8 or above must be installed.<\/li>\n<\/ul>\n<h3>Download Java Tetris Game Project<\/h3>\n<p>Please download the source code of the Java Tetris Game Project from the following link: <a href=\"https:\/\/drive.google.com\/file\/d\/1zQnN5SpQ5g-aLcii0kt-bqsVbXhR38rw\/view?usp=drive_link\"><strong>Java<\/strong> <strong>Tetris Game Project Code.<\/strong><\/a><\/p>\n<h3>Steps to Create Tetris Game in Java:<\/h3>\n<ul>\n<li>Initial Setup.<\/li>\n<li>Creating the Game Board<\/li>\n<li>Implementing the Tetromino Shapes<\/li>\n<li>Handling User Input<\/li>\n<li>Game Logic and State Updation<\/li>\n<li>Drawing the Game Components<\/li>\n<li>Testing the game<\/li>\n<\/ul>\n<h4>1. Initial SetUp:<\/h4>\n<p>This step involves the initialization of the game and setting up the necessary libraries required for the respective development. The imported packages are \u2018java.awt\u2019 and \u2018javax.swing\u2019 for the GUI implementation.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">import java.awt.*;\r\nimport java.awt.event.*;\r\nimport javax.swing.*;<\/pre>\n<h4>2. Creating the Game Board:<\/h4>\n<p>This step involves the definition of the main class \u2018Tetris\u2019 that extends \u2018JPanel\u2019 to create a game panel. The basic elements, like the game board and the GUI components, like- buttons and labels, are set up inside this main class.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public Tetris() {\r\n    initBoard();\r\n}\r\n\r\nprivate void initBoard() {\r\n    setFocusable(true);\r\n    addKeyListener(new TAdapter());\r\n    setBackground(Color.BLACK);\r\n    curPiece = new Shape();\r\n    timer = new Timer(INITIAL_DELAY, new GameCycle());\r\n    board = new Tetrominoe[BOARD_WIDTH][BOARD_HEIGHT];\r\n    clearBoard();\r\n\r\n    \/\/ Designing the Game Over Label\r\n    gameOverLabel = new JLabel(\"Game Over\");\r\n    gameOverLabel.setForeground(Color.RED);\r\n    gameOverLabel.setFont(new Font(\"SansSerif\", Font.BOLD, 36));\r\n    gameOverLabel.setBounds(50, 230, 200, 50);\r\n    gameOverLabel.setVisible(false);\r\n    add(gameOverLabel);\r\n\r\n    \/\/ Designing the START Button\r\n    startButton = new JButton(\"Start\");\r\n    startButton.setBackground(Color.ORANGE);\r\n    startButton.setOpaque(true);\r\n    startButton.addActionListener(new ActionListener() {\r\n        public void actionPerformed(ActionEvent e) {\r\n            if (isStarted) {\r\n                restart();\r\n            } else {\r\n                start();\r\n            }\r\n        }\r\n    });\r\n    setLayout(null);\r\n    startButton.setBounds(0, 560, 300, 30);\r\n    add(startButton);\r\n}\r\n\r\n@Override\r\npublic Dimension getPreferredSize() {\r\n    return new Dimension(BOARD_WIDTH * SQUARE_SIZE, BOARD_HEIGHT * SQUARE_SIZE + 40);\r\n}\r\n\r\n\/\/ Helper methods for square dimensions\r\nprivate int squareWidth() {\r\n    return getWidth() \/ BOARD_WIDTH;\r\n}\r\n\r\nprivate int squareHeight() {\r\n    return getHeight() \/ BOARD_HEIGHT;\r\n}\r\n\r\n\/\/ Get the Tetrominoe shape at a specific position on the board\r\nprivate Tetrominoe shapeAt(int x, int y) {\r\n    return board[x][y];\r\n}<\/pre>\n<h4>3. Implementing the Tetriminoe Shapes:<\/h4>\n<p>This step basically creates the class \u2018Shapes\u2019 to represent the Tetriminoe shapes.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">import java.util.Random;\r\n\r\npublic class Shape {\r\n    private Tetrominoe pieceShape;     \/\/ Represents the type of Tetrominoe shape of the piece.\r\n    private int[][] coordinates;       \/\/ Stores the x and y coordinates of each block in the piece.\r\n\r\n    public Shape() {\r\n        coordinates = new int[4][2];   \/\/ Initialize the coordinates array with 4 rows and 2 columns.\r\n        setShape(Tetrominoe.NoShape);  \/\/ Set the initial shape to NoShape.\r\n    }\r\n\r\n    public void setShape(Tetrominoe shape) {\r\n        int[][][] coordsTable = new int[][][] {\r\n                {{0, 0}, {0, 0}, {0, 0}, {0, 0}},             \/\/ NoShape\r\n                {{0, -1}, {0, 0}, {-1, 0}, {-1, 1}},         \/\/ ZShape\r\n                {{0, -1}, {0, 0}, {1, 0}, {1, 1}},           \/\/ SShape\r\n                {{0, -1}, {0, 0}, {0, 1}, {0, 2}},           \/\/ LineShape\r\n                {{-1, 0}, {0, 0}, {1, 0}, {0, 1}},           \/\/ TShape\r\n                {{0, 0}, {1, 0}, {0, 1}, {1, 1}},             \/\/ SquareShape\r\n                {{-1, -1}, {0, -1}, {0, 0}, {0, 1}},         \/\/ LShape\r\n                {{1, -1}, {0, -1}, {0, 0}, {0, 1}}           \/\/ MirroredLShape\r\n        };\r\n\r\n        \/\/ Copy the coordinates from the lookup table for the given shape.\r\n        for (int i = 0; i &lt; 4; i++) {\r\n            for (int j = 0; j &lt; 2; ++j) {\r\n                coordinates[i][j] = coordsTable[shape.ordinal()][i][j];\r\n            }\r\n        }\r\n        pieceShape = shape;   \/\/ Set the piece shape.\r\n    }\r\n\r\n    private void setX(int index, int x) {\r\n        coordinates[index][0] = x;   \/\/ Set the x-coordinate of the block at the given index.\r\n    }\r\n\r\n    private void setY(int index, int y) {\r\n        coordinates[index][1] = y;   \/\/ Set the y-coordinate of the block at the given index.\r\n    }\r\n\r\n    public int x(int index) {\r\n        return coordinates[index][0];   \/\/ Get the x-coordinate of the block at the given index.\r\n    }\r\n\r\n    public int y(int index) {\r\n        return coordinates[index][1];   \/\/ Get the y-coordinate of the block at the given index.\r\n    }\r\n\r\n    public Tetrominoe getShape() {\r\n        return pieceShape;   \/\/ Get the shape of the piece.\r\n    }\r\n\r\n    public void setRandomShape() {\r\n        Random rand = new Random();\r\n        int x = Math.abs(rand.nextInt()) % 7 + 1;\r\n        Tetrominoe[] values = Tetrominoe.values();\r\n        setShape(values[x]);   \/\/ Set the shape of the piece to a random shape.\r\n    }\r\n\r\n    public int minY() {\r\n        int minY = coordinates[0][1];\r\n        for (int i = 0; i &lt; 4; i++) {\r\n            minY = Math.min(minY, coordinates[i][1]);   \/\/ Find the minimum y-coordinate of the piece.\r\n        }\r\n        return minY;\r\n    }\r\n\r\n    public Shape rotateLeft() {\r\n        if (pieceShape == Tetrominoe.SquareShape) {\r\n            return this;   \/\/ Square shape does not change when rotated, so return the current instance.\r\n        }\r\n        Shape rotatedShape = new Shape();   \/\/ Create a new Shape instance for the rotated shape.\r\n        rotatedShape.pieceShape = pieceShape;   \/\/ Set the shape of the rotated piece.\r\n\r\n        \/\/ Perform rotation calculations for each block.\r\n        for (int i = 0; i &lt; 4; ++i) {\r\n            rotatedShape.setX(i, y(i));\r\n            rotatedShape.setY(i, -x(i));\r\n        }\r\n\r\n        return rotatedShape;   \/\/ Return the rotated shape.\r\n    }\r\n\r\n    public Shape rotateRight() {\r\n        if (pieceShape == Tetrominoe.SquareShape) {\r\n            return this;   \/\/ Square shape does not change when rotated, so return the current instance.\r\n        }\r\n        Shape rotatedShape = new Shape();   \/\/ Create a new Shape instance for the rotated shape.\r\n        rotatedShape.pieceShape = pieceShape;   \/\/ Set the shape of the rotated piece.\r\n\r\n        \/\/ Perform rotation calculations for each block.\r\n        for (int i = 0; i &lt; 4; ++i) {\r\n            rotatedShape.setX(i, -y(i));\r\n            rotatedShape.setY(i, x(i));\r\n        }\r\n\r\n        return rotatedShape;   \/\/ Return the rotated shape.\r\n    }\r\n}<\/pre>\n<p>Enum named \u2018Tetriminoe\u2019 has also been created to provide color to the shapes.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">import java.awt.*;\r\n\r\npublic enum Tetrominoe {\r\n    NoShape, ZShape, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape;\r\n\r\n    \/\/ Define the color associated with each shape\r\n    private final Color[] shapeColors = {\r\n            Color.BLACK,           \/\/ NoShape (Empty)\r\n            new Color(204, 102, 102),  \/\/ ZShape\r\n            new Color(102, 204, 102),  \/\/ SShape\r\n            new Color(102, 102, 204),  \/\/ LineShape\r\n            new Color(204, 204, 102),  \/\/ TShape\r\n            new Color(204, 102, 204),  \/\/ SquareShape\r\n            new Color(102, 204, 204),  \/\/ LShape\r\n            new Color(218, 170, 0)     \/\/ MirroredLShape\r\n    };\r\n\r\n    \/\/ Get the color associated with the shape\r\n    public Color getColor() {\r\n        return shapeColors[this.ordinal()];\r\n    }\r\n}<\/pre>\n<h4>4. Handling User Input:<\/h4>\n<p>This step basically creates an event listener using the \u2018TAdapter\u2019 class. Handling of the key presses for movement of the shapes and pause functionality of the game is managed under this step.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\/\/ Handle keyboard input\r\nprivate class TAdapter extends KeyAdapter {\r\n    @Override\r\n    public void keyPressed(KeyEvent e) {\r\n        if (!isStarted || curPiece.getShape() == Tetrominoe.NoShape) {\r\n            return;\r\n        }\r\n        int keycode = e.getKeyCode();\r\n        if (keycode == 'p' || keycode == 'P') {\r\n            pause();\r\n        }\r\n        if (isPaused) {\r\n            return;\r\n        }\r\n        switch (keycode) {\r\n            case KeyEvent.VK_LEFT:\r\n                tryMove(curPiece, curX - 1, curY);\r\n                break;\r\n            case KeyEvent.VK_RIGHT:\r\n                tryMove(curPiece, curX + 1, curY);\r\n                break;\r\n            case KeyEvent.VK_DOWN:\r\n                tryMove(curPiece, curX, curY - 1); \/\/ Move the piece one line down\r\n                break;\r\n            case KeyEvent.VK_UP:\r\n                tryMove(curPiece.rotateLeft(), curX, curY);\r\n                break;\r\n            case KeyEvent.VK_SPACE:\r\n                dropShape();\r\n                break;\r\n        }\r\n    }\r\n}\r\n\r\n\/\/ Game cycle timer\r\nprivate class GameCycle implements ActionListener {\r\n    @Override\r\n    public void actionPerformed(ActionEvent e) {\r\n        gameCycle();\r\n    }\r\n}<\/pre>\n<h4>5. Game Logic and State Updation:<\/h4>\n<p>The game starts from this step. Here we have three basic methods to control the game state: \u2018start\u2019, \u2018restart\u2019 and \u2018pause\u2019.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\/\/ Start the game\r\nprivate void start() {\r\n    if (isPaused) {\r\n        return;\r\n    }\r\n    isStarted = true;\r\n    startButton.setVisible(false);\r\n    isFallingFinished = false;\r\n    numLinesRemoved = 0;\r\n    clearBoard();\r\n    newPiece();\r\n    timer.start();\r\n    startButton.setEnabled(false);\r\n    gameOverLabel.setVisible(false); \/\/ Reset the game over label\r\n    requestFocus();\r\n}\r\n\r\n\/\/ Restart the game\r\nprivate void restart() {\r\n    isStarted = false;\r\n    isFallingFinished = false;\r\n    isPaused = false;\r\n    numLinesRemoved = 0;\r\n    clearBoard();\r\n    startButton.setEnabled(true);\r\n    gameOverLabel.setVisible(false); \/\/ Reset the game over label\r\n    repaint();\r\n}\r\n\r\n\/\/ Pause or resume the game\r\nprivate void pause() {\r\n    if (!isStarted) {\r\n        return;\r\n    }\r\n    isPaused = !isPaused;\r\n    if (isPaused) {\r\n        timer.stop();\r\n    } else {\r\n        timer.start();\r\n    }\r\n    repaint();\r\n}<\/pre>\n<p>This step also handles all the implementation and updation of the game like, implementing a timer cycle (\u2018gameCycle\u2019), moving shapes (\u2018oneLineDown\u2019, \u2018dropShape\u2019, \u2018pieceDropped\u2019, \u2018tryMove\u2019), line clearings ( \u2018removeFullLines\u2019 ), creating new shapes (\u2018newPiece\u2019 ) and managing gameover condition (\u2018update\u2019).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\/\/ Move the current piece one line down\r\nprivate void oneLineDown() {\r\n    if (!tryMove(curPiece, curX, curY - 1)) {\r\n        pieceDropped();\r\n    }\r\n}\r\n\r\n\/\/ Drop the current piece to the bottom\r\nprivate void dropShape() {\r\n    int newY = curY;\r\n    while (newY &gt; 0) {\r\n        if (!tryMove(curPiece, curX, newY - 1)) {\r\n            break;\r\n        }\r\n        newY--;\r\n    }\r\n    pieceDropped();\r\n}\r\n\r\n\/\/ Place the dropped piece on the board\r\nprivate void pieceDropped() {\r\n    for (int i = 0; i &lt; 4; i++) {\r\n        int x = curX + curPiece.x(i);\r\n        int y = curY - curPiece.y(i);\r\n        board[x][y] = curPiece.getShape();\r\n    }\r\n    removeFullLines();\r\n    if (!isFallingFinished) {\r\n        newPiece();\r\n    }\r\n}\r\n\r\n\/\/ Remove full lines from the board and update the score\r\nprivate void removeFullLines() {\r\n    int numFullLines = 0;\r\n    for (int i = BOARD_HEIGHT - 1; i &gt;= 0; i--) {\r\n        boolean lineIsFull = true;\r\n        for (int j = 0; j &lt; BOARD_WIDTH; j++) {\r\n            if (shapeAt(j, i) == Tetrominoe.NoShape) {\r\n                lineIsFull = false;\r\n                break;\r\n            }\r\n        }\r\n        if (lineIsFull) {\r\n            numFullLines++;\r\n            for (int k = i; k &lt; BOARD_HEIGHT - 1; k++) {\r\n                for (int j = 0; j &lt; BOARD_WIDTH; j++) {\r\n                    board[j][k] = shapeAt(j, k + 1);\r\n                }\r\n            }\r\n        }\r\n    }\r\n    if (numFullLines &gt; 0) {\r\n        numLinesRemoved += numFullLines;\r\n        isFallingFinished = true;\r\n        curPiece.setShape(Tetrominoe.NoShape);\r\n        repaint();\r\n    }\r\n}\r\n\r\n\/\/ Generate a new random piece\r\nprivate void newPiece() {\r\n    curPiece.setRandomShape();\r\n    curX = BOARD_WIDTH \/ 2 - 1;\r\n    curY = BOARD_HEIGHT - 1 + curPiece.minY();\r\n\r\n    if (!tryMove(curPiece, curX, curY)) {\r\n        curPiece.setShape(Tetrominoe.NoShape);\r\n        timer.stop();\r\n        isStarted = false;\r\n        startButton.setEnabled(true);\r\n        gameOverLabel.setVisible(true);\r\n        startButton.setVisible(true);\r\n    }\r\n}\r\n\r\n\/\/ Try to move the current piece to a new position\r\nprivate boolean tryMove(Shape newPiece, int newX, int newY) {\r\n    for (int i = 0; i &lt; 4; i++) {\r\n        int x = newX + newPiece.x(i);\r\n        int y = newY - newPiece.y(i);\r\n        if (x &lt; 0 || x &gt;= BOARD_WIDTH || y &lt; 0 || y &gt;= BOARD_HEIGHT || shapeAt(x, y) != Tetrominoe.NoShape) {\r\n            return false;\r\n        }\r\n    }\r\n    curPiece = newPiece;\r\n    curX = newX;\r\n    curY = newY;\r\n    repaint();\r\n    return true;\r\n}\r\n\/\/ Update the game state\r\nprivate void gameCycle() {\r\n    update();\r\n    repaint();\r\n}\r\n\r\n\r\n\/\/ Update the game state\r\nprivate void update() {\r\n    if (isFallingFinished) {\r\n        isFallingFinished = false;\r\n        newPiece();\r\n    } else {\r\n        oneLineDown();\r\n    }\r\n}<\/pre>\n<h4>6. Drawing the Game Components:<\/h4>\n<p>This step involves the drawing and display of the game board and its components like grid lines, occupied squares, score and lines cleared display, etc. The doDrawing method manages colors and rendering, using the drawSquare method to draw each square with its associated color. It sets rendering hints for smooth graphics and creates a grid structure with vertical and horizontal lines. The method iterates over the game board, retrieves the shape at each position, and renders colored squares for occupied positions. The current falling piece is drawn using the curX and curY variables. The drawPause method displays a pause message when needed. Overall, the doDrawing method ensures visually appealing game components.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\/\/ Draw the game components on the panel\r\nprivate void doDrawing(Graphics g) {\r\n    Graphics2D g2d = (Graphics2D) g;\r\n    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r\n\r\n    Dimension size = getSize();\r\n    g2d.setColor(Color.DARK_GRAY);\r\n    int boardTop = (int) size.getHeight() - BOARD_HEIGHT * squareHeight();\r\n\r\n    \/\/ Draw the vertical lines of the board\r\n    for (int i = 0; i &lt; BOARD_HEIGHT; i++) {\r\n        g2d.drawLine(0, boardTop + i * squareHeight(), BOARD_WIDTH * squareWidth(), boardTop + i * squareHeight());\r\n    }\r\n\r\n    \/\/ Draw the horizontal lines of the board\r\n    for (int j = 0; j &lt; BOARD_WIDTH; j++) {\r\n        g2d.drawLine(j * squareWidth(), boardTop, j * squareWidth(), boardTop + BOARD_HEIGHT * squareHeight());\r\n    }\r\n\r\n    \/\/ Draw the occupied squares on the board\r\n    for (int i = 0; i &lt; BOARD_HEIGHT; i++) {\r\n        for (int j = 0; j &lt; BOARD_WIDTH; j++) {\r\n            Tetrominoe shape = shapeAt(j, BOARD_HEIGHT - i - 1);\r\n            if (shape != Tetrominoe.NoShape) {\r\n                drawSquare(g2d, j * squareWidth(),\r\n                        boardTop + i * squareHeight(), shape);\r\n            }\r\n        }\r\n    }\r\n\r\n    \/\/ Draw the current falling piece\r\n    if (curPiece.getShape() != Tetrominoe.NoShape) {\r\n        for (int i = 0; i &lt; 4; i++) {\r\n            int x = curX + curPiece.x(i);\r\n            int y = curY - curPiece.y(i);\r\n            drawSquare(g2d, x * squareWidth(),\r\n                    boardTop + (BOARD_HEIGHT - y - 1) * squareHeight(),\r\n                    curPiece.getShape());\r\n        }\r\n    }\r\n\r\n    \/\/ Draw the pause message if the game is paused\r\n    if (isPaused) {\r\n        drawPause(g2d);\r\n    }\r\n}\r\n\r\n\/\/ Draw a square with a specified color\r\nprivate void drawSquare(Graphics2D g2d, int x, int y, Tetrominoe shape) {\r\n    Color[] colors = {\r\n            new Color(0, 0, 0), new Color(204, 102, 102),\r\n            new Color(102, 204, 102), new Color(102, 102, 204),\r\n            new Color(204, 204, 102), new Color(204, 102, 204),\r\n            new Color(102, 204, 204), new Color(218, 170, 0)\r\n    };\r\n    Color color = colors[shape.ordinal()];\r\n    g2d.setColor(color);\r\n    g2d.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2);\r\n    g2d.setColor(color.brighter());\r\n    g2d.drawLine(x, y + squareHeight() - 1, x, y);\r\n    g2d.drawLine(x, y, x + squareWidth() - 1, y);\r\n    g2d.setColor(color.darker());\r\n    g2d.drawLine(x + 1, y + squareHeight() - 1,\r\n            x + squareWidth() - 1, y + squareHeight() - 1);\r\n    g2d.drawLine(x + squareWidth() - 1, y + squareHeight() - 1,\r\n            x + squareWidth() - 1, y + 1);\r\n}\r\n\r\n\r\n\r\n\r\n\/\/ Clear the board by setting all positions to NoShape\r\nprivate void clearBoard() {\r\n    for (int i = 0; i &lt; BOARD_WIDTH; i++) {\r\n        for (int j = 0; j &lt; BOARD_HEIGHT; j++) {\r\n            board[i][j] = Tetrominoe.NoShape;\r\n        }\r\n    }\r\n}\r\n\r\n\/\/ Draw the pause message on the panel\r\nprivate void drawPause(Graphics2D g2d) {\r\n    String pauseMsg = \"Paused\";\r\n    g2d.setColor(Color.YELLOW);\r\n    g2d.setFont(new Font(\"SansSerif\", Font.BOLD, 24));\r\n    FontMetrics fm = getFontMetrics(g2d.getFont());\r\n    int msgWidth = fm.stringWidth(pauseMsg);\r\n    int msgHeight = fm.getHeight();\r\n    int x = (getWidth() - msgWidth) \/ 2;\r\n    int y = (getHeight() - msgHeight) \/ 2;\r\n    g2d.drawString(pauseMsg, x, y);\r\n}\r\n\r\n@Override\r\npublic void paintComponent(Graphics g) {\r\n    super.paintComponent(g);\r\n\r\n    \/\/ Draw the lines cleared and score information\r\n    Font font = new Font(\"SansSerif\", Font.BOLD, 14);\r\n    FontMetrics fontMetrics = g.getFontMetrics(font);\r\n    String linesClearedText = \"Lines Cleared: \" + numLinesRemoved;\r\n    String scoreText = \"Score: \" + (numLinesRemoved * 100);\r\n    int textWidth = fontMetrics.stringWidth(linesClearedText);\r\n    g.setColor(Color.GREEN);\r\n    g.setFont(font);\r\n    g.drawString(linesClearedText, 5, 15);\r\n    g.drawString(scoreText, 180, 15);\r\n\r\n    \/\/ Draw the game components\r\n    doDrawing(g);\r\n}<\/pre>\n<h4>7. The main() method:<\/h4>\n<p>The main method is the entry point of the program. It initiates the frame and its border layout by invoking through SwingUtilites.invokeLater().<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\/\/ Entry point of the program\r\npublic static void main(String[] args) {\r\n    SwingUtilities.invokeLater(() -&gt; {\r\n        JFrame frame = new JFrame(\"TechVidvan's Tetris\");\r\n        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\r\n        frame.setResizable(false);\r\n        frame.add(new Tetris(), BorderLayout.CENTER);\r\n        frame.pack();\r\n        frame.setLocationRelativeTo(null);\r\n        frame.setVisible(true);\r\n    });\r\n}<\/pre>\n<h4>8. Test the Tetris game:<\/h4>\n<p>Run the respective code to test the game.<\/p>\n<p><strong>1. Basic GUI<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/java-tetris-game-output.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-88154 size-full\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/java-tetris-game-output.webp\" alt=\"java tetris game output\" width=\"400\" height=\"816\" \/><\/a><\/p>\n<p><strong>2. Score Updation<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/score-updation.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-88155 size-full\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/score-updation.webp\" alt=\"score updation\" width=\"400\" height=\"791\" \/><\/a><\/p>\n<p><strong>3. Pause State<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/pause-state.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-88156 size-full\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/pause-state.webp\" alt=\"pause state\" width=\"390\" height=\"779\" \/><\/a><\/p>\n<p><strong>4. GameOver State<\/strong><\/p>\n<p><a href=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/game-over-state.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-88157 size-full\" src=\"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/07\/game-over-state.webp\" alt=\"game over state\" width=\"400\" height=\"784\" \/><\/a><\/p>\n<h3>Conclusion:<\/h3>\n<p>In conclusion, using the AWT and Swing APIs, this Tetris project illustrated how to create a graphical user interface. To win the game, players must arrange falling blocks into complete lines. The project has also demonstrated important concepts in Java GUI programming and game development, including user input, object-oriented programming, and event handling. Anyone who is interested in learning more about these subjects should check out this initiative.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A well-known game&#8217;s Java adaptation is the Tetris game project. It demonstrates how to develop a graphical user interface using the AWT and Swing libraries. Players must arrange falling blocks to form entire lines&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":88151,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[183],"tags":[2753,2755,2756,5127,5128,5129,5130],"class_list":["post-88098","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","tag-java-project-ideas","tag-java-projects","tag-java-projects-for-beginners","tag-java-tetris-game","tag-java-tetris-game-project","tag-tetris-game","tag-tetris-game-project"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Java Tetris Game - Thrilling Blocks &amp; Endless Joy! - TechVidvan<\/title>\n<meta name=\"description\" content=\"Experience classic fun with our Java Tetris game! Play for free &amp; challenge your skills. Enjoy endless blocks, and nostalgia.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Java Tetris Game - Thrilling Blocks &amp; Endless Joy! - TechVidvan\" \/>\n<meta property=\"og:description\" content=\"Experience classic fun with our Java Tetris game! Play for free &amp; challenge your skills. Enjoy endless blocks, and nostalgia.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/\" \/>\n<meta property=\"og:site_name\" content=\"TechVidvan\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/TechVidvan\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-07-24T13:39:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-03T09:33:35+00:00\" \/>\n<meta name=\"author\" content=\"TechVidvan Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@vidvantech\" \/>\n<meta name=\"twitter:site\" content=\"@vidvantech\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"TechVidvan Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Java Tetris Game - Thrilling Blocks &amp; Endless Joy! - TechVidvan","description":"Experience classic fun with our Java Tetris game! Play for free & challenge your skills. Enjoy endless blocks, and nostalgia.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/","og_locale":"en_US","og_type":"article","og_title":"Java Tetris Game - Thrilling Blocks &amp; Endless Joy! - TechVidvan","og_description":"Experience classic fun with our Java Tetris game! Play for free & challenge your skills. Enjoy endless blocks, and nostalgia.","og_url":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/","og_site_name":"TechVidvan","article_publisher":"https:\/\/www.facebook.com\/TechVidvan\/","article_published_time":"2023-07-24T13:39:10+00:00","article_modified_time":"2026-06-03T09:33:35+00:00","author":"TechVidvan Team","twitter_card":"summary_large_image","twitter_creator":"@vidvantech","twitter_site":"@vidvantech","twitter_misc":{"Written by":"TechVidvan Team","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#article","isPartOf":{"@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/"},"author":{"name":"TechVidvan Team","@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/person\/e9c26e74dd3d87421f7ada9433b8cd22"},"headline":"Java Tetris Game &#8211; Thrilling Blocks &amp; Endless Joy!","datePublished":"2023-07-24T13:39:10+00:00","dateModified":"2026-06-03T09:33:35+00:00","mainEntityOfPage":{"@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/"},"wordCount":675,"commentCount":0,"publisher":{"@id":"https:\/\/techvidvan.com\/tutorials\/#organization"},"image":{"@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#primaryimage"},"thumbnailUrl":"","keywords":["java project ideas","java projects","java projects for beginners","java tetris game","java tetris game project","tetris game","tetris game project"],"articleSection":["Java Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/","url":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/","name":"Java Tetris Game - Thrilling Blocks &amp; Endless Joy! - TechVidvan","isPartOf":{"@id":"https:\/\/techvidvan.com\/tutorials\/#website"},"primaryImageOfPage":{"@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#primaryimage"},"image":{"@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#primaryimage"},"thumbnailUrl":"","datePublished":"2023-07-24T13:39:10+00:00","dateModified":"2026-06-03T09:33:35+00:00","description":"Experience classic fun with our Java Tetris game! Play for free & challenge your skills. Enjoy endless blocks, and nostalgia.","breadcrumb":{"@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#primaryimage","url":"","contentUrl":""},{"@type":"BreadcrumbList","@id":"https:\/\/techvidvan.com\/tutorials\/java-tetris-game\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/techvidvan.com\/tutorials\/"},{"@type":"ListItem","position":2,"name":"Java Tetris Game &#8211; Thrilling Blocks &amp; Endless Joy!"}]},{"@type":"WebSite","@id":"https:\/\/techvidvan.com\/tutorials\/#website","url":"https:\/\/techvidvan.com\/tutorials\/","name":"TechVidvan Blogs","description":"","publisher":{"@id":"https:\/\/techvidvan.com\/tutorials\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/techvidvan.com\/tutorials\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/techvidvan.com\/tutorials\/#organization","name":"TechVidvan","url":"https:\/\/techvidvan.com\/tutorials\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/logo\/image\/","url":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2024\/03\/techvidvan-logo-200x50-1.webp","contentUrl":"https:\/\/techvidvan.com\/tutorials\/wp-content\/uploads\/2024\/03\/techvidvan-logo-200x50-1.webp","width":200,"height":50,"caption":"TechVidvan"},"image":{"@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/TechVidvan\/","https:\/\/x.com\/vidvantech"]},{"@type":"Person","@id":"https:\/\/techvidvan.com\/tutorials\/#\/schema\/person\/e9c26e74dd3d87421f7ada9433b8cd22","name":"TechVidvan Team","description":"The TechVidvan Team delivers practical, beginner-friendly tutorials on programming, Java, Python, C++, DSA, AI, ML, data Science, Android, Flutter, MERN, Web Development, and technology. Our experts are here to help you upskill and excel in today\u2019s tech industry."}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/posts\/88098","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/comments?post=88098"}],"version-history":[{"count":2,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/posts\/88098\/revisions"}],"predecessor-version":[{"id":448025,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/posts\/88098\/revisions\/448025"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/media?parent=88098"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/categories?post=88098"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techvidvan.com\/tutorials\/wp-json\/wp\/v2\/tags?post=88098"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}