java代碼實現(xiàn)俄羅斯方塊
本文實例為大家分享了java實現(xiàn)俄羅斯方塊的具體代碼,供大家參考,具體內(nèi)容如下
俄羅斯方塊設(shè)計思想
俄羅斯方塊都從小玩到大吧,什么規(guī)則大家都知道了吧,以前感覺那玩意賊好玩,但是就是老贏不了,現(xiàn)在學會了自己寫一個天天練!
鍵盤操作:
左鍵:左移; 右鍵:右移;
上鍵:變換造型 下鍵:加速下掉(沒毛病吧,沒有繼續(xù)整)
任意一行的方塊滿格,這一行就消除,消除一行方塊得10分,目前小主我還沒有設(shè)置關(guān)卡,各位喜歡的寶寶們可以自己設(shè)置關(guān)卡哦;
那么那些方塊的造型到底從哪里來的呢,那就是我們自己設(shè)計的,常見的幾種造型就是:I型,T型,L型,田字格型等等吧,自己個加唄!
那么到底咋整的咧?其實啊就是一個4*4的數(shù)組,當然了你開心設(shè)計n*n也可以,你牛皮你說了算!
那么下面舉了一個例子,用來告訴你們?yōu)樯赌銈兛匆姷脑煨涂梢宰儞Q的原因就是這樣提前設(shè)計好,0為空,1為填充格,這樣你就可以在你的游戲里面凹造型了!

算了:直接放圖先看代碼運行結(jié)果吧:

