├── Board.java
├── MainMenu.java
├── README.md
├── Shape.java
├── TAdapter.java
├── Tetris.java
├── Tetris
├── Board.java
├── MainMenu.java
├── Shape.java
├── TAdapter.java
├── Tetris.java
├── kethop.png
├── muiten.png
├── music1.mp3
├── thayThong.jpg
└── wasd.png
├── ThuanTheBadLuckCoder
├── kethop.png
├── muiten.png
├── music1.mp3
├── thayThong.jpg
└── wasd.png
/Board.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import java.awt.Color;
4 | import java.awt.Dimension;
5 | import java.awt.Font;
6 | import java.awt.Graphics;
7 | import java.awt.event.ActionEvent;
8 | import java.awt.event.ActionListener;
9 |
10 |
11 | //import javax.swing.JButton;
12 | import javax.swing.JLabel;
13 | import javax.swing.JPanel;
14 | import javax.swing.Timer;
15 |
16 | import Tetris.Shape.Tetrominoes;
17 |
18 | public class Board extends JPanel implements ActionListener {
19 | //checked
20 | private Tetris tetris;
21 | private final int BoardWidth = 10;
22 | private final int BoardHeight = 22;
23 | private Timer timer;
24 | private boolean isFallingFinished = false;
25 | private boolean isStarted = false;
26 | boolean isPaused = false;
27 | private boolean gameOver= false;
28 | private int numLinesRemoved = 0;
29 | private int curX = 0;
30 | private int curY = 0;
31 | private JLabel statusbar;
32 | private Shape curPiece;
33 | private Tetrominoes[] board;
34 | //checked
35 | public Board(Tetris parent, JLabel statusbar, TAdapter adapter) {
36 | initBoard(parent, statusbar, adapter);
37 | }
38 |
39 | public boolean getIsStarted(){
40 | return isStarted;
41 | }
42 |
43 | //checked
44 | private void initBoard(Tetris parent, JLabel statusbar, TAdapter adapter) {
45 | tetris = parent;
46 | setFocusable(true);
47 | curPiece = new Shape();
48 | timer = new Timer(400, this);
49 | timer.start();
50 |
51 | this.statusbar = statusbar;
52 | statusbar.setFont(new Font("Serif", Font.PLAIN, 30));
53 | board = new Tetrominoes[BoardWidth * BoardHeight];
54 | clearBoard();
55 | addListener(adapter);
56 | }
57 |
58 | public void addListener(TAdapter adapter){
59 | adapter.addBoard(this);
60 | addKeyListener(adapter);
61 | }
62 |
63 |
64 |
65 | //checked
66 | @Override
67 | public void actionPerformed(ActionEvent e) {
68 | if (!isPaused) {
69 | if (isFallingFinished) {
70 | isFallingFinished = false;
71 | newPiece();
72 | } else {
73 | oneLineDown();
74 | }
75 | }
76 |
77 | }
78 | //checked
79 | private int squareWidth() {
80 | return (int) getSize().getWidth() / BoardWidth;
81 | }
82 | private int squareHeight() {
83 | return (int) getSize().getHeight() / BoardHeight;
84 | }
85 | private Tetrominoes shapeAt(int x, int y) {
86 | return board[(y * BoardWidth) + x];
87 | }
88 |
89 | //check
90 | public void start() {
91 |
92 | if (isPaused)
93 | return;
94 |
95 | isStarted = true;
96 | isFallingFinished = false;
97 | numLinesRemoved = 0;
98 | clearBoard();
99 |
100 | newPiece();
101 | timer.start();
102 | }
103 |
104 | //checked
105 | public void pause() {
106 |
107 | if (!isStarted)
108 | return;
109 |
110 | isPaused = !isPaused;
111 |
112 | if (isPaused) {
113 | timer.stop();
114 | statusbar.setText("paused");
115 | } else {
116 |
117 | timer.start();
118 | statusbar.setText(String.valueOf(numLinesRemoved));
119 | }
120 |
121 | repaint();
122 | }
123 |
124 | //checked
125 | private void doDrawing(Graphics g) {
126 | Dimension size = getSize();
127 | int boardTop = (int) size.getHeight() - BoardHeight * squareHeight();
128 |
129 | for (int i = 0; i < BoardHeight; ++i) {
130 |
131 | for (int j = 0; j < BoardWidth; ++j) {
132 |
133 | Tetrominoes shape = shapeAt(j, BoardHeight - i - 1);
134 |
135 | if (shape != Tetrominoes.NoShape)
136 | drawSquare(g, 0 + j * squareWidth(),
137 | boardTop + i * squareHeight(), shape);
138 | }
139 | }
140 |
141 | if (curPiece.getShape() != Tetrominoes.NoShape) {
142 |
143 | for (int i = 0; i < 4; ++i) {
144 | int x = curX + curPiece.x(i);
145 | int y = curY - curPiece.y(i);
146 | drawSquare(g, 0 + x * squareWidth(), boardTop + (BoardHeight - y - 1) * squareHeight(), curPiece.getShape());
147 | }
148 | }
149 |
150 |
151 | }
152 | //checked
153 | @Override
154 | public void paintComponent(Graphics g) {
155 | super.paintComponent(g);
156 | doDrawing(g);
157 | }
158 | //checked
159 | public void dropDown() {
160 | if(!isPaused) {
161 | int newY = curY;
162 | while (newY > 0) {
163 |
164 | if (!tryMove(0, -1))
165 | break;
166 | --newY;
167 |
168 | }
169 | pieceDropped();
170 | }
171 |
172 |
173 | }
174 | //checked
175 | public void oneLineDown() {
176 |
177 | if (!tryMove(0, -1))
178 | pieceDropped();
179 |
180 |
181 | }
182 |
183 | //checked
184 | private void clearBoard() {
185 |
186 | for (int i = 0; i < BoardHeight * BoardWidth; ++i)
187 | board[i] = Tetrominoes.NoShape;
188 |
189 |
190 | }
191 |
192 | //checked
193 | private void pieceDropped() {
194 | if (!isPaused) {
195 | for (int i = 0; i < 4; ++i) {
196 |
197 | int x = curX + curPiece.x(i);
198 | int y = curY - curPiece.y(i);
199 | board[(y * BoardWidth) + x] = curPiece.getShape();
200 | }
201 |
202 | removeFullLines();
203 |
204 | if (!isFallingFinished)
205 | newPiece();
206 | }
207 |
208 | }
209 | //checked
210 | private void newPiece() {
211 | if (!isPaused) {
212 | curPiece.setRandomShape();
213 | curX = BoardWidth / 2 - 1;
214 | curY = BoardHeight - 1 + curPiece.minY();
215 |
216 | if (!tryMove(0, 0)) {
217 |
218 | curPiece.setShape(Tetrominoes.NoShape);
219 | timer.stop();
220 | isStarted = false;
221 | statusbar.setText("Game Over!!!");
222 | if(!gameOver)
223 | tetris.gameOver();
224 | gameOver = true;
225 | }
226 | }
227 |
228 | }
229 | //checked
230 | public boolean tryMove(int difX, int difY) {
231 | if(!isPaused) {
232 | for (int i = 0; i < 4; ++i) {
233 | int x = curX + difX + curPiece.x(i);
234 | int y = curY + difY - curPiece.y(i);
235 |
236 |
237 | if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
238 | return false;
239 |
240 | if (shapeAt(x, y) != Tetrominoes.NoShape)
241 | return false;
242 | }
243 |
244 | curX += difX;
245 | curY += difY;
246 |
247 | repaint();
248 |
249 |
250 | }
251 |
252 | return true;
253 | }
254 |
255 | public boolean rotateLeft() {
256 | Shape temp = new Shape(curPiece);
257 | curPiece = curPiece.rotateLeft();
258 | if(tryMove(0, 0))
259 | return true;
260 | else{
261 | curPiece = temp;
262 | return false;
263 | }
264 | }
265 | //checked
266 | private void removeFullLines() {
267 | if (!isPaused) {
268 | int numFullLines = 0;
269 |
270 | for (int i = BoardHeight - 1; i >= 0; --i) {
271 | boolean lineIsFull = true;
272 |
273 | for (int j = 0; j < BoardWidth; ++j) {
274 | if (shapeAt(j, i) == Tetrominoes.NoShape) {
275 | lineIsFull = false;
276 | break;
277 | }
278 | }
279 |
280 | if (lineIsFull) {
281 | ++numFullLines;
282 | for (int k = i; k < BoardHeight - 1; ++k) {
283 | for (int j = 0; j < BoardWidth; ++j)
284 | board[(k * BoardWidth) + j] = shapeAt(j, k + 1);
285 | }
286 | }
287 | }
288 | if (numFullLines > 0) {
289 |
290 | numLinesRemoved += numFullLines;
291 | statusbar.setText(String.valueOf(numLinesRemoved));
292 | isFallingFinished = true;
293 | curPiece.setShape(Tetrominoes.NoShape);
294 | repaint();
295 | }
296 | }
297 |
298 | }
299 | //checked
300 | private void drawSquare(Graphics g, int x, int y, Tetrominoes shape) {
301 |
302 | Color colors[] = {
303 | //NoShape
304 | new Color(0, 0, 0),
305 | //ZShape
306 | new Color(204, 102, 102),
307 | //oZ
308 | new Color(102, 204, 102),
309 | //L
310 | //I
311 | new Color(204, 102, 204),
312 | //T
313 | new Color(218, 170, 0),
314 | //Square
315 | new Color(102, 204, 204),
316 | new Color(102, 102, 204),
317 | //oL
318 | new Color(204, 204, 102)
319 | };
320 |
321 | Color color = colors[shape.ordinal()];
322 |
323 | g.setColor(color);
324 | g.fillRect(x + 4, y + 4, squareWidth() - 4, squareHeight() - 4);
325 |
326 | g.setColor(color.brighter());
327 | g.drawLine(x, y + squareHeight() - 2, x, y);
328 | g.drawLine(x, y, x + squareWidth() - 2, y);
329 |
330 | g.setColor(color.darker());
331 | g.drawLine(x + 2, y + squareHeight() - 2,
332 | x + squareWidth() - 2, y + squareHeight() - 2);
333 | g.drawLine(x + squareWidth() - 2, y + squareHeight() - 2,
334 | x + squareWidth() - 2, y + 2);
335 |
336 | }
337 | }
338 |
--------------------------------------------------------------------------------
/MainMenu.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import javax.swing.*;
4 | import java.awt.*;
5 | import java.awt.event.ActionEvent;
6 | import java.awt.event.ActionListener;
7 | import java.awt.Graphics;
8 | import java.awt.image.BufferedImage;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.util.logging.Level;
12 | import java.util.logging.Logger;
13 | import javax.imageio.ImageIO;
14 | import javax.swing.JPanel;
15 |
16 |
17 |
18 | public class MainMenu extends JFrame {
19 | JButton onePlayer = new JButton("1 Player");
20 | JButton twoPlayers = new JButton("2 Players");
21 | JButton howToPlay = new JButton("How To Play");
22 | JButton exit = new JButton("Exit");
23 | JButton exit1 = new JButton("Back");
24 | JFrame MainMenuFr = new JFrame("Tetris Time!");
25 | int a = -1;
26 | ActionEvent e;
27 | Tetris game;
28 |
29 |
30 | public MainMenu() {
31 | addButtons();
32 | }
33 |
34 | public void addButtons() {
35 | onePlayer.setBounds(95, 50, 200, 80);
36 | twoPlayers.setBounds(95, 150, 200, 80);
37 | howToPlay.setBounds(95, 250, 200, 80);
38 | exit.setBounds(125, 400, 120, 40);
39 |
40 | MainMenuFr.add(onePlayer);
41 | MainMenuFr.add(twoPlayers);
42 | MainMenuFr.add(howToPlay);
43 | MainMenuFr.add(exit);
44 | try {
45 | ImageIcon image = new ImageIcon(getClass().getResource("thayThong.jpg"));
46 | JLabel displayField = new JLabel(image);
47 | MainMenuFr.add(displayField);
48 | } catch(Exception e) {
49 | System.out.println("Image cannot be found");
50 | }
51 | MainMenuFr.setSize(400, 500);
52 | //MainMenuFr.setLayout(null);
53 | MainMenuFr.setResizable(false);
54 | MainMenuFr.setVisible(true);
55 | MainMenuFr.setLocationRelativeTo(null);
56 |
57 |
58 | onePlayer.addActionListener(new ActionListener() {
59 |
60 | @Override
61 | public void actionPerformed(ActionEvent e) {
62 | a = 1;
63 | //System.out.println(getA());
64 | game = new Tetris(a);
65 | MainMenuFr.setVisible(false);
66 | game.setVisible(true);
67 | //System.exit(0);
68 | }
69 |
70 | });
71 |
72 | twoPlayers.addActionListener(new ActionListener() {
73 | @Override
74 | public void actionPerformed(ActionEvent e) {
75 | a = 2;
76 | //System.out.println(getA());
77 | game = new Tetris(a);
78 | MainMenuFr.setVisible(false);
79 | game.setVisible(true);
80 | //System.exit(0);
81 | }
82 | });
83 |
84 | howToPlay.addActionListener(new ActionListener() {
85 | @Override
86 | public void actionPerformed(ActionEvent e) {
87 | JFrame howToPlayButton = new JFrame();
88 | howToPlayButton.setSize(1000, 800);
89 | howToPlayButton.setVisible(true);
90 | howToPlayButton.setResizable(false);
91 | howToPlayButton.setLocationRelativeTo(null);
92 |
93 | exit1.setBounds(425, 700, 160, 40);
94 | howToPlayButton.add(exit1);
95 |
96 |
97 | try {
98 | ImageIcon image = new ImageIcon(getClass().getResource("kethop.png"));
99 | JLabel displayField = new JLabel(image);
100 | howToPlayButton.add(displayField);
101 | } catch (Exception i) {
102 | //System.out.println("Image cannot be found");
103 | }
104 |
105 |
106 | exit1.addActionListener(new ActionListener() {
107 | @Override
108 | public void actionPerformed(ActionEvent e) {
109 | // TODO Auto-generated method stub
110 | //System.out.println("0");
111 | howToPlayButton.setVisible(false);
112 |
113 | }
114 | });
115 | }
116 | });
117 |
118 | exit.addActionListener(new ActionListener() {
119 | @Override
120 | public void actionPerformed(ActionEvent e) {
121 | // TODO Auto-generated method stub
122 | //System.out.println("0");
123 | System.exit(0);
124 |
125 | }
126 | });
127 | }
128 |
129 | public int getA() {
130 | return a;
131 | }
132 | }
133 |
134 |
135 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Tetris Game
2 |
3 |
4 | Overview
5 |
6 | This is a simple implementation of the classic Tetris game developed as a part of the Object-Oriented Programming (OOP) course. The project is built using Java and focuses on providing a highly customizable experience for players. All Tetris blocks (Tetrominoes) are fully coded, allowing for easy customization and a more user-friendly gaming experience.
7 |
8 | Features
9 |
10 | - Customizable Tetrominoes: The Tetris blocks are entirely programmed with code, enabling quick and easy customization. Players can modify shapes, colors, and behaviors of the blocks to enhance their gaming experience.
11 | - Classic Gameplay: Retains the original Tetris gameplay mechanics, including block rotation, clearing lines, and increasing difficulty over time.
12 | - User-Friendly Interface: The game features a simple and intuitive interface, making it accessible to players of all ages.
13 | - OOP Principles: The project demonstrates the use of Object-Oriented Programming principles such as inheritance, polymorphism, and encapsulation.
14 |
15 |
16 | Installation
17 | To run this game on your local machine, follow these steps:
18 |
19 | 1. Clone the repository:
20 | git clone https://github.com/yourusername/tetris-game.git
21 |
22 | 2. Navigate to the project directory:
23 | cd tetris-game
24 |
25 | 3. Compile the project:
26 | javac -d bin src/*.java
27 |
28 | 4. Run the game:
29 | java -cp bin Main
30 |
31 | How to Play
32 |
33 | - Move: Use the arrow keys to move the Tetromino left, right, or down.
34 | - Rotate: Press the "Up" arrow key to rotate the Tetromino.
35 | - Pause: Press the "P" key to pause the game.
36 | - Resume: Press the "R" key to resume the game.
37 |
38 |
39 |
40 | Customization
41 | To customize the Tetrominoes:
42 |
43 | 1. Open the Tetromino.java file in the src directory.
44 |
45 | 2. Modify the shapes, colors, or other properties as desired.
46 |
47 | 3. Recompile and run the game to see your changes in action.
48 |
49 | Contributing
50 | If you'd like to contribute to the project, feel free to fork the repository and submit a pull request.
51 |
52 | Any contributions, such as bug fixes, feature enhancements, or documentation improvements, are welcome!
53 |
54 | Contact
55 | If you have any questions or feedback, feel free to reach out:
56 |
57 | Email: dtthuan.contact@gmail.com
58 |
59 | GitHub: dtr_thuann
60 |
--------------------------------------------------------------------------------
/Shape.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 | import java.util.Random;
3 |
4 | public class Shape {
5 |
6 | public enum Tetrominoes { NoShape, ZShape, oZShape, IShape,
7 | TShape, SquareShape, LShape, oLShape };
8 |
9 | private Tetrominoes pieceShape;
10 | private int coords[][] = new int[4][2];
11 | private int[][][] coordsTable;
12 |
13 |
14 | public Shape() {
15 | setShape(Tetrominoes.NoShape);
16 | }
17 |
18 | public Shape(Shape shape) {
19 | this.pieceShape = shape.pieceShape;
20 | for (int i = 0; i < 4; ++i) {
21 | this.setX(i, shape.x(i));
22 | this.setY(i, shape.y(i));
23 | }
24 | }
25 |
26 | public void setShape(Tetrominoes shape) {
27 |
28 | coordsTable = new int[][][] {
29 | //NoShape1
30 | {{0,0}, {0,0}, {0,0}, {0,0}},
31 | //ZShape2
32 | {{0,1}, {0,0}, {1,0}, {1,-1}},
33 | //oZShape3
34 | {{0,1}, {0,0}, {-1, 0}, {-1,-1}},
35 | //IShape6
36 | //{{2,0}, {1,0}, {0,0}, {-1,0}},
37 | {{ 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 }},
38 | //TShape7
39 | {{1,0}, {0,0}, {0,1}, {-1,0}},
40 | //SquareShape
41 | {{1,0}, {1,1}, {0,0}, {0,1}},
42 | //LShape4
43 | {{1,-1}, {0,-1}, {0,0}, {0,1}},
44 | //oLShape5
45 | {{0,-1}, {0,0}, {0,1}, {-1,-1}}
46 | };
47 |
48 | for (int i = 0; i < 4 ; i++) {
49 |
50 | for (int j = 0; j < 2; ++j) {
51 |
52 | coords[i][j] = coordsTable[shape.ordinal()][i][j];
53 | }
54 | }
55 |
56 | pieceShape = shape;
57 | }
58 |
59 |
60 |
61 |
62 | public void setRandomShape() {
63 |
64 | Random r = new Random();
65 | int x = Math.abs(r.nextInt()) % 7 + 1;
66 | Tetrominoes[] values = Tetrominoes.values();
67 | setShape(values[x]);
68 | }
69 |
70 | public int minX() {
71 |
72 | int m = coords[0][0];
73 |
74 | for (int i = 0; i < 4; i++) {
75 |
76 | m = Math.min(m, coords[i][0]);
77 | }
78 |
79 | return m;
80 | }
81 |
82 |
83 | public int minY() {
84 |
85 | int m = coords[0][1];
86 |
87 | for (int i = 0; i < 4; i++) {
88 |
89 | m = Math.min(m, coords[i][1]);
90 | }
91 |
92 | return m;
93 | }
94 |
95 | public int x(int index) {
96 | return coords[index][0];
97 | }
98 | public int y(int index) {
99 | return coords[index][1];
100 | }
101 | public Tetrominoes getShape() {
102 | return pieceShape;
103 | }
104 |
105 | private void setX(int index, int x) {
106 | coords[index][0] = x;
107 | }
108 |
109 | private void setY(int index, int y) {
110 | coords[index][1] = y;
111 | }
112 |
113 | public Shape rotateLeft() {
114 | if (pieceShape == Tetrominoes.SquareShape) {
115 | return this;
116 | }
117 |
118 | Shape result = new Shape();
119 | result.pieceShape = pieceShape;
120 | for (int i = 0; i < 4; ++i) {
121 | result.setX(i, y(i));
122 | result.setY(i, -x(i));
123 | }
124 | return result;
125 | }
126 |
127 | /*public Shape rotateRight() {
128 |
129 | if (pieceShape == Tetrominoes.SquareShape) {
130 | return this;
131 | }
132 |
133 | else if (pieceShape == Tetrominoes.IShape) {
134 |
135 | }
136 |
137 | else {
138 | Shape result = new Shape();
139 | result.pieceShape = pieceShape;
140 |
141 | for (int i = 0; i < 4; ++i) {
142 |
143 | result.setX(i, -y(i));
144 | result.setY(i, x(i));
145 | }
146 |
147 | return result;
148 | }
149 |
150 | } */
151 |
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/TAdapter.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import java.awt.event.*;
4 | import java.util.ArrayList;
5 |
6 | public class TAdapter extends KeyAdapter {
7 | ArrayList boards = new ArrayList<>();
8 |
9 | public void addBoard(Board board) {
10 | boards.add(board);
11 | }
12 |
13 | @Override
14 | public void keyPressed(KeyEvent e) {
15 | /*
16 | if (!isStarted || curPiece.getShape() == Tetrominoes.NoShape) {
17 | return;
18 | }*/
19 |
20 | int keycode = e.getKeyCode();
21 |
22 | if (keycode == 'p' || keycode == 'P') {
23 | for(Board board : boards)
24 | board.pause();
25 | return;
26 | }
27 |
28 |
29 | /*if (isPaused)
30 | return;*/
31 |
32 | switch (boards.size()) {
33 | case 2:
34 | controlPlayer2(keycode);
35 | case 1:
36 | controlPlayer1(keycode);
37 | break;
38 | default:
39 | break;
40 | }
41 | }
42 |
43 | private void controlPlayer1(int keycode){
44 | Board board = boards.get(0);
45 |
46 | switch (keycode) {
47 | case KeyEvent.VK_LEFT:
48 | board.tryMove(-1, 0);
49 | break;
50 |
51 | case KeyEvent.VK_RIGHT:
52 | board.tryMove(1, 0);
53 | break;
54 |
55 | case KeyEvent.VK_UP:
56 | board.rotateLeft();
57 | break;
58 |
59 | case KeyEvent.VK_DOWN:
60 | board.oneLineDown();
61 | break;
62 | case KeyEvent.VK_L:
63 | board.dropDown();
64 | break;
65 | case KeyEvent.VK_P:
66 | board.pause();
67 | break;
68 | }
69 |
70 |
71 | }
72 |
73 | private void controlPlayer2(int keycode){
74 | Board board = boards.get(1);
75 | switch (keycode) {
76 | case KeyEvent.VK_A:
77 | board.tryMove(-1, 0);
78 | break;
79 |
80 | case KeyEvent.VK_D:
81 | board.tryMove(1, 0);
82 | break;
83 |
84 | case KeyEvent.VK_W:
85 | board.rotateLeft();
86 | break;
87 |
88 | case KeyEvent.VK_S:
89 | board.oneLineDown();
90 | break;
91 |
92 | case KeyEvent.VK_G:
93 | board.dropDown();
94 | break;
95 | case KeyEvent.VK_P:
96 | board.pause();
97 | break;
98 | }
99 |
100 |
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Tetris.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import java.awt.*;
4 |
5 | import javax.sound.sampled.AudioSystem;
6 | import javax.swing.*;
7 |
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 |
11 |
12 | import java.io.FileInputStream;
13 | import java.io.FileNotFoundException;
14 |
15 | import java.io.File;
16 | import java.io.IOException;
17 | import java.util.Scanner;
18 |
19 | import javax.sound.sampled.*;
20 |
21 | public class Tetris extends JFrame {
22 | private JLabel statusbar;
23 | private JLabel statusbar1;
24 | static JPanel mainPanel = new JPanel();
25 | JButton playAgain;
26 | int player;
27 | static MainMenu a = new MainMenu();
28 |
29 | public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
30 |
31 | /* SwingUtilities.invokeLater(new Runnable() {
32 |
33 | @Override
34 | public void run() {
35 | while (a.getA() != -1) {
36 | int numberOfPlayer = a.getA();
37 | a.MainMenuFr.setVisible(false);
38 | if (numberOfPlayer == 1 || numberOfPlayer == 2) {
39 | Tetris game = new Tetris(numberOfPlayer);
40 | game.setVisible(true);
41 | System.out.print("da chay");
42 |
43 | }
44 | else {
45 | System.out.print("khong chay");
46 | }
47 | }
48 |
49 | }
50 | }); */
51 |
52 | }
53 |
54 | public void playSound() {{
55 | new Thread(new Runnable() {
56 | public void run() {
57 | try {
58 | AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("music.wav").getAbsoluteFile());
59 | Clip clip = AudioSystem.getClip();
60 | clip.open(audioInputStream);
61 | clip.start();
62 | } catch(Exception ex) {
63 | System.out.println("Error with playing sound.");
64 | ex.printStackTrace();
65 | }
66 | }
67 | }).start();
68 | }
69 | }
70 |
71 |
72 |
73 |
74 | public Tetris(int numberOfPlayer) {
75 | playSound();
76 | mainPanel = new JPanel();
77 | player = numberOfPlayer;
78 | playAgain = new JButton("Back To Menu?");
79 | playAgain.addActionListener(new ActionListener() {
80 | @Override
81 | public void actionPerformed(ActionEvent e) {
82 | setVisible(false);
83 | a.MainMenuFr.setVisible(true);
84 | }
85 | });
86 | add(playAgain);
87 | playAgain.setVisible(false);
88 | if (numberOfPlayer == 1) {
89 | //System.out.println("so 1");
90 | initUI();
91 | }
92 | else if (numberOfPlayer == 2) {
93 | //System.out.println("so 2");
94 | initUI2Players();
95 | }
96 |
97 | }
98 |
99 | int count = 0;
100 | public void gameOver() {
101 | count++;
102 | if(player == 1) {
103 | playAgain.setBounds(110 ,650, 180, 60);
104 | playAgain.setVisible(true);
105 | } else {
106 | if(count == 2){
107 | playAgain.setBounds(310 ,650, 180, 60);
108 | playAgain.setVisible(true);
109 | }
110 | }
111 | }
112 |
113 | private void initUI2Players() {
114 | TAdapter adapter = new TAdapter();
115 |
116 | statusbar = new JLabel(" 0");
117 |
118 |
119 | Board board = new Board(this, statusbar, adapter);
120 | board.add(statusbar, BorderLayout.PAGE_END);
121 | board.start();
122 |
123 | statusbar1 = new JLabel(" 0");
124 |
125 |
126 | Board board1 = new Board(this, statusbar1, adapter);
127 |
128 | board1.add(statusbar1, BorderLayout.PAGE_END);
129 | mainPanel.add(board1);
130 | mainPanel.add(board);
131 | board1.start();
132 |
133 |
134 |
135 | mainPanel.setLayout(new GridLayout(0, 2,5,2));
136 | mainPanel.setSize(800,800);
137 | setBackground(Color.black);
138 |
139 | add(mainPanel);
140 |
141 | setResizable(false);
142 |
143 | setSize(800, 800);
144 | setTitle("Tetris");
145 | setDefaultCloseOperation(EXIT_ON_CLOSE);
146 | setLocationRelativeTo(null);
147 | setResizable(false);
148 |
149 | //set mau nen
150 | board.setBackground(Color.DARK_GRAY);
151 | //board1.setBackground(Color.white);
152 |
153 |
154 |
155 | }
156 |
157 | public void initUI() {
158 | TAdapter adapter = new TAdapter();
159 |
160 | statusbar = new JLabel(" 0");
161 | add(statusbar, BorderLayout.SOUTH);
162 | Board board = new Board(this, statusbar, adapter);
163 | add(board);
164 | board.start();
165 |
166 | setSize(400, 800);
167 | setTitle("Tetris");
168 | setDefaultCloseOperation(EXIT_ON_CLOSE);
169 | setLocationRelativeTo(null);
170 | setResizable(false);
171 |
172 | //set mau nen
173 | board.setBackground(Color.black);
174 | }
175 |
176 |
177 | // public JLabel getStatusBar() {
178 |
179 | // return statusbar;
180 | // }
181 | }
--------------------------------------------------------------------------------
/Tetris/Board.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import java.awt.Color;
4 | import java.awt.Dimension;
5 | import java.awt.Graphics;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 |
9 |
10 | //import javax.swing.JButton;
11 | import javax.swing.JLabel;
12 | import javax.swing.JPanel;
13 | import javax.swing.Timer;
14 |
15 | import Tetris.Shape.Tetrominoes;
16 |
17 | public class Board extends JPanel implements ActionListener {
18 | //checked
19 | private Tetris tetris;
20 | private final int BoardWidth = 10;
21 | private final int BoardHeight = 22;
22 | private Timer timer;
23 | private boolean isFallingFinished = false;
24 | private boolean isStarted = false;
25 | boolean isPaused = false;
26 | private boolean gameOver= false;
27 | private int numLinesRemoved = 0;
28 | private int curX = 0;
29 | private int curY = 0;
30 | private JLabel statusbar;
31 | private Shape curPiece;
32 | private Tetrominoes[] board;
33 | //checked
34 | public Board(Tetris parent, JLabel statusbar, TAdapter adapter) {
35 | initBoard(parent, statusbar, adapter);
36 | }
37 |
38 | public boolean getIsStarted(){
39 | return isStarted;
40 | }
41 |
42 | //checked
43 | private void initBoard(Tetris parent, JLabel statusbar, TAdapter adapter) {
44 | tetris = parent;
45 | setFocusable(true);
46 | curPiece = new Shape();
47 | timer = new Timer(400, this);
48 | timer.start();
49 |
50 | this.statusbar = statusbar;
51 | board = new Tetrominoes[BoardWidth * BoardHeight];
52 | clearBoard();
53 | addListener(adapter);
54 | }
55 |
56 | public void addListener(TAdapter adapter){
57 | adapter.addBoard(this);
58 | addKeyListener(adapter);
59 | }
60 |
61 |
62 |
63 | //checked
64 | @Override
65 | public void actionPerformed(ActionEvent e) {
66 | if (!isPaused) {
67 | if (isFallingFinished) {
68 | isFallingFinished = false;
69 | newPiece();
70 | } else {
71 | oneLineDown();
72 | }
73 | }
74 |
75 | }
76 | //checked
77 | private int squareWidth() {
78 | return (int) getSize().getWidth() / BoardWidth;
79 | }
80 | private int squareHeight() {
81 | return (int) getSize().getHeight() / BoardHeight;
82 | }
83 | private Tetrominoes shapeAt(int x, int y) {
84 | return board[(y * BoardWidth) + x];
85 | }
86 |
87 | //check
88 | public void start() {
89 |
90 | if (isPaused)
91 | return;
92 |
93 | isStarted = true;
94 | isFallingFinished = false;
95 | numLinesRemoved = 0;
96 | clearBoard();
97 |
98 | newPiece();
99 | timer.start();
100 | }
101 |
102 | //checked
103 | public void pause() {
104 |
105 | if (!isStarted)
106 | return;
107 |
108 | isPaused = !isPaused;
109 |
110 | if (isPaused) {
111 |
112 | timer.stop();
113 | statusbar.setText("paused");
114 | } else {
115 |
116 | timer.start();
117 | statusbar.setText(String.valueOf(numLinesRemoved));
118 | }
119 |
120 | repaint();
121 | }
122 |
123 | //checked
124 | private void doDrawing(Graphics g) {
125 | if (!isPaused) {
126 | Dimension size = getSize();
127 | int boardTop = (int) size.getHeight() - BoardHeight * squareHeight();
128 |
129 | for (int i = 0; i < BoardHeight; ++i) {
130 |
131 | for (int j = 0; j < BoardWidth; ++j) {
132 |
133 | Tetrominoes shape = shapeAt(j, BoardHeight - i - 1);
134 |
135 | if (shape != Tetrominoes.NoShape)
136 | drawSquare(g, 0 + j * squareWidth(),
137 | boardTop + i * squareHeight(), shape);
138 | }
139 | }
140 |
141 | if (curPiece.getShape() != Tetrominoes.NoShape) {
142 |
143 | for (int i = 0; i < 4; ++i) {
144 | int x = curX + curPiece.x(i);
145 | int y = curY - curPiece.y(i);
146 | drawSquare(g, 0 + x * squareWidth(), boardTop + (BoardHeight - y - 1) * squareHeight(), curPiece.getShape());
147 | }
148 | }
149 | }
150 |
151 | }
152 | //checked
153 | @Override
154 | public void paintComponent(Graphics g) {
155 | super.paintComponent(g);
156 | doDrawing(g);
157 | }
158 | //checked
159 | public void dropDown() {
160 | if(!isPaused) {
161 | int newY = curY;
162 | while (newY > 0) {
163 |
164 | if (!tryMove(0, -1))
165 | break;
166 | --newY;
167 |
168 | }
169 | pieceDropped();
170 | }
171 |
172 |
173 | }
174 | //checked
175 | public void oneLineDown() {
176 | if (!isPaused) {
177 | if (!tryMove(0, -1))
178 | pieceDropped();
179 | }
180 |
181 | }
182 |
183 | //checked
184 | private void clearBoard() {
185 | if (!isPaused) {
186 | for (int i = 0; i < BoardHeight * BoardWidth; ++i)
187 | board[i] = Tetrominoes.NoShape;
188 | }
189 |
190 | }
191 |
192 | //checked
193 | private void pieceDropped() {
194 | if (!isPaused) {
195 | for (int i = 0; i < 4; ++i) {
196 |
197 | int x = curX + curPiece.x(i);
198 | int y = curY - curPiece.y(i);
199 | board[(y * BoardWidth) + x] = curPiece.getShape();
200 | }
201 |
202 | removeFullLines();
203 |
204 | if (!isFallingFinished)
205 | newPiece();
206 | }
207 |
208 | }
209 | //checked
210 | private void newPiece() {
211 | if (!isPaused) {
212 | curPiece.setRandomShape();
213 | curX = BoardWidth / 2 - 1;
214 | curY = BoardHeight - 1 + curPiece.minY();
215 |
216 | if (!tryMove(0, 0)) {
217 |
218 | curPiece.setShape(Tetrominoes.NoShape);
219 | timer.stop();
220 | isStarted = false;
221 | statusbar.setText("Game Over!!!");
222 | if(!gameOver)
223 | tetris.gameOver();
224 | gameOver = true;
225 | }
226 | }
227 |
228 | }
229 | //checked
230 | public boolean tryMove(int difX, int difY) {
231 | if(!isPaused) {
232 | for (int i = 0; i < 4; ++i) {
233 | int x = curX + difX + curPiece.x(i);
234 | int y = curY + difY - curPiece.y(i);
235 |
236 |
237 | if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
238 | return false;
239 |
240 | if (shapeAt(x, y) != Tetrominoes.NoShape)
241 | return false;
242 | }
243 |
244 | curX += difX;
245 | curY += difY;
246 |
247 | repaint();
248 |
249 |
250 | }
251 |
252 | return true;
253 | }
254 |
255 | public boolean rotateLeft() {
256 | Shape temp = new Shape(curPiece);
257 | curPiece = curPiece.rotateLeft();
258 | if(tryMove(0, 0))
259 | return true;
260 | else{
261 | curPiece = temp;
262 | return false;
263 | }
264 | }
265 | //checked
266 | private void removeFullLines() {
267 | if (!isPaused) {
268 | int numFullLines = 0;
269 |
270 | for (int i = BoardHeight - 1; i >= 0; --i) {
271 | boolean lineIsFull = true;
272 |
273 | for (int j = 0; j < BoardWidth; ++j) {
274 | if (shapeAt(j, i) == Tetrominoes.NoShape) {
275 | lineIsFull = false;
276 | break;
277 | }
278 | }
279 |
280 | if (lineIsFull) {
281 | ++numFullLines;
282 | for (int k = i; k < BoardHeight - 1; ++k) {
283 | for (int j = 0; j < BoardWidth; ++j)
284 | board[(k * BoardWidth) + j] = shapeAt(j, k + 1);
285 | }
286 | }
287 | }
288 | if (numFullLines > 0) {
289 |
290 | numLinesRemoved += numFullLines;
291 | statusbar.setText(String.valueOf(numLinesRemoved));
292 | isFallingFinished = true;
293 | curPiece.setShape(Tetrominoes.NoShape);
294 | repaint();
295 | }
296 | }
297 |
298 | }
299 | //checked
300 | private void drawSquare(Graphics g, int x, int y, Tetrominoes shape) {
301 |
302 | Color colors[] = {
303 | //NoShape
304 | new Color(0, 0, 0),
305 | //ZShape
306 | new Color(204, 102, 102),
307 | //oZ
308 | new Color(102, 204, 102),
309 | //L
310 | //I
311 | new Color(204, 102, 204),
312 | //T
313 | new Color(218, 170, 0),
314 | //Square
315 | new Color(102, 204, 204),
316 | new Color(102, 102, 204),
317 | //oL
318 | new Color(204, 204, 102)
319 | };
320 |
321 | Color color = colors[shape.ordinal()];
322 |
323 | g.setColor(color);
324 | g.fillRect(x + 4, y + 4, squareWidth() - 4, squareHeight() - 4);
325 |
326 | g.setColor(color.brighter());
327 | g.drawLine(x, y + squareHeight() - 2, x, y);
328 | g.drawLine(x, y, x + squareWidth() - 2, y);
329 |
330 | g.setColor(color.darker());
331 | g.drawLine(x + 2, y + squareHeight() - 2,
332 | x + squareWidth() - 2, y + squareHeight() - 2);
333 | g.drawLine(x + squareWidth() - 2, y + squareHeight() - 2,
334 | x + squareWidth() - 2, y + 2);
335 |
336 | }
337 | }
338 |
--------------------------------------------------------------------------------
/Tetris/MainMenu.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import javax.swing.*;
4 | import java.awt.*;
5 | import java.awt.event.ActionEvent;
6 | import java.awt.event.ActionListener;
7 | import java.awt.Graphics;
8 | import java.awt.image.BufferedImage;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.util.logging.Level;
12 | import java.util.logging.Logger;
13 | import javax.imageio.ImageIO;
14 | import javax.swing.JPanel;
15 |
16 |
17 |
18 | public class MainMenu extends JFrame {
19 | JButton onePlayer = new JButton("1 Player");
20 | JButton twoPlayers = new JButton("2 Players");
21 | JButton howToPlay = new JButton("How To Play");
22 | JButton exit = new JButton("Exit");
23 | JButton exit1 = new JButton("Back");
24 | JFrame MainMenuFr = new JFrame("Tetris Time!");
25 | int a = -1;
26 | ActionEvent e;
27 | Tetris game;
28 |
29 |
30 | public MainMenu() {
31 | addButtons();
32 | }
33 |
34 | public void addButtons() {
35 | onePlayer.setBounds(95, 50, 200, 80);
36 | twoPlayers.setBounds(95, 150, 200, 80);
37 | howToPlay.setBounds(95, 250, 200, 80);
38 | exit.setBounds(125, 400, 120, 40);
39 |
40 | MainMenuFr.add(onePlayer);
41 | MainMenuFr.add(twoPlayers);
42 | MainMenuFr.add(howToPlay);
43 | MainMenuFr.add(exit);
44 | try {
45 | ImageIcon image = new ImageIcon(getClass().getResource("thayThong.jpg"));
46 | JLabel displayField = new JLabel(image);
47 | MainMenuFr.add(displayField);
48 | } catch(Exception e) {
49 | System.out.println("Image cannot be found");
50 | }
51 | MainMenuFr.setSize(400, 500);
52 | //MainMenuFr.setLayout(null);
53 | MainMenuFr.setResizable(false);
54 | MainMenuFr.setVisible(true);
55 | MainMenuFr.setLocationRelativeTo(null);
56 |
57 |
58 | onePlayer.addActionListener(new ActionListener() {
59 |
60 | @Override
61 | public void actionPerformed(ActionEvent e) {
62 | a = 1;
63 | //System.out.println(getA());
64 | game = new Tetris(a);
65 | MainMenuFr.setVisible(false);
66 | game.setVisible(true);
67 | //System.exit(0);
68 | }
69 |
70 | });
71 |
72 | twoPlayers.addActionListener(new ActionListener() {
73 | @Override
74 | public void actionPerformed(ActionEvent e) {
75 | a = 2;
76 | //System.out.println(getA());
77 | game = new Tetris(a);
78 | MainMenuFr.setVisible(false);
79 | game.setVisible(true);
80 | //System.exit(0);
81 | }
82 | });
83 |
84 | howToPlay.addActionListener(new ActionListener() {
85 | @Override
86 | public void actionPerformed(ActionEvent e) {
87 | JFrame howToPlayButton = new JFrame();
88 | howToPlayButton.setSize(1000, 800);
89 | howToPlayButton.setVisible(true);
90 | howToPlayButton.setResizable(false);
91 | howToPlayButton.setLocationRelativeTo(null);
92 |
93 | exit1.setBounds(425, 700, 160, 40);
94 | howToPlayButton.add(exit1);
95 |
96 |
97 | try {
98 | ImageIcon image = new ImageIcon(getClass().getResource("kethop.png"));
99 | JLabel displayField = new JLabel(image);
100 | howToPlayButton.add(displayField);
101 | } catch (Exception i) {
102 | //System.out.println("Image cannot be found");
103 | }
104 |
105 |
106 | exit1.addActionListener(new ActionListener() {
107 | @Override
108 | public void actionPerformed(ActionEvent e) {
109 | // TODO Auto-generated method stub
110 | //System.out.println("0");
111 | howToPlayButton.setVisible(false);
112 |
113 | }
114 | });
115 | }
116 | });
117 |
118 | exit.addActionListener(new ActionListener() {
119 | @Override
120 | public void actionPerformed(ActionEvent e) {
121 | // TODO Auto-generated method stub
122 | //System.out.println("0");
123 | System.exit(0);
124 |
125 | }
126 | });
127 | }
128 |
129 | public int getA() {
130 | return a;
131 | }
132 | }
133 |
134 |
135 |
--------------------------------------------------------------------------------
/Tetris/Shape.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 | import java.util.Random;
3 |
4 | public class Shape {
5 |
6 | public enum Tetrominoes { NoShape, ZShape, oZShape, IShape,
7 | TShape, SquareShape, LShape, oLShape };
8 |
9 | private Tetrominoes pieceShape;
10 | private int coords[][] = new int[4][2];
11 | private int[][][] coordsTable;
12 |
13 |
14 | public Shape() {
15 | setShape(Tetrominoes.NoShape);
16 | }
17 |
18 | public Shape(Shape shape) {
19 | this.pieceShape = shape.pieceShape;
20 | for (int i = 0; i < 4; ++i) {
21 | this.setX(i, shape.x(i));
22 | this.setY(i, shape.y(i));
23 | }
24 | }
25 |
26 | public void setShape(Tetrominoes shape) {
27 |
28 | coordsTable = new int[][][] {
29 | //NoShape1
30 | {{0,0}, {0,0}, {0,0}, {0,0}},
31 | //ZShape2
32 | {{0,1}, {0,0}, {1,0}, {1,-1}},
33 | //oZShape3
34 | {{0,1}, {0,0}, {-1, 0}, {-1,-1}},
35 | //IShape6
36 | //{{2,0}, {1,0}, {0,0}, {-1,0}},
37 | {{ 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 }},
38 | //TShape7
39 | {{1,0}, {0,0}, {0,1}, {-1,0}},
40 | //SquareShape
41 | {{1,0}, {1,1}, {0,0}, {0,1}},
42 | //LShape4
43 | {{1,-1}, {0,-1}, {0,0}, {0,1}},
44 | //oLShape5
45 | {{0,-1}, {0,0}, {0,1}, {-1,-1}}
46 | };
47 |
48 | for (int i = 0; i < 4 ; i++) {
49 |
50 | for (int j = 0; j < 2; ++j) {
51 |
52 | coords[i][j] = coordsTable[shape.ordinal()][i][j];
53 | }
54 | }
55 |
56 | pieceShape = shape;
57 | }
58 |
59 |
60 |
61 |
62 | public void setRandomShape() {
63 |
64 | Random r = new Random();
65 | int x = Math.abs(r.nextInt()) % 7 + 1;
66 | Tetrominoes[] values = Tetrominoes.values();
67 | setShape(values[x]);
68 | }
69 |
70 | public int minX() {
71 |
72 | int m = coords[0][0];
73 |
74 | for (int i=0; i < 4; i++) {
75 |
76 | m = Math.min(m, coords[i][0]);
77 | }
78 |
79 | return m;
80 | }
81 |
82 |
83 | public int minY() {
84 |
85 | int m = coords[0][1];
86 |
87 | for (int i=0; i < 4; i++) {
88 |
89 | m = Math.min(m, coords[i][1]);
90 | }
91 |
92 | return m;
93 | }
94 |
95 | public int x(int index) {
96 | return coords[index][0];
97 | }
98 | public int y(int index) {
99 | return coords[index][1];
100 | }
101 | public Tetrominoes getShape() {
102 | return pieceShape;
103 | }
104 |
105 | private void setX(int index, int x) {
106 | coords[index][0] = x;
107 | }
108 |
109 | private void setY(int index, int y) {
110 | coords[index][1] = y;
111 | }
112 |
113 | public Shape rotateLeft() {
114 | if (pieceShape == Tetrominoes.SquareShape) {
115 | return this;
116 | }
117 |
118 | Shape result = new Shape();
119 | result.pieceShape = pieceShape;
120 | for (int i = 0; i < 4; ++i) {
121 | result.setX(i, y(i));
122 | result.setY(i, -x(i));
123 | }
124 | return result;
125 | }
126 |
127 | /*public Shape rotateRight() {
128 |
129 | if (pieceShape == Tetrominoes.SquareShape) {
130 | return this;
131 | }
132 |
133 | else if (pieceShape == Tetrominoes.IShape) {
134 |
135 | }
136 |
137 | else {
138 | Shape result = new Shape();
139 | result.pieceShape = pieceShape;
140 |
141 | for (int i = 0; i < 4; ++i) {
142 |
143 | result.setX(i, -y(i));
144 | result.setY(i, x(i));
145 | }
146 |
147 | return result;
148 | }
149 |
150 | } */
151 |
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/Tetris/TAdapter.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import java.awt.event.*;
4 | import java.util.ArrayList;
5 |
6 | public class TAdapter extends KeyAdapter {
7 | ArrayList boards = new ArrayList<>();
8 |
9 | public void addBoard(Board board) {
10 | boards.add(board);
11 | }
12 |
13 | @Override
14 | public void keyPressed(KeyEvent e) {
15 | /*
16 | if (!isStarted || curPiece.getShape() == Tetrominoes.NoShape) {
17 | return;
18 | }*/
19 |
20 | int keycode = e.getKeyCode();
21 |
22 | if (keycode == 'p' || keycode == 'P') {
23 | for(Board board : boards)
24 | board.pause();
25 | return;
26 | }
27 |
28 |
29 | /*if (isPaused)
30 | return;*/
31 |
32 | switch (boards.size()) {
33 | case 2:
34 | controlPlayer2(keycode);
35 | case 1:
36 | controlPlayer1(keycode);
37 | break;
38 | default:
39 | break;
40 | }
41 | }
42 |
43 | private void controlPlayer1(int keycode){
44 | Board board = boards.get(0);
45 | if (!board.isPaused) {
46 | switch (keycode) {
47 | case KeyEvent.VK_LEFT:
48 | board.tryMove(-1, 0);
49 | break;
50 |
51 | case KeyEvent.VK_RIGHT:
52 | board.tryMove(1, 0);
53 | break;
54 |
55 | case KeyEvent.VK_UP:
56 | board.rotateLeft();
57 | break;
58 |
59 | case KeyEvent.VK_DOWN:
60 | board.oneLineDown();
61 | break;
62 | case KeyEvent.VK_L:
63 | board.dropDown();
64 | break;
65 | case KeyEvent.VK_P:
66 | board.pause();
67 | break;
68 | }
69 | }
70 |
71 | }
72 |
73 | private void controlPlayer2(int keycode){
74 | Board board = boards.get(1);
75 | if (!board.isPaused) {
76 | switch (keycode) {
77 | case KeyEvent.VK_A:
78 | board.tryMove(-1, 0);
79 | break;
80 |
81 | case KeyEvent.VK_D:
82 | board.tryMove(1, 0);
83 | break;
84 |
85 | case KeyEvent.VK_W:
86 | board.rotateLeft();
87 | break;
88 |
89 | case KeyEvent.VK_S:
90 | board.oneLineDown();
91 | break;
92 |
93 | case KeyEvent.VK_G:
94 | board.dropDown();
95 | break;
96 | }
97 | }
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Tetris/Tetris.java:
--------------------------------------------------------------------------------
1 | package Tetris;
2 |
3 | import java.awt.*;
4 |
5 | import javax.sound.sampled.AudioSystem;
6 | import javax.swing.*;
7 |
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 |
11 |
12 | import java.io.FileInputStream;
13 | import java.io.FileNotFoundException;
14 |
15 | import java.io.File;
16 | import java.io.IOException;
17 | import java.util.Scanner;
18 |
19 | import javax.sound.sampled.*;
20 |
21 | public class Tetris extends JFrame {
22 | private JLabel statusbar;
23 | private JLabel statusbar1;
24 | static JPanel mainPanel = new JPanel();
25 | JButton playAgain;
26 | int player;
27 | static MainMenu a = new MainMenu();
28 |
29 | public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
30 |
31 | /* SwingUtilities.invokeLater(new Runnable() {
32 |
33 | @Override
34 | public void run() {
35 | while (a.getA() != -1) {
36 | int numberOfPlayer = a.getA();
37 | a.MainMenuFr.setVisible(false);
38 | if (numberOfPlayer == 1 || numberOfPlayer == 2) {
39 | Tetris game = new Tetris(numberOfPlayer);
40 | game.setVisible(true);
41 | System.out.print("da chay");
42 |
43 | }
44 | else {
45 | System.out.print("khong chay");
46 | }
47 | }
48 |
49 | }
50 | }); */
51 |
52 | }
53 |
54 | public void playSound() {{
55 | new Thread(new Runnable() {
56 | public void run() {
57 | try {
58 | AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("music.wav").getAbsoluteFile());
59 | Clip clip = AudioSystem.getClip();
60 | clip.open(audioInputStream);
61 | clip.start();
62 | } catch(Exception ex) {
63 | System.out.println("Error with playing sound.");
64 | ex.printStackTrace();
65 | }
66 | }
67 | }).start();
68 | }
69 | }
70 |
71 |
72 |
73 |
74 | public Tetris(int numberOfPlayer) {
75 | playSound();
76 | mainPanel = new JPanel();
77 | player = numberOfPlayer;
78 | playAgain = new JButton("Back To Menu?");
79 | playAgain.addActionListener(new ActionListener() {
80 | @Override
81 | public void actionPerformed(ActionEvent e) {
82 | setVisible(false);
83 | a.MainMenuFr.setVisible(true);
84 | }
85 | });
86 | add(playAgain);
87 | playAgain.setVisible(false);
88 | if (numberOfPlayer == 1) {
89 | //System.out.println("so 1");
90 | initUI();
91 | }
92 | else if (numberOfPlayer == 2) {
93 | //System.out.println("so 2");
94 | initUI2Players();
95 | }
96 |
97 | }
98 |
99 | int count = 0;
100 | public void gameOver() {
101 | count++;
102 | if(player == 1) {
103 | playAgain.setBounds(110 ,650, 180, 60);
104 | playAgain.setVisible(true);
105 | } else {
106 | if(count == 2){
107 | playAgain.setBounds(310 ,650, 180, 60);
108 | playAgain.setVisible(true);
109 | }
110 | }
111 | }
112 |
113 | private void initUI2Players() {
114 | TAdapter adapter = new TAdapter();
115 |
116 | statusbar = new JLabel(" 0");
117 |
118 |
119 | Board board = new Board(this, statusbar, adapter);
120 | board.add(statusbar, BorderLayout.PAGE_END);
121 | board.start();
122 |
123 | statusbar1 = new JLabel(" 0");
124 |
125 |
126 | Board board1 = new Board(this, statusbar1, adapter);
127 |
128 | board1.add(statusbar1, BorderLayout.PAGE_END);
129 | mainPanel.add(board1);
130 | mainPanel.add(board);
131 | board1.start();
132 |
133 |
134 |
135 | mainPanel.setLayout(new GridLayout(0, 2,5,2));
136 | mainPanel.setSize(800,800);
137 | setBackground(Color.black);
138 |
139 | add(mainPanel);
140 |
141 | setResizable(false);
142 |
143 | setSize(800, 800);
144 | setTitle("Tetris");
145 | setDefaultCloseOperation(EXIT_ON_CLOSE);
146 | setLocationRelativeTo(null);
147 | setResizable(false);
148 |
149 | //set mau nen
150 | board.setBackground(Color.DARK_GRAY);
151 | //board1.setBackground(Color.white);
152 |
153 |
154 |
155 | }
156 |
157 | public void initUI() {
158 | TAdapter adapter = new TAdapter();
159 |
160 | statusbar = new JLabel(" 0");
161 | add(statusbar, BorderLayout.SOUTH);
162 | Board board = new Board(this, statusbar, adapter);
163 | add(board);
164 | board.start();
165 |
166 | setSize(400, 800);
167 | setTitle("Tetris");
168 | setDefaultCloseOperation(EXIT_ON_CLOSE);
169 | setLocationRelativeTo(null);
170 | setResizable(false);
171 |
172 | //set mau nen
173 | board.setBackground(Color.black);
174 | }
175 |
176 |
177 | // public JLabel getStatusBar() {
178 |
179 | // return statusbar;
180 | // }
181 | }
--------------------------------------------------------------------------------
/Tetris/kethop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/Tetris/kethop.png
--------------------------------------------------------------------------------
/Tetris/muiten.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/Tetris/muiten.png
--------------------------------------------------------------------------------
/Tetris/music1.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/Tetris/music1.mp3
--------------------------------------------------------------------------------
/Tetris/thayThong.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/Tetris/thayThong.jpg
--------------------------------------------------------------------------------
/Tetris/wasd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/Tetris/wasd.png
--------------------------------------------------------------------------------
/ThuanTheBadLuckCoder:
--------------------------------------------------------------------------------
1 | ## 🌐 Socials:
2 | [](https://discord.gg/silov#0656) [](https://facebook.com/dontrnthun) [](https://instagram.com/dtr_thuann) [](https://linkedin.com/in/dtrthuann) [](https://tiktok.com/@dtrnthun) [](https://twitter.com/dtr_thuann)
3 |
4 | # 💻 Tech Stack:
5 |                      
6 | # 📊 GitHub Stats:
7 | 
8 | 
9 | 
10 |
11 | ## 🐦 Latest Tweet
12 | [](https://github.com/VishwaGauravIn/github-twitter-card-embed)
13 |
14 | ### ✍️ Random Dev Quote
15 | 
16 |
17 | ### 🔝 Top Contributed Repo
18 | 
19 |
20 | ---
21 | [](https://visitcount.itsvg.in)
22 |
--------------------------------------------------------------------------------
/kethop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/kethop.png
--------------------------------------------------------------------------------
/muiten.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/muiten.png
--------------------------------------------------------------------------------
/music1.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/music1.mp3
--------------------------------------------------------------------------------
/thayThong.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/thayThong.jpg
--------------------------------------------------------------------------------
/wasd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ThuanTheBadLuckCoder/Tetris/d3b2d60f6eae9713b5c4f772178dedc113b13a40/wasd.png
--------------------------------------------------------------------------------