歡迎您光臨本站 註冊首頁

Java實現簡易俄羅斯方塊

←手機掃碼閱讀     lousu-xi @ 2020-06-16 , reply:0

本文實例為大家分享了Java實現簡易俄羅斯方塊的具體代碼,供大家參考,具體內容如下

一、將對象抽象為類

首先考慮俄羅斯方塊遊戲中含有哪些具體的對象,對象中含有哪些具體屬性和方法,然後用代碼來實現。

建立如下類:

Cell類:代表最小的方格單位,構成7種圖形的最基本圖形。

    含有row(行號),col(列號),image(對應的圖片)屬性,

    含有left(左移),right(右移),drop(下落)方法。

Tetromino類:代表由4個最小方格構成的7種圖形的合集。

    含有cells(四個方塊)屬性,

    含有moveLeft(四格方塊向左移動),moveRight(四格方塊向右移動),softDrop(軟下落),randomOne(隨機生成一個四格方格)方法。

T類繼承於Tetromino類:

I類繼承於Tetromino類:


 

L類繼承於Tetromino類:


 

S類繼承於Tetromino類:


 

Z類繼承於Tetromino類:


 

O類繼承於Tetromino類:


 

J類繼承於Tetromino類:


 

Tetris類:俄羅斯方塊的主方法類,包括了遊戲運行過程中所需要的眾多方法。

    含有currentOne(正在下落的四格方塊),nextOne(即將下落的四格方塊),Cell[][]wall(二維數組的表格,代表牆)屬性。

二、類的實現

Notes:各類實現過程中要符合Javabean規範。

