Java實現(xiàn)俄羅斯方塊的源碼分享
本文實現(xiàn)的功能有:
1、 初始化游戲窗口
2、初始化游戲的界面
3、初始化游戲的說明面板
4、隨機生成下落方塊
5、方塊下落速度變化
6、判斷方塊是否可以下落
7、移除某一行方塊上面的方塊后讓上面的方塊掉落
8、刷新移除某一行方塊后的界面
9、清除方塊
10、繪制方塊
11、鍵盤控制方塊的移動、變形和快速下落
12、游戲的暫停功能
三小時純手工打造,具體實現(xiàn)代碼:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class start extends JFrame implements KeyListener {
public static void main(String[] args) throws Exception {
// SwingUtilities.invokeLater(start::initWindow);
start t=new start();
t.game_begin();
}
//游戲的行數(shù)為26,列數(shù)為12
private static final int game_x=26;
private static final int game_y=12;
//文本域數(shù)組
JTextArea[][] text;
//二維數(shù)組
int [][] data;
//顯示游戲狀態(tài)的標簽
JLabel Label1;
//顯示游戲分數(shù)的標簽
JLabel Label;
//提示暫停鍵的標簽
JLabel label;
//用于判斷游戲是否結(jié)束
boolean isrunning;
//用于存儲所有方塊的數(shù)組
int [] allRect;
//用于存儲當前方塊的變量
int rect;
//線程的休眠時間
int time=1000;
//表示方塊坐標
int x,y;
//該變量用于計算得分
int score=0;
//定義一個標志變量,判斷游戲是否暫停
boolean game_pause=false;
//定義一個變量,用于記錄按下暫停的次數(shù)
int pause=0;
public void initWindow(){
//設(shè)置窗口大小
this.setSize(600,850);
//設(shè)置窗口是否可見
this.setVisible(true);
//設(shè)置窗口居中
this.setLocationRelativeTo(null);
//設(shè)置釋放窗體
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//設(shè)置窗體大小不可變
this.setResizable(false);
//設(shè)置標題
this.setTitle("俄羅斯方塊");
}
public start(){
text=new JTextArea[game_x][game_y];
data=new int[game_x][game_y];
//初始化游戲狀態(tài)的標簽
Label1 =new JLabel("游戲狀態(tài):正在游戲中!");
//初始化游戲分數(shù)的標簽
Label=new JLabel("游戲得分:0");
//初始化提示標簽
label=new JLabel("按下s鍵,即可暫停游戲!");
initGamePanel();
initExplainPanel();
initWindow();
//初始化游戲開始的標志
isrunning=true;
//初始化存放方塊的數(shù)組
allRect =new int[]{0x00cc,0x8888,0x000f,0x888f,0xf888,0xf111,0x111f,0x0eee,0xffff,0x0008
,0x0888,0x000e,0x0088,0x000c,0x08c8,0x00e4,0x04c4,0x004e,0x08c4,0x006c,0x04c8,0x00c6};
}
//初始化游戲界面
public void initGamePanel(){
JPanel game_main=new JPanel();
game_main.setLayout(new GridLayout(game_x,game_y,1,1));
for (int i = 0; i < text.length; i++) {
for (int j = 0; j < text[i].length; j++) {
//設(shè)置文本域的行列數(shù)
text[i][j]=new JTextArea(game_x,game_y);
//設(shè)置文本域的背景顏色
text[i][j].setBackground(Color.WHITE);//白色
//添加鍵盤監(jiān)聽事件
text[i][j].addKeyListener(this);
//初始化游戲邊界
if(j==0 || j==text[i].length-1 || i==text.length-1){
text[i][j].setBackground(Color.BLACK);//設(shè)置為黑色,這里看個人喜好設(shè)置
data[i][j]=1;//表示這里有方塊
}
//設(shè)置文本域不可編輯
text[i][j].setEditable(false);
//文本區(qū)域添加到主面板上去
game_main.add(text[i][j]);
}
}
//將主面板添加到窗口中
this.setLayout(new BorderLayout());
this.add(game_main,BorderLayout.CENTER);//把游戲區(qū)域添加到窗口的中間
}
//初始化游戲的說明界面
public void initExplainPanel(){
//創(chuàng)建游戲的左說明面板
JPanel explain_left=new JPanel();
//創(chuàng)建游戲的右說明面板
JPanel explain_right=new JPanel();
//初始化格式布局
explain_left.setLayout(new GridLayout(4,1));
explain_right.setLayout(new GridLayout(3,1));
//在左說明面板,添加說明文字
explain_left.add(new JLabel("按空格鍵,方塊變形"));
explain_left.add(new JLabel("按左箭頭,方塊左移"));
explain_left.add(new JLabel("按右箭頭,方塊右移"));
explain_left.add(new JLabel("按下箭頭,方塊下落"));
//設(shè)置游戲標簽的內(nèi)容為紅色字體
Label1.setForeground(Color.RED);
//將游戲狀態(tài)和得分、提示添加到右面板上
explain_right.add(label);
explain_right.add(Label);
explain_right.add(Label1);
//將左說明面板添加到窗口左側(cè)
this.add(explain_left,BorderLayout.WEST);
//將右說明面板添加到窗口右側(cè)
this.add(explain_right,BorderLayout.EAST);
}
//開始游戲的方法
public void game_begin() throws Exception {
while (true){
//判斷游戲是否結(jié)束
if(!isrunning){
break;
}
//進行游戲
game_run();
}
//在標簽位置顯示游戲結(jié)束
Label1.setText("游戲狀態(tài):游戲結(jié)束!");
}
//隨機生成下落方塊形狀的方法
public void ranRect(){
Random random=new Random();
rect=allRect[random.nextInt(22)];
}
//游戲運行的方法
public void game_run() throws Exception {
ranRect();
//方塊下落位置
x=0;
y=5;
for (int i = 0; i < game_x; i++) {
Thread.sleep(time);
if (game_pause) {
i--;
} else {
//判斷方塊是否可以下落
if (!canFall(x, y)) {
//將data變成1,表示有方塊占用
changData(x, y);
//循環(huán)遍歷4層,看是否有行可以消除
for (int j = x; j < x + 4; j++) {
int sum = 0;
for (int k = 1; k <= (game_y - 2); k++) {
if (data[j][k] == 1) {
sum++;
}
}
//判斷是否有一行可以被消除
if (sum == (game_y - 2)) {
//消除J這一行
removeRow(j);
}
}
//判斷游戲是否失敗
for (int j = 1; j < (game_y - 2); j++) {
if (data[3][j] == 1) {
isrunning = false;
break;
}
}
break;//方塊無法下落,我們應該重新生成一個方塊,并重新遍歷26層
} else {
//方塊可以下落,層數(shù)加一
x++;
//方塊下落一格
fall(x, y);
}
}
}
}
//判斷方塊是否可以繼續(xù)下落的方法
public boolean canFall(int m,int n){
//定義一個變量
int temp=0x8000;
//遍歷4*4方格
for (int i = 0; i <4 ; i++) {
for (int j = 0; j < 4; j++) {
if((temp & rect)!=0){
//判斷該位置的下一行是否有方塊
if(data[m+1][n]==1){
return false;
}
}
n++;
temp >>=1;//右移一位
}
m++;
n=n-4;//讓n回歸首列
}
//循環(huán)結(jié)束,可以下落
return true;
}
//改變不可下降的方塊對應的區(qū)域的值的方法
public void changData(int m,int n){
//定義一個變量
int temp=0x8000;
//遍歷整個4*4的方塊
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if((temp & rect)!=0){
data[m][n]=1;
}
n++;
temp >>=1;//右移一位
}
m++;
n=n-4;
}
}
//移除某一行的所有方塊,并讓上面的方塊掉落的方法
public void removeRow(int row){
int temp=100;
for (int i = row; i >=1 ; i--) {
for (int j = 1; j <=(game_y-2) ; j++) {
//進行覆蓋
data[i][j]=data[i-1][j];
}
}
//刷新游戲區(qū)域
reflesh(row);
//方塊加速
if(time>temp){
time-=temp;
}
//每消除一行,得分加100
score+=temp;
//顯示變化后的分數(shù)
Label.setText("游戲得分:"+score);
}
//刷新移除某一行后的游戲界面的方法
public void reflesh(int row){
//遍歷row上面的游戲區(qū)域
for (int i = row; i >=1 ; i--) {
for (int j = 1; j <=(game_y-2) ; j++) {
if(data[i][j]==1){//如果是方塊,將方塊設(shè)置為藍色
text[i][j].setBackground(Color.BLUE);
}else{//如果不是方塊,說明是游戲的背景區(qū)域
text[i][j].setBackground(Color.WHITE);//設(shè)置為白色
}
}
}
}
//方塊向下掉落一層的方法
public void fall(int m,int n){
if(m>0){
//清除上一層方塊
clear(m-1,n);
}
//重新繪制方塊
draw(m,n);
}
//清除方塊掉落后,上一層有顏色的地方的方法
public void clear(int m,int n){
//定義一個變量
int temp=0x8000;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((temp & rect) != 0) {
text[m][n].setBackground(Color.WHITE);//將其設(shè)置成背景顏色,相當于消除
}
n++;
temp >>=1;//右移一位
}
m++;
n=n-4;
}
}
//重新繪制掉落后的方塊的方法
public void draw(int m,int n){
//定義一個變量
int temp=0x8000;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if((temp & rect)!=0){
text[m][n].setBackground(Color.BLUE);//設(shè)置成之前的方塊顏色
}
n++;
temp >>=1;//右移一位
}
m++;
n=n-4;
}
}
@Override
public void keyTyped(KeyEvent e) {
//控制游戲暫停
if(e.getKeyChar()=='s'){//如果按下s,則游戲暫停
//判斷游戲是否結(jié)束
if(!isrunning){
return;
}
pause++;
//判斷是按下一次,暫停游戲
if(pause==1){
game_pause=true;
Label1.setText("游戲狀態(tài):暫停中!");
}
//判斷是按下兩次,繼續(xù)游戲
if(pause==2){
game_pause=false;
pause=0;//重置暫停次數(shù)
Label1.setText("游戲狀態(tài):正在游戲中!");
}
}
//控制方塊進行變形
if(e.getKeyChar()==KeyEvent.VK_SPACE){
//判斷游戲是否結(jié)束
if(!isrunning){
return;
}
//判斷游戲是否暫停
if(game_pause){
return;
}
//定義變量,存儲目前方塊的索引
int old;
for (old = 0; old < allRect.length; old++) {
//判斷是否是當前方塊
if(rect==allRect[old]){
break;
}
}
//定義變量,存儲變形后的方塊
int next;
//判斷是完整方塊
if(old==0||old==7||old==8||old==9){
return;
}
//清除當前方塊
clear(x,y);
if(old==1||old==2){
next=allRect[old==1?2:1];
//如果可以變形
if(canTurn(next,x,y)){
rect=next;
}
}
if(old>=3&&old<=6){
next=allRect[old+1>6?3:old+1];
if(canTurn(next,x,y)){
rect=next;
}
}
if(old==10||old==11){
next=allRect[old==10?11:10];
if(canTurn(next,x,y)){
rect=next;
}
}
if(old==12||old==13){
next=allRect[old==12?13:12];
if(canTurn(next,x,y)){
rect=next;
}
}
if(old>=14&&old<=17){
next=allRect[old+1>17?14:old+1];
if(canTurn(next,x,y)){
rect=next;
}
}
if(old==18||old==19){
next=allRect[old==18?19:18];
if(canTurn(next,x,y)){
rect=next;
}
}
if(old==20||old==21){
next=allRect[old==20?21:20];
if(canTurn(next,x,y)){
rect=next;
}
}
//重新繪制變形后的方塊
draw(x,y);
}
}
public boolean canTurn(int a,int m,int n){
//創(chuàng)建變量
int temp=0x8000;
//遍歷整個方塊
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((temp & rect) != 0) {
if(data[m][n]==1){
return false;
}
}
n++;
temp >>=1;
}
m++;
n=n-4;
}
//可以變形
return true;
}
@Override
public void keyPressed(KeyEvent e) {
//方塊進行左移
if(e.getKeyCode()==37){//左箭頭對應的數(shù)值為37
//判斷游戲是否結(jié)束
if(!isrunning){
return;
}
//判斷游戲是否暫停
if(game_pause){
return;
}
//方塊是否碰到左墻壁
if(y<=1){
return;
}
//方塊的左邊是否有方塊
int temp=0x8000;
for (int i = x; i <x+4 ; i++) {
for (int j = y; j <y+4 ; j++) {
if((temp & rect)!=0){
if(data[i][j-1]==1){
return;
}
}
temp >>=1;
}
}
//清除目前方塊
clear(x,y);
y--;//向左移動
draw(x,y);//重新繪制出向左移動后的方塊
}
//方塊進行右移
if(e.getKeyCode()==39) {//右箭頭對應的數(shù)值為39
//判斷游戲是否結(jié)束
if(!isrunning){
return;
}
//判斷游戲是否暫停
if(game_pause){
return;
}
int temp=0x8000;
int m=x;
int n=y;
//存儲最右邊的坐標值
int num=1;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((temp & rect) != 0) {
if(n>num){
num=n;
}
}
n++;
temp >>=1;
}
m++;
n=n-4;
}
//判斷是否碰到右墻壁
if(num>=(game_y-2)){
return;
}
//判斷方塊右移途中是否碰到其他方塊
temp=0x8000;
for (int i = x; i <x+4 ; i++) {
for (int j = y; j < y + 4; j++) {
if ((temp & rect) != 0) {
if(data[i][j+1]==1){
return;
}
}
temp>>=1;
}
}
//清除當前方塊
clear(x,y);
y++;//右移一位
draw(x,y);//重新繪制出向右移動后的方塊
}
//方塊進行下落
if(e.getKeyCode()==40) {//下箭頭對應的數(shù)值為40
//判斷游戲是否結(jié)束
if (!isrunning) {
return;
}
//判斷游戲是否暫停
if(game_pause){
return;
}
//判斷方塊是否可以下落
if(!canFall(x,y)){
return;
}
//清除當前方塊
clear(x,y);
//改變方塊坐標
x++;
draw(x,y);//重新繪制出向右移動后的方塊
}
}
@Override
public void keyReleased(KeyEvent e) {
}
}其中的方塊數(shù)組中的數(shù)字意義:



運行后結(jié)果:

到此這篇關(guān)于Java實現(xiàn)俄羅斯方塊的源碼分享的文章就介紹到這了,更多相關(guān)Java俄羅斯方塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java使用httpclient模擬post請求和get請求示例
這篇文章主要介紹了java使用httpclient模擬post請求和get請求示例,需要的朋友可以參考下2014-02-02
如何優(yōu)雅的拋出Spring Boot注解的異常詳解
這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅的拋出Spring Boot注解的異常的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-12-12
springboot如何使用thymeleaf模板訪問html頁面
springboot中推薦使用thymeleaf模板,使用html作為頁面展示。那么如何通過Controller來訪問來訪問html頁面呢?下面通過本文給大家詳細介紹,感興趣的朋友跟隨腳本之家小編一起看看吧2018-05-05
淺談Java中ThreadLocal引發(fā)的內(nèi)存泄漏
本文主要介紹了淺談Java中ThreadLocal引發(fā)的內(nèi)存泄漏,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-06-06
淺談Java數(shù)值類型的轉(zhuǎn)換與強制轉(zhuǎn)換
這篇文章主要介紹了Java數(shù)值類型的轉(zhuǎn)換與強制轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04