喜歡嗎?喜歡就直接做吧,可能代碼寫的不夠好,請各位大神多多包涵,我回頭也會多總結(jié),會不斷更新代碼的;
GamePanel類:游戲界面類,整個方塊掉落和顯示,游戲的邏輯斯洛都在這個類里面實現(xiàn);
package tetris;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements KeyListener{
private int mapRow = 21;
private int mapCol = 12;
private int mapGame[][] = new int[mapRow][mapCol];//開辟一個二維數(shù)組空間,用來存放我們的地圖信息
private Timer timer;
private int score = 0;//記錄成績
Random random = new Random();
private int curShapeType = -1;
private int curShapeState = -1;//設(shè)置當前的形狀類型和當前的形狀狀態(tài)
private int nextShapeType = -1;
private int nextShapeState = -1;//設(shè)置下一次出現(xiàn)的方塊組的類型和狀態(tài)
private int posx = 0;
private int posy = 0;
private final int shapes[][][] = new int[][][]{
//T字形按逆時針的順序存儲
{
{0,1,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0},
{0,1,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0},
{1,1,1,0, 0,1,0,0, 0,0,0,0, 0,0,0,0},
{0,1,0,0, 0,1,1,0, 0,1,0,0, 0,0,0,0}
},
//I字形按逆時針的順序存儲
{
{0,0,0,0, 1,1,1,1, 0,0,0,0, 0,0,0,0},
{0,1,0,0, 0,1,0,0, 0,1,0,0, 0,1,0,0},
{0,0,0,0, 1,1,1,1, 0,0,0,0, 0,0,0,0},
{0,1,0,0, 0,1,0,0, 0,1,0,0, 0,1,0,0}
},
//倒Z形按逆時針的順序存儲
{
{0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
{1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0},
{0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
{1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0}
},
//Z形按逆時針的順序存儲
{
{1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0},
{0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0},
{1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0},
{0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0}
},
//J字形按逆時針的順序存儲
{
{0,1,0,0, 0,1,0,0, 1,1,0,0, 0,0,0,0},
{1,1,1,0, 0,0,1,0, 0,0,0,0, 0,0,0,0},
{1,1,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0},
{1,0,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0}
},
//L字形按逆時針的順序存儲
{
{1,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0},
{0,0,1,0, 1,1,1,0, 0,0,0,0, 0,0,0,0},
{1,1,0,0, 0,1,0,0, 0,1,0,0, 0,0,0,0},
{1,1,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0}
},
//田字形按逆時針的順序存儲
{
{1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
{1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
{1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
{1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0}
}
};
private int rowRect = 4;
private int colRect = 4;//這里我們把存儲的圖像看成是一個4*4的二維數(shù)組,雖然在上面我們采用一維數(shù)組來存儲,但實際還是要看成二維數(shù)組來實現(xiàn)
private int RectWidth = 10;
public GamePanel()//構(gòu)造函數(shù)----創(chuàng)建好地圖
{
CreateRect();
initMap();//初始化這個地圖
SetWall();//設(shè)置墻
// CreateRect();
timer = new Timer(500,new TimerListener());
timer.start();
}
class TimerListener implements ActionListener{
public void actionPerformed(ActionEvent e)
{
MoveDown();
}
}
public void SetWall()//第0列和第11列都是墻,第20行也是墻
{
for(int i = 0; i < mapRow; i++)//先畫列
{
mapGame[i][0] = 2;
mapGame[i][11] = 2;
}
for(int j = 1; j < mapCol-1; j++)//畫最后一行
{
mapGame[20][j] = 2;
}
}
public void initMap()//初始化這個地圖,墻的ID是2,空格的ID是0,方塊的ID是1
{
for(int i = 0; i < mapRow; i++)
{
for(int j = 0; j < mapCol; j++)
{
mapGame[i][j] = 0;
}
}
}
public void CreateRect()//創(chuàng)建方塊---如果當前的方塊類型和狀態(tài)都存在就設(shè)置下一次的,如果不存在就設(shè)置當前的并且設(shè)置下一次的狀態(tài)和類型
{
if(curShapeType == -1 && curShapeState == -1)//當前的方塊狀態(tài)都為1,表示游戲才開始
{
curShapeType = random.nextInt(shapes.length);
curShapeState = random.nextInt(shapes[0].length);
}
else
{
curShapeType = nextShapeType;
curShapeState = nextShapeState;
}
nextShapeType = random.nextInt(shapes.length);
nextShapeState = random.nextInt(shapes[0].length);
posx = 0;
posy = 1;//墻的左上角創(chuàng)建方塊
if(GameOver(posx,posy,curShapeType,curShapeState))
{
JOptionPane.showConfirmDialog(null, "游戲結(jié)束!", "提示", JOptionPane.OK_OPTION);
System.exit(0);
}
}
public boolean GameOver(int x, int y, int ShapeType, int ShapeState)//判斷游戲是否結(jié)束
{
if(IsOrNoMove(x,y,ShapeType,ShapeState))
{
return false;
}
return true;
}
public boolean IsOrNoMove(int x, int y, int ShapeType, int ShapeState)//判斷當前的這個圖形是否可以移動,這里重點強調(diào)x,y的坐標是指4*4的二維數(shù)組(描述圖形的那個數(shù)組)的左上角目標
{
for(int i = 0; i < rowRect ; i++)
{
for(int j = 0; j < colRect; j++)
{
if(shapes[ShapeType][ShapeState][i*colRect+j] == 1 && mapGame[x+i][y+j] == 1
|| shapes[ShapeType][ShapeState][i*colRect+j] == 1 && mapGame[x+i][y+j] == 2)
{
return false;
}
}
}
return true;
}
public void Turn()//旋轉(zhuǎn)
{
int temp = curShapeState;
curShapeState = (curShapeState+1) % shapes[0].length;
if(IsOrNoMove(posx,posy,curShapeType,curShapeState))
{
}
else
{
curShapeState = temp;
}
repaint();
}
public void MoveDown()//向下移動
{
if(IsOrNoMove(posx+1,posy,curShapeType,curShapeState))
{
posx++;
}
else
{
AddToMap();//將此行固定在地圖中
CheckLine();
CreateRect();//重新創(chuàng)建一個新的方塊
}
repaint();
}
public void MoveLeft()//向左移動
{
if(IsOrNoMove(posx,posy-1,curShapeType,curShapeState))
{
posy--;
}
repaint();
}
public void MoveRight()//向右移動
{
if(IsOrNoMove(posx,posy+1,curShapeType,curShapeState))
{
posy++;
}
repaint();
}
public void AddToMap()//固定掉下來的這一圖像到地圖中
{
for(int i = 0; i < rowRect; i++)
{
for(int j = 0; j < colRect; j++)
{
if(shapes[curShapeType][curShapeState][i*colRect+j] == 1)
{
mapGame[posx+i][posy+j] = shapes[curShapeType][curShapeState][i*colRect+j];
}
}
}
}
public void CheckLine()//檢查一下這些行中是否有滿行的
{
int count = 0;
for(int i = mapRow-2; i >= 0; i--)
{
count = 0;
for(int j = 1; j < mapCol-1; j++)
{
if(mapGame[i][j] == 1)
{
count++;
}
else
break;
}
if(count >= mapCol-2)
{
for(int k = i; k > 0; k--)
{
for(int p = 1; p < mapCol-1; p++)
{
mapGame[k][p] = mapGame[k-1][p];
}
}
score += 10;
i++;
}
}
}
public void paint(Graphics g)//重新繪制窗口
{
super.paint(g);
for(int i = 0; i < rowRect; i++)//繪制正在下落的方塊
{
for(int j = 0; j < colRect; j++)
{
if(shapes[curShapeType][curShapeState][i*colRect+j] == 1)
{
g.fillRect((posy+j+1)*RectWidth, (posx+i+1)*RectWidth, RectWidth, RectWidth);
}
}
}
for(int i = 0; i < mapRow; i++)//繪制地圖上面已經(jīng)固定好的方塊信息
{
for(int j = 0; j < mapCol; j++)
{
if(mapGame[i][j] == 2)//畫墻
{
g.drawRect((j+1)*RectWidth, (i+1)*RectWidth, RectWidth, RectWidth);
}
if(mapGame[i][j] == 1)//畫小方格
{
g.fillRect((j+1)*RectWidth, (i+1)*RectWidth, RectWidth, RectWidth);
}
}
}
g.drawString("score = "+ score, 225, 15);
g.drawString("下一個方塊:", 225, 50);
for(int i = 0; i < rowRect; i++)
{
for(int j = 0; j < colRect; j++)
{
if(shapes[nextShapeType][nextShapeState][i*colRect+j] == 1)
{
g.fillRect(225+(j*RectWidth), 100+(i*RectWidth), RectWidth, RectWidth);
}
}
}
}
public void NewGame()//游戲重新開始
{
score = 0;
initMap();
SetWall();
CreateRect();
repaint();
}
public void StopGame()//游戲暫停
{
timer.stop();
}
public void ContinueGame()
{
timer.start();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode())
{
case KeyEvent.VK_UP://上----旋轉(zhuǎn)
Turn();
break;
case KeyEvent.VK_DOWN://下----向下移動
MoveDown();
break;
case KeyEvent.VK_LEFT://左----向左移動
MoveLeft();
break;
case KeyEvent.VK_RIGHT://右----向右移動
MoveRight();
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
GameFrame類:整個游戲的進入口,好吧,說白了就是有main()函數(shù)的類,這個類里面實現(xiàn)游戲界面的一些設(shè)計,你可以理解為一個小小小小的UI;
package tetris;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
public class GameFrame extends JFrame implements ActionListener{
private int widthFrame = 500;
private int heightFrame = 600;
private JMenu menuone = new JMenu("游戲");//創(chuàng)建一個菜單
private JMenuItem newGame = menuone.add("重新開始");//創(chuàng)建一個內(nèi)置菜單選項
private JMenuItem exitGame = menuone.add("游戲退出");
private JMenuItem stopGame = menuone.add("游戲暫停");
private JMenuItem goOnGame = menuone.add("游戲繼續(xù)");
private JMenu menutwo = new JMenu("幫助");//創(chuàng)建第二個菜單
private JMenuItem aboutGame = menutwo.add("關(guān)于游戲");
GamePanel gamepanel = new GamePanel();
public GameFrame()//構(gòu)造函數(shù)
{
addKeyListener(gamepanel);
newGame.addActionListener(this);
exitGame.addActionListener(this);
stopGame.addActionListener(this);
goOnGame.addActionListener(this);
aboutGame.addActionListener(this);
this.add(gamepanel);
JMenuBar menu = new JMenuBar();
menu.add(menuone);
menu.add(menutwo);
this.setJMenuBar(menu);
this.setTitle("俄羅斯方塊");
this.setBounds(50, 10, widthFrame, heightFrame);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == newGame)//游戲重新開始
{
gamepanel.NewGame();
}
if(e.getSource() == exitGame)//游戲退出
{
System.exit(0);
}
if(e.getSource() == stopGame)//游戲暫停
{
gamepanel.StopGame();
}
if(e.getSource() == goOnGame)//游戲繼續(xù)
{
gamepanel.ContinueGame();
}
if(e.getSource() == aboutGame)//關(guān)于游戲信息
{
JOptionPane.showMessageDialog(null, "左右鍵移動,向上建旋轉(zhuǎn)", "提示", JOptionPane.OK_OPTION);
}
}
public static void main(String[] args) {
new GameFrame();
}
}
更多關(guān)于俄羅斯方塊的文章,請點擊查看專題:《俄羅斯方塊》
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MyBatis使用自定義TypeHandler轉(zhuǎn)換類型的實現(xiàn)方法
這篇文章主要介紹了MyBatis使用自定義TypeHandler轉(zhuǎn)換類型的實現(xiàn)方法,本文介紹使用TypeHandler 實現(xiàn)日期類型的轉(zhuǎn)換,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-10-10
在 Spring Boot 項目中實現(xiàn)文件下載功能
這篇文章主要介紹了在 Spring Boot 項目中實現(xiàn)文件下載功能,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09
spring boot RestTemplate 發(fā)送get請求的踩坑及解決
這篇文章主要介紹了spring boot RestTemplate 發(fā)送get請求的踩坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
springboot優(yōu)雅獲取前端參數(shù)的方法詳解
現(xiàn)在的項目基本上都是前后端分離的項目,如何打通前后端,接收前端傳過來的參數(shù)呢,這篇文章小編就來和大家詳細介紹一下springboot如何優(yōu)雅的獲取前端參數(shù)吧2024-03-03
關(guān)于TransmittableThreadLocal線程池中線程復用問題的解決方案
這篇文章主要介紹了關(guān)于TransmittableThreadLocal線程池中線程復用問題的解決方案,線程池復用線程,如果子線程執(zhí)行完未移除上下文,則會導致后續(xù)線程可以取到之前線程設(shè)置的屬性,需要的朋友可以參考下2023-11-11
Spring Data JPA 如何使用QueryDsl查詢并分頁
這篇文章主要介紹了Spring Data JPA 如何使用QueryDsl查詢并分頁,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11