Cell類:

  package com.tetris;     import java.awt.image.BufferedImage;     /*   * 俄羅斯方塊中的最小單位:方格   * 特徵(屬性):   * row--行號   * col--列號   * image--對應的圖片   *    * 行為(方法)   * left();   * right();   * drop();   */  public class Cell {      private int row; //行   private int col; //列   private BufferedImage image;      public Cell(int row, int col, BufferedImage image) {   super();   this.row = row;   this.col = col;   this.image = image;   }   public Cell() {   super();   // TODO Auto-generated constructor stub   }   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 "(" + row + ", " + col + ")";   }      //向左移動   public void left(){   col--;   }   //向右移動   public void right(){   col++;   }   //向下移動   public void drop(){   row++;   }  }

 

Tetromino類:

  package com.tetris;     import java.util.Arrays;     import javax.xml.transform.Templates;     /*   * 四格方塊   * 屬性:   * ---cells,----四個方塊   *    * 行為:   * moveLeft()   * moveRight()   * softDrop()   */  public class Tetromino {      protected Cell[] cells=new Cell[4];      //四格方塊向左移動   //實際上:就是每個方塊向左移動   public void moveLeft(){   for (int i = 0; i < cells.length; i++) {   cells[i].left();   }   }   //四格方塊向右移動   //實際上:就是每個方塊向右移動   public void moveRight(){   for (int i = 0; i < cells.length; i++) {   cells[i].right();   }   }   //四格方塊向下移動   //實際上:就是每個方塊向下移動   public void softDrop(){   for (int i = 0; i < cells.length; i++) {   cells[i].drop();   }   }      @Override   public String toString() {   return "[" + Arrays.toString(cells) + "]";   }         //隨機生成一個四格方塊   public static Tetromino randomOne(){   Tetromino t = null;   int num=(int)(Math.random()*7);   switch (num){   case 0:t=new T();break;   case 1:t=new O();break;   case 2:t=new I();break;   case 3:t=new J();break;   case 4:t=new L();break;   case 5:t=new S();break;   case 6:t=new Z();break;   default:   break;   }   return t;   }  }

 

T類繼承於Tetromino類:

  package com.tetris;     public class T extends Tetromino {      //提供構造器,進行初始化   //T型的四格方塊的位置   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);   }  }

 

I類繼承於Tetromino類:

  package com.tetris;     public class I extends Tetromino {      //提供構造器,進行初始化   //T型的四格方塊的位置   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);   }  }

 

L類繼承於Tetromino類:

  package com.tetris;     public class L extends Tetromino {      //提供構造器,進行初始化   //T型的四格方塊的位置   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,5,Tetris.L);   }  }

 

S類繼承於Tetromino類:

  package com.tetris;     public class S extends Tetromino {      //提供構造器,進行初始化   //T型的四格方塊的位置   public S(){   cells[0]=new Cell(1,4,Tetris.S);   cells[1]=new Cell(0,3,Tetris.S);   cells[2]=new Cell(0,4,Tetris.S);   cells[3]=new Cell(1,5,Tetris.S);   }  }

 

Z類繼承於Tetromino類:

  package com.tetris;     public class Z extends Tetromino {      //提供構造器,進行初始化   //T型的四格方塊的位置   public Z(){   cells[0]=new Cell(0,4,Tetris.Z);   cells[1]=new Cell(0,5,Tetris.Z);   cells[2]=new Cell(1,3,Tetris.Z);   cells[3]=new Cell(1,4,Tetris.Z);   }  }

 

O類繼承於Tetromino類:

  package com.tetris;     public class O extends Tetromino {      //提供構造器,進行初始化   //T型的四格方塊的位置   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);   }  }

 

J類繼承於Tetromino類:

  package com.tetris;     public class J extends Tetromino {      //提供構造器,進行初始化   //T型的四格方塊的位置   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,3,Tetris.J);   }  }

 

Tetris類:

  //屬性:正在下落的四格方塊  private Tetromino currentOne=Tetromino.randomOne();  //屬性:將要下落的四格方塊  private Tetromino nextOne=Tetromino.randomOne();    //屬性:牆,20行10列的表格 寬度為26  private Cell[][]wall=new Cell[20][10];

 

三、繪製俄羅斯方塊圖形

個人理解,這個過程就是顯現出遊戲界面的過程,當然啦,這一步主要是加載靜態資源,諸如圖片,音頻和視頻等。

1.加載靜態資源

俄羅斯方塊主要應用的靜態資源是圖片,所以我們用到的是IO類中的ImageIO類中的ImageIO.read方法,導入各類四格方塊的圖形圖片以及背景圖片,具體代碼如下:

  public static BufferedImage T;   public static BufferedImage I;   public static BufferedImage O;   public static BufferedImage J;   public static BufferedImage L;   public static BufferedImage S;   public static BufferedImage Z;   public static BufferedImage background;      static{   try {    /*    * getResouce(String url)    * url:加載圖片的路徑    * 相對位置是同包下    */    T=ImageIO.read(Tetris.class.getResource("T.png"));    I=ImageIO.read(Tetris.class.getResource("I.png"));    O=ImageIO.read(Tetris.class.getResource("O.png"));    J=ImageIO.read(Tetris.class.getResource("J.png"));    L=ImageIO.read(Tetris.class.getResource("L.png"));    S=ImageIO.read(Tetris.class.getResource("S.png"));    Z=ImageIO.read(Tetris.class.getResource("Z.png"));   background=ImageIO.read(Tetris.class.getResource("tetris.png"));   } catch (Exception e) {    e.printStackTrace();   }   }

 

2.畫遊戲靜態界面

在這一部分中需要繪製三部分,用到了三種方法,分別是paintCurrentOne(正在下落的四格方塊),paintNextOne(等待進入的四格方塊),paintWall(背景牆)。

繪製需要重寫JPanel類中的paint(Graphics g)方法,具體代碼實現如下:

  public void paint(Graphics g){   //繪製背景   /*    * g:畫筆    * g.drawImage(image,x,y,null)    * x:開始繪製的橫座標    * y:開始繪製的縱座標    */   g.drawImage(background,0,0,null);   //平移座標軸   g.translate(15, 15);   //繪製牆   paintWall(g);   //繪製正在下落的四格方塊   paintCurrentOne(g);   //繪製下一個即將下落的四格方塊   paintNextOne(g);   }   /*   * 繪製下一個即將下落的四格方塊   * 繪製到面板的右上角的相應區域   */   public void paintNextOne(Graphics g){   //獲取nextOne對象的四個元素   Cell[] cells=nextOne.cells;   for (Cell c:cells) {    //獲取每一個元素的行號和列號    int row=c.getRow();    int col=c.getCol();    //橫座標和縱座標    int x=col*CELL_SIZE+260;    int y=row*CELL_SIZE+26;    g.drawImage(c.getImage(), x, y, null);   }   }      /*   * 繪製正在下落的四格方塊   * 取出數組的元素   * 繪製數組的圖片   * 橫座標x   * 縱座標y   */   public void paintCurrentOne(Graphics g){    Cell[] cells=currentOne.cells;    for (Cell c:cells) {    int x=c.getCol()*CELL_SIZE;    int y=c.getRow()*CELL_SIZE;    g.drawImage(c.getImage(), x, y, null);    }       }   /*   * 牆是20行,10列的表格   * 是一個二維數組   * 用雙層循環   * 繪製正方形   */   public void paintWall(Graphics a){   //外層循環控制行數   for (int i = 0; i < 20; i++) {    //內層循環控制列數    for (int j = 0; j < 10; j++) {    int x=j*CELL_SIZE;    int y=i*CELL_SIZE;    Cell cell=wall[i][j];    a.drawRect(x, y, CELL_SIZE, CELL_SIZE);    if(wall[i][j]==null){     a.drawRect(x, y, CELL_SIZE, CELL_SIZE);    }else{     a.drawImage(cell.getImage(),x,y,null);    }    }   }   }

 

實現效果如下:


 

3.讓四格方塊動起來

光有靜態的畫面是不能夠稱為遊戲的,還有要動態效果和接收鍵盤指令並響應的能力。

(1)動態效果

俄羅斯方塊中的動態效果主要指7種四格方塊擁有自動下降,軟下降,左移,右移,旋轉的能力,分別使用canDrop(),softDropAction(),moveLeftAction(),moveRightAction(),spinCellAction()方法來實現,與此同時,還需根據遊戲規則注意四格方塊可能遇到觸碰到左右邊界,方塊覆蓋等錯誤,在此使用outOfBounds(),coincide()方法來避免。當不能下落時,需要將四格方塊,嵌入到牆中,使用landToWall()方法。

具體代碼實現如下:

   /*   * 使用left鍵控制向左的行為   */   public void moveLeftAction() {   currentOne.moveLeft();   if(outOfBounds()||coincide()){    currentOne.moveRight();   }      }   /*   * 使用right鍵控制向右的行為   */   public void moveRightAction() {   currentOne.moveRight();   if(outOfBounds()||coincide()){    currentOne.moveLeft();   }      }   /*   * 使用down鍵控制四格方塊的下落   */   public void softDropAction() {   if(canDrop()){    currentOne.softDrop();   }else{    landToWall();    currentOne=nextOne;    nextOne=Tetromino.randomOne();   }      }   public boolean outOfBounds(){   Cell[] cells=currentOne.cells;   for (Cell c : cells) {    int col=c.getCol();    if(col9){    return true;    }   }   return false;    }      public boolean coincide(){   Cell[] cells=currentOne.cells;   for (Cell c : cells) {    int row=c.getRow();    int col=c.getCol();    if(wall[row][col]!=null){    return true;    }   }   return false;      }      public boolean canDrop(){   Cell[] cells=currentOne.cells;      for (Cell c: cells) {    //獲取每個元素的行號    /*    * 判斷:    * 只要有一個元素的下一行上有方塊    * 或者只要有一個元素到達最後一行,就不能下落了    */    int row=c.getRow();    int col=c.getCol();        if(row==19){    return false;    }    if(wall[row+1][col]!=null){    return false;    }   }   return true;      }   /*   * 當不能下落時,需要將四格方塊,嵌入到牆中   * 也就是存儲到二維數組中相應的位置上   */   public void landToWall(){   Cell[] cells=currentOne.cells;   for (Cell c : cells) {    //獲取最終的行號和列號    int row=c.getRow();    int col=c.getCol();    wall[row][col]=c;   }      }

 

實現效果如下:


 

(2)接收鍵盤指令並響應

遊戲和玩家緊密關聯,所以接下來我們需要使玩家能夠通過鍵盤控制四格方塊移動。

因此,我們要開啟鍵盤監聽來達到玩家實時控制遊戲的目的,並且通過不同的按鍵調用四格方塊移動的不同方法。

具體代碼如下:

//開啟鍵盤監聽事件
   KeyListener l=new KeyAdapter() {
    
    
    public void keyPressed(KeyEvent e){
     //獲取以下鍵子的代號
     int code=e.getKeyCode();
     switch (code) {
     case KeyEvent.VK_DOWN:
      softDropAction();break;
     case KeyEvent.VK_LEFT:
      moveLeftAction();break;
     case KeyEvent.VK_RIGHT:
      moveRightAction();break; 
     }
     repaint();
    }
   };
   this.addKeyListener(l);
   this.requestFocus();
   
   while(true){
    /*
     * 當程序運行到此,會進入睡眠狀態
     * 睡眠時間為300毫秒,單位為毫秒
     * 300毫秒後會自動執行後續代碼
     */
    try {
     Thread.sleep(300);
    } catch (InterruptedException e) {
     
     e.printStackTrace();
    }
    
    if(canDrop()){
     currentOne.softDrop();
    }else{
     landToWall();
     //將下一個下落的四格方塊賦值給正在下落的變量
     currentOne=nextOne;
     nextOne=Tetromino.randomOne();
    }
    
    /*
     * 下落之後,要重新進行繪製,才會看到下落後的位置
     * repaint方法也是Jpanel類中提供的
     * 此方法調用了paint方法
     */
    repaint();
   }
  }
 實現效果如下:


 



[lousu-xi ] Java實現簡易俄羅斯方塊已經有405次圍觀

http://coctec.com/docs/java/show-post-238758.html