Java實現俄羅斯方塊遊戲簡單版
本文實例為大傢分享瞭Java實現俄羅斯方塊遊戲的具體代碼,供大傢參考,具體內容如下
遊戲頁面效果如下:
俄羅斯方塊遊戲本身的邏輯:
俄羅斯方塊遊戲的邏輯是比較簡單的。它就類似於堆砌房子一樣,各種各樣的方地形狀是不同的。但是,俄羅斯方塊遊戲的界面被等均的分為若幹行和若幹列,因此方塊的本質就是占用瞭多少個單元。
首先來考慮一下數據的問題。對於界面來說,需要一個二維的 int 型數組,它保存著那些地方應該有著色,哪些沒有;然後是方塊本身,盡管它們的形狀不統一,但是它們可以用一個4X4比例的方塊所包圍,因此用16個字節就可以把一個 方塊的信息保存者,
註意:其實方塊的數據也可以用int 數組表示,但是涉及到效率問題,用位操作比用普通的算術運算要快一點。
接下來思考一下動作具體有下面幾點:
(1)方塊的誕生。它的誕生是需要用隨機原理的,另外,它如何初始化的被放置在遊戲界面的頂部?
(2)方塊是需要自動的往下掉的,它在掉的過程中,還需要判斷它是否與周圍的環境是否發生瞭沖突,能不能繼續往下。
(3)方塊本身還可以變形,變形以後的方塊具有不同的數據,判斷的方式又會不一樣。(4)當用戶一直按住s鍵的時候,方塊還需要持續往下掉。
然後就是過程,玩傢主要操作的地方有以下幾個方面:
(1) 左右操作。需要監聽KeyEvent,讓方塊左右移動,直到碰到邊界。
(2) 變形操作。也要監聽KeyEvent,讓方塊自動的變形。
(3) 下降操作。也要監聽KeyEvent,讓方塊快速的下降。
至於遊戲的結束,隻有一種情況, 那就是誕生的方塊出世就與其他方塊沖突瞭。
源程序代碼如下:註釋詳細
package tetris; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; public class Main extends JFrame implements KeyListener { private JTextArea[][] grids;// 把整個界面變為一個文本區域,整個遊戲在裡面進行 private int data[][]; // 對於每個格子的數據,1代表有方塊,0代表為空白區 private int[] allRect; // 所有的方塊類型,用16個字節來存儲,俄羅斯方塊圖形都是在4*4格子裡 private int rect; // 當前遊戲下落的方塊類型; private int x, y; // 當前方塊的坐標位置,x代表行,y代表列 private int score = 0; // 記錄當前遊戲得分情況,每消一層得10分 private JLabel label; // 顯示分數的標簽 private JLabel label1;// 顯示遊戲是否結束 private boolean running; // 用於判斷遊戲是否結束 /*無參構造函數*/ public Main() { grids = new JTextArea[26][12];//設置遊戲區域行和列 data = new int[26][12];//開辟data數組空間與遊戲區域行和列一致 allRect = new int[] { 0x00cc, 0x8888, 0x000f, 0x0c44, 0x002e, 0x088c, 0x00e8, 0x0c88, 0x00e2, 0x044c, 0x008e, 0x08c4, 0x006c, 0x04c8, 0x00c6, 0x08c8, 0x004e, 0x04c4, 0x00e4 };//19種方塊形狀,如0x00cc就是 0000 表示一個2*2的正方形方塊 //0000 //1100 //1100 label = new JLabel("score: 0"); //此標簽存放得分情況,初始化為0分 label1 = new JLabel("開始遊戲"); //此標簽為提示遊戲狀態:開始還是結束 running = false; //為標志變量,false為遊戲結束,true為遊戲正在進行 init(); // 遊戲界面初始化 } /*遊戲界面初始化函數*/ public void init() { JPanel center = new JPanel(); //此面板為遊戲核心區域 JPanel right = new JPanel(); //此面板為遊戲說明區域 center.setLayout(new GridLayout(26, 12, 1, 1)); //給遊戲核心區域劃分行、列共26行,12列 for (int i = 0; i < grids.length; i++) {//初始化面板 for (int j = 0; j < grids[i].length; j++) { grids[i][j] = new JTextArea(20, 20); grids[i][j].setBackground(Color.WHITE); grids[i][j].addKeyListener(this);// 添加鍵盤監聽事件 //初始化遊戲邊界 if (j == 0 || j == grids[i].length - 1 || i == grids.length - 1) { grids[i][j].setBackground(Color.PINK); data[i][j] = 1; } grids[i][j].setEditable(false);// 文本區域不可編輯 center.add(grids[i][j]); //把文本區域添加到主面板上 } } //初始化遊戲說明面板 right.setLayout(new GridLayout(4, 1)); right.add(new JLabel(" a : left d : right")); right.add(new JLabel(" s : down w : change")); right.add(label); label1.setForeground(Color.RED);// 設置標簽內容為紅色字體 right.add(label1); //把主面板和說明面板添加到窗體中 this.setLayout(new BorderLayout()); this.add(center, BorderLayout.CENTER); this.add(right, BorderLayout.EAST); running = true; //初始化running狀態為true,表示程序運行即遊戲開始 this.setSize(600, 850);// 設置窗體大小 this.setVisible(true);// 窗體可見 this.setLocationRelativeTo(null);// 設置窗體居中 this.setResizable(false);// 窗體大小不可改變 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 釋放窗體 } /*主函數*/ public static void main(String[] args) { Main m = new Main(); //創建Main對象,主要用於初始化數據 m.go();// 開始遊戲 } /*開始遊戲*/ public void go() {// 開始遊戲 while (true) {//遊戲開始直到遊戲失敗才結束,否則一直執行 if (running == false) {//如果遊戲失敗 break; } ranRect();// 繪制下落方格形狀 start();// 開始遊戲 } label1.setText("遊戲結束!");//則遊戲結束 } /*繪制下落方格形狀*/ public void ranRect() { rect = allRect[(int) (Math.random() * 19)];// 隨機生成方塊類型(共7種,19個形狀) } /*遊戲開始函數*/ public void start() { x = 0; y = 5; //初始化下落方塊的位置 for (int i = 0; i < 26; i++) {//共26層,一層一層下落 try { Thread.sleep(1000);//每層延時1秒 if (canFall(x, y) == false) {// 如果不可以掉落 saveData(x, y);//把此方塊區域data[][]標志為1,表示有數據 for (int k = x; k < x + 4; k++) {//循環遍歷4層,看是否有哪一層都有方塊的情況,以便消除那一行方格和統計得分 int sum = 0; for (int j = 1; j <= 10; j++) { if (data[k][j] == 1) { sum++; } } if (sum == 10) {//如果k層都有方塊,則消除k層方塊 removeRow(k); } } for (int j = 1; j <= 10; j++) {//遊戲最上面的4層不能有方塊,否則遊戲失敗 if (data[3][j] == 1) { running = false; break; } } break; } // 如果可以掉落 x++;// 層加一 fall(x, y);// 掉下來一層 } catch (InterruptedException e) { e.printStackTrace(); } } } /*判斷正下落的方塊是否可以下落*/ public boolean canFall(int m, int n) { int temp = 0x8000;//表示1000 0000 0000 0000 for (int i = 0; i < 4; i++) {//循環遍歷16個方格(4*4) for (int j = 0; j < 4; j++) { if ((temp & rect) != 0) {// 此處有方塊時 if (data[m + 1][n] == 1)// 如果下一個地方有方塊,則直接返回false return false; } n++;//列加一 temp >>= 1; } m++;// 下一行 n = n - 4;// 回到首列 } return true;//可以掉落返回true } /*把不可下降的方塊的對應的data存儲為1,表示此坐標有方塊*/ public void saveData(int m, int n) { int temp = 0x8000;//表示1000 0000 0000 0000 for (int i = 0; i < 4; i++) {//循環遍歷16個方格(4*4) for (int j = 0; j < 4; j++) { if ((temp & rect) != 0) {// 此處有方塊時 data[m][n] = 1;//data數組存放為1 } n++;//下一列 temp >>= 1; } m++;// 下一行 n = n - 4;// 回到首列 } } /*移除row行所有方塊,以上的依次往下降*/ public void removeRow(int row) { for (int i = row; i >= 1; i--) { for (int j = 1; j <= 10; j++) { data[i][j] = data[i - 1][j];// } } reflesh();// 刷新移除row行方塊後的遊戲主面板區域 score += 10;// 分數加10; label.setText("score: " + score);//顯示得分 } /* 刷新移除row行方塊後的遊戲主面板區域*/ public void reflesh() { for (int i = 1; i < 25; i++) { for (int j = 1; j < 11; j++) { if (data[i][j] == 1) {//有方塊的地方把方塊設置為綠色 grids[i][j].setBackground(Color.GREEN); } else {//無方塊的地方把方塊設置為白色 grids[i][j].setBackground(Color.WHITE); } } } } /*方塊掉落一層*/ 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;//表示1000 0000 0000 0000 for (int i = 0; i < 4; i++) {//循環遍歷16個方格(4*4) for (int j = 0; j < 4; j++) { if ((temp & rect) != 0) {// 此處有方塊時 grids[m][n].setBackground(Color.WHITE);//清除顏色,變為白色 } n++;//下一列 temp >>= 1; } m++;//下一行 n = n - 4;//回到首列 } } /*繪制掉落後方塊圖像*/ public void draw(int m, int n) { int temp = 0x8000;//表示1000 0000 0000 0000 for (int i = 0; i < 4; i++) {//循環遍歷16個方格(4*4) for (int j = 0; j < 4; j++) { if ((temp & rect) != 0) {// 此處有方塊時 grids[m][n].setBackground(Color.GREEN);//有方塊的地方變為綠色 } n++;//下一列 temp >>= 1; } m++;//下一行 n = n - 4;//回到首列 } } @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { if (e.getKeyChar() == 'a') {// 方格進行左移 if (running == false) { return; } if (y <= 1)//碰到左邊墻壁時 return; int temp = 0x8000;//表示1000 0000 0000 0000 for (int i = x; i < x + 4; i++) {//循環遍歷16個方格(4*4) for (int j = y; j < y + 4; j++) { if ((rect & temp) != 0) {// 此處有方塊時 if (data[i][j - 1] == 1) {//如果左移一格有方塊時 return; } } temp >>= 1; } } clear(x, y);//可以進行左移操作時,清除左移前方塊顏色 y--; draw(x, y);//然後重新繪制左移後方塊的圖像 } if (e.getKeyChar() == 'd') {//方塊進行右移操作 if (running == false) { return; } int temp = 0x8000; int m = x, n = y; int num = 7; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if ((temp & rect) != 0) { if (n > num) { num = n; } } temp >>= 1; n++; } m++; n = n - 4; } if (num >= 10) { return; } temp = 0x8000; for (int i = x; i < x + 4; i++) { for (int j = y; j < y + 4; j++) { if ((rect & temp) != 0) { if (data[i][j + 1] == 1) { return; } } temp >>= 1; } } clear(x, y);//可以進行右移操作時,清除右移前方塊顏色 y++; draw(x, y);//然後重新繪制右移後方塊的圖像 } if (e.getKeyChar() == 's') {//方塊進行下移操作 if (running == false) { return; } if (canFall(x, y) == false) { saveData(x, y); return; } clear(x, y);//可以進行下移操作時,清除下移前方塊顏色 x++; draw(x, y);//然後重新繪制下移後方塊的圖像 } if (e.getKeyChar() == 'w') {//改變方塊形狀 if (running == false) { return; } int i = 0; for (i = 0; i < allRect.length; i++) {//循環遍歷19個方塊形狀 if (allRect[i] == rect)//找到下落的方塊對應的形狀,然後進行形狀改變 break; } if (i == 0)//為正方形方塊無需形狀改變,為方塊圖形種類1 return; clear(x, y); if (i == 1 || i == 2) {//為方塊圖形種類2 rect = allRect[i == 1 ? 2 : 1]; if (y > 7) y = 7; } if (i >= 3 && i <= 6) {//為方塊圖形種類3 rect = allRect[i + 1 > 6 ? 3 : i + 1]; } if (i >= 7 && i <= 10) {//為方塊圖形種類4 rect = allRect[i + 1 > 10 ? 7 : i + 1]; } if (i == 11 || i == 12) {//為方塊圖形種類5 rect = allRect[i == 11 ? 12 : 11]; } if (i == 13 || i == 14) {//為方塊圖形種類6 rect = allRect[i == 13 ? 14 : 13]; } if (i >= 15 && i <= 18) {//為方塊圖形種類7 rect = allRect[i + 1 > 18 ? 15 : i + 1]; } draw(x, y); } } }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。