Java游戲開(kāi)發(fā)之俄羅斯方塊的實(shí)現(xiàn)
俄羅斯方塊小游戲
簡(jiǎn)單的實(shí)現(xiàn)俄羅斯方塊,只有一個(gè)主代碼,很好理解的,有暫停/繼續(xù)、重新開(kāi)始、結(jié)束游戲的簡(jiǎn)單功能。這里就不多說(shuō)實(shí)現(xiàn)的原理了,可以在網(wǎng)上進(jìn)行相關(guān)的查詢(xún)。這里就直接給出了源代碼,這個(gè)也是我參考網(wǎng)上的,自己進(jìn)行了相關(guān)的更改,增加了一些功能。
import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.imageio.*; import javax.swing.*; import javax.swing.Timer; public class MyGame extends JFrame { public MyGame(){ GameBody gamebody=new GameBody(); gamebody.setBounds(5,10,500,600); // gamebody.setOpaque(false); gamebody.setLayout(null); addKeyListener(gamebody); add(gamebody); int w=Toolkit.getDefaultToolkit().getScreenSize().width; int h=Toolkit.getDefaultToolkit().getScreenSize().height; JLabel image=new JLabel(new ImageIcon("13.jpg")); image.setBounds(0,0,500,600); getLayeredPane().setLayout(null); getLayeredPane().add(image,new Integer(Integer.MIN_VALUE)); ((JPanel)getContentPane()).setOpaque(false); final JButton login=new JButton(new ImageIcon("login4.PNG")); login.setContentAreaFilled(false); login.setMargin(new Insets(0,0,0,0)); login.setBorderPainted(false); login.setBounds(340,320,120,26); gamebody.add(login); login.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { //登錄的按鈕 if(e.getSource()==login){ requestFocus(true); //獲得焦點(diǎn),不用失去焦點(diǎn) gamebody.resetMap(); //重置地圖 gamebody.drawWall(); //沖重新繪制邊界墻體 gamebody.createshape(); //重新產(chǎn)生新的地圖 gamebody.setStart(false); //喚醒定時(shí)下落的線程 gamebody.score=0; //將分?jǐn)?shù)置為零 repaint(); } } }); final JButton pauselogin=new JButton(new ImageIcon("login6.PNG")); pauselogin.setContentAreaFilled(false); pauselogin.setMargin(new Insets(0,0,0,0)); pauselogin.setBorderPainted(false); pauselogin.setBounds(340,370,120,26); gamebody.add(pauselogin); pauselogin.addMouseListener(new MouseListener(){ //暫停的按鈕 /* public void actionPerformed(ActionEvent e) { //用事件監(jiān)聽(tīng),沒(méi)用實(shí)現(xiàn)再次按暫停鍵后繼續(xù)游戲 //while(true){ if (e.getSource()==pauselogin) { gamebody.setStart(true); requestFocus(true); }if(e.getSource()==login){ new GameBody.setStart(false); requestFocus(true); } //} }*/ //鼠標(biāo)點(diǎn)擊事件,可以分別判斷不同的事件,做出不同的反應(yīng) public void mouseClicked(MouseEvent e){ if(e.getButton()==e.BUTTON1 ){ //單擊左鍵暫停 gamebody.setStart(true); //將自動(dòng)下落線程關(guān)閉 //requestFocus(true); //同時(shí)整個(gè)JFrame失去焦點(diǎn),無(wú)法操作,但可以點(diǎn)擊按鈕 } else if(e.getButton()==e.BUTTON3 ){ //右擊暫停,繼續(xù)游戲 gamebody.setStart(false); //喚醒自動(dòng)下落線程 requestFocus(true); } if(e.getClickCount()==2){ //左鍵雙擊,也可以繼續(xù)游戲 gamebody.setStart(false); requestFocus(true); } } public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mousePressed(MouseEvent e){} public void mouseReleased(MouseEvent e){} }); final JButton overlogin=new JButton(new ImageIcon("login5.PNG")); //退出的按鈕 overlogin.setMargin(new Insets(0,0,0,0)); overlogin.setContentAreaFilled(false); overlogin.setBounds(340,420,120,26); overlogin.setBorderPainted(false); add(overlogin); overlogin.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { System.exit(1); } }); setTitle("俄羅斯方塊 V.1.0"); setResizable(false); setFocusable(true); setBounds((w-500)/2,(h-600)/2,500,600); setLayout(null); setVisible(true); setDefaultCloseOperation(3); } public static void main(String[] args) { new MyGame(); } //創(chuàng)建需要定義的局部變量和游戲類(lèi) class GameBody extends JPanel implements KeyListener{ private int shapeType=-1; //定義方塊的類(lèi)型 定義的為7中 private int shapeState=-1; //定義方塊為何種狀態(tài),每種都有四種狀態(tài) private int nextshapeType=-1; //定義下一塊產(chǎn)生的類(lèi)型 private int nextshapeState=-1; //定義下一塊的方塊的狀態(tài) private final int CELL=25; //定義方格的大小 private int score=0; //定義顯示的成績(jī) private int left; //定義初始圖形與兩邊的墻的距離 private int top; //定義初始圖形與上下墻的距離 private int i=0; //表示列 private int j=0; //表示行 public int flag=0; public volatile boolean start=false; //暫停的判斷條件,為輕量鎖,保持同步的 //public boolean start=false; //Timer t; Random randomcolor=new Random(); Random random=new Random(); //定義地圖的大小,創(chuàng)建二位的數(shù)組 int[][] map=new int[13][23]; //初始化地圖 public void resetMap(){ for(i=0;i<12;i++){ for(j=0;j<22;j++){ //遍歷的范圍不能小 map[i][j]=0; } } } //畫(huà)圍墻的方法 public void drawWall(){ for(j=0;j<22;j++) //0到21行 { map[0][j]=2; map[11][j]=2; //第0行和第11行為墻 } for(i=0;i<12;i++){ //0到11列 map[i][21]=2; //第21行劃墻 } } //定義隨機(jī)的圖形種類(lèi) private final int[][][] shapes=new int[][][]{ // 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 } }, // s { { 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, 0, 0, 0, 1, 1, 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, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // o { { 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 } }, // l { { 1, 0, 0, 0, 1, 0, 0, 0, 1, 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, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // 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 } } }; //產(chǎn)生新圖形的方法 public void createshape(){ if(shapeType==-1&&shapeState==-1){ shapeType = random.nextInt(shapes.length); shapeState = random.nextInt(shapes[0].length); }else{ shapeType=nextshapeType; shapeState=nextshapeState; } nextshapeType = random.nextInt(shapes.length); nextshapeState = random.nextInt(shapes[0].length); //shapeType=(int)(Math.random()*1000)%7; //在7中類(lèi)型中隨機(jī)選取 //shapeState=(int)(Math.random()*1000)%4; //在四種狀態(tài)中隨機(jī)選取 left=4; top=0; //圖形產(chǎn)生的初始位置為(4,0)\ if(gameOver(left,top)==1){ //判斷游戲 resetMap(); drawWall(); score=0; JOptionPane.showMessageDialog(null, "GAME OVER"); } } //遍歷[4][4]數(shù)組產(chǎn)生的方塊并判斷狀態(tài) public int judgeState(int left,int top,int shapeType,int shapeState){ for(int a=0;a<4;a++){ for(int b=0;b<4;b++){ if(((shapes[shapeType][shapeState][a*4+b]==1 && //遍歷數(shù)組中為1的個(gè)數(shù),即判斷是否有圖形 map[left+b+1][top+a]==1))|| //判斷地圖中是否還有障礙物 ((shapes[shapeType][shapeState][a*4+b]==1 && //遍歷數(shù)組中為1的個(gè)數(shù),即判斷是否有圖形 map[left+b+1][top+a]==2))){ //判斷是否撞墻 return 0; //表明無(wú)法不能正常運(yùn)行 } } } return 1; } //創(chuàng)建鍵盤(pán)事件監(jiān)聽(tīng) public void keyPressed(KeyEvent e){ //if (start){ switch(e.getKeyCode()){ case KeyEvent.VK_LEFT: leftMove();//調(diào)用左移的方法 repaint(); break; case KeyEvent.VK_RIGHT: rightMove();//調(diào)用右移的方法 repaint(); break; case KeyEvent.VK_DOWN: downMove();//調(diào)用左移的方法 repaint(); break; case KeyEvent.VK_UP: turnShape();//調(diào)用變形的方法 repaint(); break; } // } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } //創(chuàng)建左移的方法 public void leftMove(){ if(judgeState(left-1,top,shapeType,shapeState)==1){ left-=1; } } //創(chuàng)建右移的方法 public void rightMove(){ if(judgeState(left+1,top,shapeType,shapeState)==1){ left+=1; }; } //創(chuàng)建下移的方法 public void downMove(){ if(judgeState(left,top+1,shapeType,shapeState)==1){ //判斷有圖形 top+=1; deleteLine(); //判斷下移后是否有滿行 } if(judgeState(left,top+1,shapeType,shapeState)==0){ //判斷沒(méi)有圖形 addshape(left,top,shapeType,shapeState); createshape(); deleteLine(); } } //創(chuàng)建旋轉(zhuǎn)變形的方法 public void turnShape(){ int tempshape=shapeState; shapeState=(shapeState+1)%4; //在四中的狀態(tài)中選取 if(judgeState(left,top,shapeType,shapeState)==1){ } if(judgeState(left,top,shapeType,shapeState)==0){ shapeState=tempshape; //沒(méi)有圖形,不能進(jìn)行旋轉(zhuǎn),還原原來(lái)狀態(tài) } repaint(); } //繪圖方法 public void paintComponent(Graphics g){ super.paintComponent(g); int t=randomcolor.nextInt(5); int count=randomcolor.nextInt(5); Color[] color=new Color[]{Color.pink,Color.green,Color.red,Color.yellow,Color.blue}; /* Image image = null; try { image = ImageIO.read(new File("1.jpg")); } catch (IOException e) { // TODO 自動(dòng)生成的 catch 塊 e.printStackTrace(); g.drawImage(image, 0, 0,this); }*/ //繪制圍墻 for(j=0;j<22;j++){ for(i=0;i<12;i++){ if(map[i][j]==2){//判斷是否為墻并繪制 g.setColor(Color.blue); g.fill3DRect(i*CELL,j*CELL,CELL,CELL,true); } if(map[i][j]==0){//判斷是否為墻并繪制 g.setColor(Color.red); g.drawRoundRect(i*CELL,j*CELL,CELL,CELL,6,6);} } } //繪制正在下落的圖形 for(int k=0;k<16;k++){ if(shapes[shapeType][shapeState][k]==1){ g.setColor(Color.red); g.fill3DRect((left+k%4+1)*CELL,(top+k/4)*CELL,CELL,CELL,true); //left\top為左上角的坐標(biāo) } } //繪制落下的圖形 for(j=0;j<22;j++){ for(i=0;i<12;i++){ if(map[i][j]==1){ g.setColor(Color.green); g.fill3DRect(i*CELL,j*CELL,CELL,CELL,true); } } } //顯示右邊預(yù)覽圖形 for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++){ if(shapes[nextshapeType][nextshapeState][i*4+j] == 1) { g.setColor(Color.red); g.fill3DRect(375+(j*(CELL-10)),190+(i*(CELL-10)), CELL-10, CELL-10,true); } } } //添加右邊預(yù)覽圖形方格 for(int i = 0; i < 5; i++) { for(int j = 0; j < 5; j++){ g.setColor(Color.blue); g.drawRoundRect(360+(j*(CELL-10)),175+(i*(CELL-10)),CELL-10, CELL-10,3,3); } } g.setFont(new Font("楷書(shū)",Font.BOLD,20)); g.setColor(Color.BLUE); g.drawString("游戲分?jǐn)?shù):", 310, 70); g.setColor(Color.RED); g.drawString(score+" ", 420, 70); g.setColor(Color.BLUE); g.drawString(" 分", 450, 70); } //創(chuàng)建添加新圖形到地圖的方法、 public void addshape(int left,int top,int shapeType,int shapeState){ int temp=0; for(int a=0;a<4;a++){ for(int b=0;b<4;b++){ //對(duì)存儲(chǔ)方塊隊(duì)的[4][4]數(shù)組遍歷 if(map[left+b+1][top+a]==0){ //表明[4][4]數(shù)組沒(méi)有方塊 map[left+b+1][top+a]=shapes[shapeType][shapeState][temp]; } temp++; } } } //創(chuàng)建消行的方法,即將滿行以上的部分整體下移 public void deleteLine(){ int tempscore=0; //定義滿行的列個(gè)數(shù)滿足1 for(int a=0;a<22;a++){ //對(duì)地圖進(jìn)行遍歷 for(int b=0;b<12;b++){ if(map[b][a]==1){ //表示找到滿行 tempscore++; // 記錄一行有多少個(gè)1 if(tempscore==10){ score+=10; for(int k=a;k>0;k--){ //從滿行開(kāi)始回歷 for(int c=1;c<12;c++){ map[c][k]=map[c][k-1]; //將圖形整體下移一行 } } } } } tempscore=0; } } //判斷游戲結(jié)束,1、判斷新塊的狀態(tài)是否不存在,即judgeState()==0 //2、判斷初始產(chǎn)生的位置是否一直為1; public int gameOver(int left,int top){ if(judgeState(left,top,shapeType,shapeState)==0){ return 1; } return 0; } //創(chuàng)建構(gòu)造方法 public GameBody(){ resetMap(); drawWall(); createshape(); //Timer timer=new Timer(1000,new TimeListener()); Thread timer=new Thread(new TimeListener()); timer.start(); } public void setStart(boolean start){ //改變start值的方法 this.start=start; } //創(chuàng)建定時(shí)下落的監(jiān)聽(tīng)器 class TimeListener implements Runnable{ public void run(){ while(true){ if(!start){ try{ repaint(); if(judgeState(left,top+1,shapeType,shapeState)==1){ top+=1; deleteLine();} if(judgeState(left,top+1,shapeType,shapeState)==0){ if(flag==1){ addshape(left,top,shapeType,shapeState); deleteLine(); createshape(); flag=0; } flag=1; } Thread.sleep(800); }catch(Exception e){ e.getMessage(); } } } } } } } //外層
下面是游戲演示的一些界面效果圖:
這里說(shuō)一下,我是把圖片和源代碼直接放在了一個(gè)文件夾下,對(duì)于初學(xué)者很好理解,這也是很好的練手項(xiàng)目。圖片什么的大家可以在網(wǎng)上直接找一個(gè),然后重命名一下就可了。
以上就是Java游戲開(kāi)發(fā)之俄羅斯方塊的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Java俄羅斯方塊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)線程的暫停和恢復(fù)的示例詳解
這幾天的項(xiàng)目中,客戶給了個(gè)需求,希望我可以開(kāi)啟一個(gè)任務(wù),想什么時(shí)候暫停就什么時(shí)候暫停,想什么時(shí)候開(kāi)始就什么時(shí)候開(kāi)始,所以本文小編給大家介紹了Java實(shí)現(xiàn)線程的暫停和恢復(fù)的示例,需要的朋友可以參考下2023-11-11詳解Spring Cloud Gateway基于服務(wù)發(fā)現(xiàn)的默認(rèn)路由規(guī)則
這篇文章主要介紹了詳解Spring Cloud Gateway基于服務(wù)發(fā)現(xiàn)的默認(rèn)路由規(guī)則,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05SpringBoot實(shí)現(xiàn)服務(wù)接入nacos注冊(cè)中心流程詳解
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)服務(wù)接入nacos注冊(cè)中心流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-01-01Java中枚舉類(lèi)enum的values()方法舉例詳解
這篇文章主要給大家介紹了關(guān)于Java中枚舉類(lèi)enum的values()方法舉例詳解,作為一種常用方法,可以在枚舉中對(duì)數(shù)組里的枚舉值進(jìn)行遍歷,這就是values()方法的使用,需要的朋友可以參考下2023-11-11springboot整合mybatis實(shí)現(xiàn)多表查詢(xún)的實(shí)戰(zhàn)記錄
SpringBoot對(duì)數(shù)據(jù)庫(kù)操作有多種方式,下面這篇文章主要給大家介紹了關(guān)于springboot整合mybatis實(shí)現(xiàn)多表查詢(xún)的相關(guān)資料,文中通過(guò)示例代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08Javaweb使用thymeleaf局部刷新結(jié)合Layui插件實(shí)現(xiàn)Html分頁(yè)
本文主要介紹了Javaweb使用thymeleaf局部刷新結(jié)合Layui插件實(shí)現(xiàn)Html分頁(yè),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10SpringBoot整合Mybatis實(shí)現(xiàn)CRUD
這篇文章主要介紹了SpringBoot整合Mybatis實(shí)現(xiàn)CRUD的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09