大家好,我是百思不得小趙。
創(chuàng)作時間:2022 年 5 月 12 日
博客主頁: ??點此進入博客主頁
—— 新時代的農民工 ??
—— 換一種思維邏輯去看待這個世界 ??
今天是加入CSDN的第1167天。覺得有幫助麻煩??點贊、??評論、??收藏
目錄
一、游戲背景
二、功能實現(xiàn)
三、效果展示
一、游戲背景
俄羅斯方塊是俄羅斯人發(fā)明的。這人叫阿列克謝·帕基特諾夫(Алексей Пажитнов 英文:Alexey Pazhitnov)。俄羅斯方塊原名是俄語Тетрис(英語是Tetris),這個名字來源于希臘語tetra,意思是“四”,而游戲的作者最喜歡網(wǎng)球(tennis)。于是,他把兩個詞tetra和tennis合而為一,命名為Tetris,這也就是俄羅斯方塊名字的由來。
規(guī)則說明:
由小方塊組成的不同形狀的板塊陸續(xù)從屏幕上方落下來,玩家通過調整板塊的位置和方向,使它們在屏幕底部拼出完整的一條或幾條。這些完整的橫條會隨即消失,給新落下來的板塊騰出空間,與此同時,玩家得到分數(shù)獎勵。沒有被消除掉的方塊不斷堆積起來,一旦堆到屏幕頂端,玩家便告輸,游戲結束。
二、功能實現(xiàn)
開發(fā)工具:idea、jdk8
技術匯總:Java基礎知識、數(shù)組、面向對象、多線程、IO流、Swing。
整體代碼分為三個模塊:方格模塊,七種圖形模塊,俄羅斯方塊主模塊。
小方塊類:Cell
public class Cell {
// 行
private int row;
// 列
private int col;
private BufferedImage image;
public Cell() {
}
public Cell(int row, int col, BufferedImage image) {
this.row = row;
this.col = col;
this.image = image;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public BufferedImage getImage() {
return image;
}
public void setImage(BufferedImage image) {
this.image = image;
}
@Override
public String toString() {
return "Cell{" +
"row=" + row +
", col=" + col +
", image=" + image +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Cell)) {
return false;
}
Cell cell = (Cell) o;
return getRow() == cell.getRow() &&
getCol() == cell.getCol() &&
Objects.equals(getImage(), cell.getImage());
}
@Override
public int hashCode() {
return Objects.hash(getRow(), getCol(), getImage());
}
//左移動一格
public void left(){
col--;
}
//右移動一格
public void right(){
col++;
}
//下移動一格
public void down(){
row++;
}
}
?四方格圖形的父類:Tetromino
public class Tetromino {
public Cell[] cells = new Cell[4];
//旋轉的狀態(tài)
protected State[] states;
//聲明旋轉次數(shù)
protected int count = 10000;
//左移方法
public void moveLeft() {
for (Cell cell : cells) {
cell.left();
}
}
//右移方法
public void moveRight() {
for (Cell cell : cells) {
cell.right();
}
}
//單元格下落
public void moveDrop() {
for (Cell cell : cells) {
cell.down();
}
}
//編寫隨機生成四方格
public static Tetromino randomOne() {
int num = (int) (Math.random() * 7);
Tetromino tetromino = null;
switch (num) {
case 0:
tetromino = new I();
break;
case 1:
tetromino = new J();
break;
case 2:
tetromino = new L();
break;
case 3:
tetromino = new O();
break;
case 4:
tetromino = new S();
break;
case 5:
tetromino = new T();
break;
case 6:
tetromino = new Z();
break;
}
return tetromino;
}
//順時針旋轉的方法
public void rotateRight() {
if (states.length == 0) {
return;
}
//旋轉次數(shù)+1
count++;
State s = states[count % states.length];
Cell cell = cells[0];
int row = cell.getRow();
int col = cell.getCol();
cells[1].setRow(row + s.row1);
cells[1].setCol(col + s.col1);
cells[2].setRow(row + s.row2);
cells[2].setCol(col + s.col2);
cells[3].setRow(row + s.row3);
cells[3].setCol(col + s.col3);
}
//逆時針旋轉的方法
public void rotateLeft() {
if (states.length == 0) {
return;
}
//旋轉次數(shù)+1
count--;
State s = states[count % states.length];
Cell cell = cells[0];
int row = cell.getRow();
int col = cell.getCol();
cells[1].setRow(row + s.row1);
cells[1].setCol(col + s.col1);
cells[2].setRow(row + s.row2);
cells[2].setCol(col + s.col2);
cells[3].setRow(row + s.row3);
cells[3].setCol(col + s.col3);
}
//四方格旋轉狀態(tài)的內部類
protected class State {
//存儲四方格各元素的位置
int row0, col0, row1, col1, row2, col2, row3, col3;
public State() {
}
public State(int row0, int col0, int row1, int col1, int row2, int col2, int row3, int col3) {
this.row0 = row0;
this.col0 = col0;
this.row1 = row1;
this.col1 = col1;
this.row2 = row2;
this.col2 = col2;
this.row3 = row3;
this.col3 = col3;
}
public int getRow0() {
return row0;
}
public void setRow0(int row0) {
this.row0 = row0;
}
public int getCol0() {
return col0;
}
public void setCol0(int col0) {
this.col0 = col0;
}
public int getRow1() {
return row1;
}
public void setRow1(int row1) {
this.row1 = row1;
}
public int getCol1() {
return col1;
}
public void setCol1(int col1) {
this.col1 = col1;
}
public int getRow2() {
return row2;
}
public void setRow2(int row2) {
this.row2 = row2;
}
public int getCol2() {
return col2;
}
public void setCol2(int col2) {
this.col2 = col2;
}
public int getRow3() {
return row3;
}
public void setRow3(int row3) {
this.row3 = row3;
}
public int getCol3() {
return col3;
}
public void setCol3(int col3) {
this.col3 = col3;
}
@Override
public String toString() {
return "State{" +
"row0=" + row0 +
", col0=" + col0 +
", row1=" + row1 +
", col1=" + col1 +
", row2=" + row2 +
", col2=" + col2 +
", row3=" + row3 +
", col3=" + col3 +
'}';
}
}
}
七種圖形類:I、J、L、O、S、T、Z
public class I extends Tetromino {
public I() {
cells[0] = new Cell(0,4, Tetris.I);
cells[1] = new Cell(0,3, Tetris.I);
cells[2] = new Cell(0,5, Tetris.I);
cells[3] = new Cell(0,6, Tetris.I);
//共有兩種旋轉狀態(tài)
states =new State[2];
//初始化兩種狀態(tài)的相對坐標
states[0]=new State(0,0,0,-1,0,1,0,2);
states[1]=new State(0,0,-1,0,1,0,2,0);
}
}
public class J extends Tetromino {
public J() {
cells[0] = new Cell(0,4, Tetris.J);
cells[1] = new Cell(0,3, Tetris.J);
cells[2] = new Cell(0,5, Tetris.J);
cells[3] = new Cell(1,5, Tetris.J);
states=new State[4];
states[0]=new State(0,0,0,-1,0,1,1,1);
states[1]=new State(0,0,-1,0,1,0,1,-1);
states[2]=new State(0,0,0,1,0,-1,-1,-1);
states[3]=new State(0,0,1,0,-1,0,-1,1);
}
}
public class L extends Tetromino {
public L() {
cells[0] = new Cell(0,4, Tetris.L);
cells[1] = new Cell(0,3, Tetris.L);
cells[2] = new Cell(0,5, Tetris.L);
cells[3] = new Cell(1,3, Tetris.L);
states=new State[4];
states[0]=new State(0,0,0,-1,0,1,1,-1);
states[1]=new State(0,0,-1,0,1,0,-1,-1);
states[2]=new State(0,0,0,1,0,-1,-1,1);
states[3]=new State(0,0,1,0,-1,0,1,1);
}
}
public class O extends Tetromino {
public O() {
cells[0] = new Cell(0, 4, Tetris.O);
cells[1] = new Cell(0, 5, Tetris.O);
cells[2] = new Cell(1, 4, Tetris.O);
cells[3] = new Cell(1, 5, Tetris.O);
//無旋轉狀態(tài)
states = new State[0];
}
}
public class S extends Tetromino {
public S() {
cells[0] = new Cell(0,4, Tetris.S);
cells[1] = new Cell(0,5, Tetris.S);
cells[2] = new Cell(1,3, Tetris.S);
cells[3] = new Cell(1,4, Tetris.S);
//共有兩種旋轉狀態(tài)
states =new State[2];
//初始化兩種狀態(tài)的相對坐標
states[0]=new State(0,0,0,1,1,-1,1,0);
states[1]=new State(0,0,1,0,-1,-1,0,-1);
}
}
public class T extends Tetromino {
public T() {
cells[0] = new Cell(0,4, Tetris.T);
cells[1] = new Cell(0,3, Tetris.T);
cells[2] = new Cell(0,5, Tetris.T);
cells[3] = new Cell(1,4, Tetris.T);
states=new State[4];
states[0]=new State(0,0,0,-1,0,1,1,0);
states[1]=new State(0,0,-1,0,1,0,0,-1);
states[2]=new State(0,0,0,1,0,-1,-1,0);
states[3]=new State(0,0,1,0,-1,0,0,1);
}
}
public class Z extends Tetromino {
public Z() {
cells[0] = new Cell(1,4, Tetris.Z);
cells[1] = new Cell(0,3, Tetris.Z);
cells[2] = new Cell(0,4, Tetris.Z);
cells[3] = new Cell(1,5, Tetris.Z);
//共有兩種旋轉狀態(tài)
states =new State[2];
//初始化兩種狀態(tài)的相對坐標
states[0]=new State(0,0,-1,-1,-1,0,0,1);
states[1]=new State(0,0,-1,1,0,1,1,0);
}
}
俄羅斯方塊游戲主類:Tetris
public class Tetris extends JPanel {
//正在下落的方塊
private Tetromino currentOne = Tetromino.randomOne();
//將要下落的方塊
private Tetromino nextOne = Tetromino.randomOne();
//游戲主區(qū)域
private Cell[][] wall = new Cell[18][9];
//聲明單元格的值
private static final int CELL_SIZE = 48;
//游戲分數(shù)池
int[] scores_pool = {0, 1, 2, 5, 10};
//當前游戲的分數(shù)
private int totalScore = 0;
//當前消除的行數(shù)
private int totalLine = 0;
//游戲三種狀態(tài) 游戲中、暫停、結束
public static final int PLING = 0;
public static final int STOP = 1;
public static final int OVER = 2;
//當前游戲狀態(tài)值
private int game_state;
//顯示游戲狀態(tài)
String[] show_state = {"P[pause]", "C[continue]", "S[replay]"};
//載入方塊圖片
public static BufferedImage I;
public static BufferedImage J;
public static BufferedImage L;
public static BufferedImage O;
public static BufferedImage S;
public static BufferedImage T;
public static BufferedImage Z;
public static BufferedImage background;
static {
try {
I = ImageIO.read(new File("images/I.png"));
J = ImageIO.read(new File("images/J.png"));
L = ImageIO.read(new File("images/L.png"));
O = ImageIO.read(new File("images/O.png"));
S = ImageIO.read(new File("images/S.png"));
T = ImageIO.read(new File("images/T.png"));
Z = ImageIO.read(new File("images/Z.png"));
background = ImageIO.read(new File("images/background.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void paint(Graphics g) {
g.drawImage(background, 0, 0, null);
//平移坐標軸
g.translate(22, 15);
//繪制游戲主區(qū)域
paintWall(g);
//繪制正在下落的四方格
paintCurrentOne(g);
//繪制下一個將要下落的四方格
paintNextOne(g);
//繪制游戲得分
paintSource(g);
//繪制當前游戲狀態(tài)
paintState(g);
}
public void start() {
game_state = PLING;
KeyListener l = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
switch (code) {
case KeyEvent.VK_DOWN:
sortDropActive();
break;
case KeyEvent.VK_LEFT:
moveleftActive();
break;
case KeyEvent.VK_RIGHT:
moveRightActive();
break;
case KeyEvent.VK_UP:
rotateRightActive();
break;
case KeyEvent.VK_SPACE:
hadnDropActive();
break;
case KeyEvent.VK_P:
//判斷當前游戲狀態(tài)
if (game_state == PLING) {
game_state = STOP;
}
break;
case KeyEvent.VK_C:
if (game_state == STOP) {
game_state = PLING;
}
break;
case KeyEvent.VK_S:
//重新開始
game_state = PLING;
wall = new Cell[18][9];
currentOne = Tetromino.randomOne();
nextOne = Tetromino.randomOne();
totalScore = 0;
totalLine = 0;
break;
}
}
};
//將窗口設置為焦點
this.addKeyListener(l);
this.requestFocus();
while (true) {
if (game_state == PLING) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (camDrop()) {
currentOne.moveDrop();
} else {
landToWall();
destroyLine();
if (isGameOver()) {
game_state = OVER;
} else {
//游戲沒有結束
currentOne = nextOne;
nextOne = Tetromino.randomOne();
}
}
}
repaint();
}
}
//創(chuàng)建順時針旋轉
public void rotateRightActive() {
currentOne.rotateRight();
if (outOFBounds() || coincide()) {
currentOne.rotateLeft();
}
}
//瞬間下落
public void hadnDropActive() {
while (true) {
//判斷能否下落
if (camDrop()) {
currentOne.moveDrop();
} else {
break;
}
}
//嵌入到墻中
landToWall();
destroyLine();
if (isGameOver()) {
game_state = OVER;
} else {
//游戲沒有結束
currentOne = nextOne;
nextOne = Tetromino.randomOne();
}
}
//按鍵一次,下落一格
public void sortDropActive() {
if (camDrop()) {
//當前四方格下落一格
currentOne.moveDrop();
} else {
landToWall();
destroyLine();
if (isGameOver()) {
game_state = OVER;
} else {
//游戲沒有結束
currentOne = nextOne;
nextOne = Tetromino.randomOne();
}
}
}
//單元格嵌入墻中
private void landToWall() {
Cell[] cells = currentOne.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
wall[row][col] = cell;
}
}
//判斷四方格能否下落
public boolean camDrop() {
Cell[] cells = currentOne.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
//判斷是否到達底部
if (row == wall.length - 1) {
return false;
} else if (wall[row + 1][col] != null) {
return false;
}
}
return true;
}
//消除行
public void destroyLine() {
int line = 0;
Cell[] cells = currentOne.cells;
for (Cell cell : cells) {
int row = cell.getRow();
if (isFullLine(row)) {
line++;
for (int i = row; i > 0; i--) {
System.arraycopy(wall[i - 1], 0, wall[i], 0, wall[0].length);
}
wall[0] = new Cell[9];
}
}
//分數(shù)池獲取分數(shù),累加到總分
totalScore += scores_pool[line];
//總行數(shù)
totalLine += line;
}
//判斷當前行是否已經(jīng)滿了
public boolean isFullLine(int row) {
Cell[] cells = wall[row];
for (Cell cell : cells) {
if (cell == null) {
return false;
}
}
return true;
}
//判斷游戲是否結束
public boolean isGameOver() {
Cell[] cells = nextOne.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
if (wall[row][col] != null) {
return true;
}
}
return false;
}
private void paintState(Graphics g) {
if (game_state == PLING) {
g.drawString(show_state[PLING], 500, 660);
} else if (game_state == STOP) {
g.drawString(show_state[STOP], 500, 660);
} else {
g.drawString(show_state[OVER], 500, 660);
g.setColor(Color.RED);
g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 60));
g.drawString("GAME OVER!", 30, 400);
}
}
private void paintSource(Graphics g) {
g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 30));
g.drawString("分數(shù): " + totalScore, 500, 250);
g.drawString("行數(shù): " + totalLine, 500, 430);
}
private void paintNextOne(Graphics g) {
Cell[] cells = nextOne.cells;
for (Cell cell : cells) {
int x = cell.getCol() * CELL_SIZE + 370;
int y = cell.getRow() * CELL_SIZE + 25;
g.drawImage(cell.getImage(), x, y, null);
}
}
private void paintCurrentOne(Graphics g) {
Cell[] cells = currentOne.cells;
for (Cell cell : cells) {
int x = cell.getCol() * CELL_SIZE;
int y = cell.getRow() * CELL_SIZE;
g.drawImage(cell.getImage(), x, y, null);
}
}
private void paintWall(Graphics g) {
for (int i = 0; i < wall.length; i++) {
for (int j = 0; j < wall[i].length; j++) {
int x = j * CELL_SIZE;
int y = i * CELL_SIZE;
Cell cell = wall[i][j];
//判斷是否有小方塊
if (cell == null) {
g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
} else {
g.drawImage(cell.getImage(), x, y, null);
}
}
}
}
//判斷是否出界
public boolean outOFBounds() {
Cell[] cells = currentOne.cells;
for (Cell cell : cells) {
int col = cell.getCol();
int row = cell.getRow();
if (row < 0 || row > wall.length - 1 || col < 0 || col > wall[0].length-1) {
return true;
}
}
return false;
}
//按鍵一次,左移一次
public void moveleftActive() {
currentOne.moveLeft();
//判斷是否越界或重合
if (outOFBounds() || coincide()) {
currentOne.moveRight();
}
}
//按鍵一次,右移一次
public void moveRightActive() {
currentOne.moveRight();
//判斷是否越界或重合
if (outOFBounds() || coincide()) {
currentOne.moveLeft();
}
}
//判斷是否重合
public boolean coincide() {
Cell[] cells = currentOne.cells;
for (Cell cell : cells) {
int row = cell.getRow();
int col = cell.getCol();
if (wall[row][col] != null) {
return true;
}
}
return false;
}
public static void main(String[] args) {
JFrame jFrame = new JFrame("俄羅斯方塊");
//創(chuàng)建游戲界面
Tetris panel = new Tetris();
jFrame.add(panel);
//設置可見
jFrame.setVisible(true);
//設置窗口大小
jFrame.setSize(810, 940);
//設置劇中
jFrame.setLocationRelativeTo(null);
//設置窗口關閉時停止
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//游戲主要開始邏輯
panel.start();
}
}
三、效果展示
游戲開始,方快下落,右邊區(qū)域展示即將下落的方塊圖、分數(shù)、消除的行數(shù)以及游戲切換的狀態(tài)。
按下空格鍵,方塊瞬間下落, 按下P鍵游戲暫停,消除一行分數(shù)為1(此處由分數(shù)池進行控制)
?按下C鍵游戲繼續(xù)。
?按下S鍵,游戲重新開始。
?方塊占滿,游戲結束,此時可以按下S鍵重新開始游戲。
本次游戲中所使用的素材文件以及所有的源代碼文件都已經(jīng)同步到Github,小伙伴們點擊下方鏈接直接獲取。
Github鏈接地址:點擊獲取完整源代碼,下載到本地即可運行https://github.com/xiaoZ-zhao/Tetris
Gitee地址:Tetris: 【開箱即用】使用Java實現(xiàn)俄羅斯方塊,開發(fā)工具idea - Gitee.comhttps://gitee.com/xiaoZcode/Tetris/tree/master文章來源:http://www.zghlxwxcb.cn/news/detail-777089.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-777089.html
到了這里,關于Java實現(xiàn)俄羅斯方塊小游戲。(附完整源代碼)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!