Java俄羅斯方塊小游戲
去年就已經(jīng)學(xué)了這個(gè)技術(shù)了,一直沒(méi)去寫(xiě),現(xiàn)在抽個(gè)時(shí)間寫(xiě)了個(gè)俄羅斯方塊游戲。
只有簡(jiǎn)單的新游戲,暫停,繼續(xù),積分功能。簡(jiǎn)單的實(shí)現(xiàn)了俄羅斯的經(jīng)典功能。
不介紹了,有興趣的自己運(yùn)行一下,后面貼出了圖片。
代碼:
package cn.hncu; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.Timer; public class Tetris extends JFrame{ public static void main(String[] args) { Tetris te = new Tetris(); te.setVisible(true); //如果在界面中添加了編輯框等會(huì)搶占焦點(diǎn)的控件,則需要用下面的代碼 //te.requestFocus(true);//讓游戲面板獲得焦點(diǎn)--搶到鍵盤(pán)的監(jiān)聽(tīng) } private TetrisPanel tp; JMenuItem itemPause; JMenuItem itemContinue; public Tetris() { this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setLocation(700, 200); this.setSize(220, 275); this.setResizable(false); tp = new TetrisPanel(); this.getContentPane().add(tp); //添加菜單 JMenuBar menubar = new JMenuBar(); this.setJMenuBar(menubar); JMenu menuGame = new JMenu("游戲"); menubar.add(menuGame); JMenuItem itemNew = new JMenuItem("新游戲"); itemNew.setActionCommand("new"); itemPause = new JMenuItem("暫停"); itemPause.setActionCommand("pause"); itemContinue = new JMenuItem("繼續(xù)"); itemContinue.setActionCommand("continue"); itemContinue.setEnabled(false); menuGame.add(itemNew); menuGame.add(itemPause); menuGame.add(itemContinue); MenuListener menuListener = new MenuListener(); itemNew.addActionListener(menuListener); itemPause.addActionListener(menuListener); itemContinue.addActionListener(menuListener); //讓整個(gè)JFrame添加鍵盤(pán)監(jiān)聽(tīng) this.addKeyListener( tp.listener ); } class MenuListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { //玩新游戲 if(e.getActionCommand().equals("new")){ tp.newGame(); } if(e.getActionCommand().equals("pause")){ timer.stop(); itemContinue.setEnabled(true); itemPause.setEnabled(false); } if(e.getActionCommand().equals("continue")){ timer.restart(); itemContinue.setEnabled(false); itemPause.setEnabled(true); } } } private Timer timer; class TetrisPanel extends JPanel{ // 方塊的形狀: // 第一維代表方塊類型(包括7種:S、Z、L、J、I、O、T) // 第二維代表旋轉(zhuǎn)次數(shù) // 第三四維代表方塊矩陣 // shapes[type][turnState][i] i--> block[i/4][i%4] int shapes[][][] = new int[][][] { /* * 模板 { {0,0,0,0,0,0,0,0, 0,0,0,0, 0,0,0,0}, {0,0,0,0,0,0,0,0, 0,0,0,0, * 0,0,0,0}, {0,0,0,0,0,0,0,0, 0,0,0,0, 0,0,0,0}, {0,0,0,0,0,0,0,0, * 0,0,0,0, 0,0,0,0} } */ // I (※把版本1中的橫條從第1行換到第2行) { { 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, 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 } }, // 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 } } }; private int blockType;//方塊類型 private int turnState;//旋轉(zhuǎn)狀態(tài) private int x;//方塊的位置x--列的位置--列號(hào) private int y;//方塊的位置y--行的位置--行號(hào) private int map[][]=new int[13][23];//地圖:12列22行。為防止越界,數(shù)組開(kāi)成:13列23行 private int delay=1000; public TimerKeyLister listener=new TimerKeyLister(); private int score=0;//分?jǐn)?shù) public TetrisPanel(){ newGame(); nextBlock(); //timer = new Timer(delay,listener); //timer.start(); } public void newGame() { blockType = (int)(Math.random()*1000)%7; turnState = (int)(Math.random()*1000)%4; x=4; y=0; for( int i=0;i<12;i++){//走列 for(int j=0;j<21;j++){//走行 if(i==0 || i==11){//3為界面邊框的格 map[i][j]=3;//按理只要用0和1以外的整數(shù)就可以,但這里用3有特殊作用--后面用 }else{ map[i][j]=0; } } map[i][21]=3;//3為界面邊框的格 } if(timer!=null){ timer.stop(); } delay=1000; timer = new Timer(delay,listener); timer.start(); } private void nextBlock() { blockType = (int)(Math.random()*1000)%7; turnState = (int)(Math.random()*1000)%4; x=4; y=0; //game Over if(crash(x,y,blockType,turnState)==0){ timer.stop(); int option = JOptionPane.showConfirmDialog(this, "Game Over!!,還敢來(lái)嗎..."); if (option == JOptionPane.OK_OPTION) { newGame(); } else if (option == JOptionPane.NO_OPTION) { System.exit(0); } } } private void down() { if( crash(x,y+1,blockType,turnState)==0 ){//注意,這里用y+1,是判斷塊往下掉一格后,map中對(duì)應(yīng)位置是否為堆積塊或框架 add(x,y,blockType,turnState);//把當(dāng)前方塊的信息保存到地圖 nextBlock(); }else{ y++; } repaint(); } private void left() { if(x>=0){ x -= crash(x-1,y,blockType,turnState); } repaint(); } private void right() { if(x<8){ x += crash(x+1,y,blockType,turnState); } repaint(); } private void turn() { if(crash(x,y,blockType,(turnState+1)%4)==1 ){ turnState = (turnState+1)%4; } repaint(); } private void add(int x, int y, int blockType, int turnState) { for( int a=0; a<4; a++){ for(int b=0; b<4; b++){ if( shapes[blockType][turnState][a*4+b] ==1 ){ map[x+b+1][y+a] = 1; } } } tryDelLine(); } //消行 private void tryDelLine(){ for(int b=0;b<21;b++){ int c=1; for(int a=0;a<12;a++){ c &= map[a][b];//全部是1,c的結(jié)果才是1 } if(c==1){//有一行需要消 //依次往下移動(dòng)一行 for(int d=b; d>0; d--){ for(int e=0;e<11;e++){ map[e][d] = map[e][d-1]; } } //加分 score +=100; delay /=1.05; timer.setDelay(delay); } } } //參數(shù)例子: 4,3,2,3 //判斷有無(wú)碰撞 private int crash(int x, int y, int blockType, int turnState){ for( int a=0; a<4; a++){ for(int b=0; b<4; b++){ // if( (shapes[blockType][turnState][a*4+b]==1 && map[x+b+1][y+a] ==1) || // (shapes[blockType][turnState][a*4+b]==1 && map[x+b+1][y+a] ==3 ) ){ // } if( (shapes[blockType][turnState][a*4+b] & map[x+b+1][y+a]) ==1 ){ return 0;//碰撞 } } } return 1;//沒(méi)有碰撞 } @Override public void paint(Graphics g) { // blockType =6; // turnState = 3; // x=4; // y=6; super.paint(g);//消除殘影 g.setColor(new Color(153,51,205)); //畫(huà)當(dāng)前方塊 for(int j=0;j<16;j++){ if(shapes[blockType][turnState][j]==1){ g.fillRect((j%4+x+1)*10, (j/4+y)*10, 10, 10); g.setColor(Color.cyan); g.drawRect((j%4+x+1)*10, (j/4+y)*10, 10, 10); g.setColor(new Color(153,51,205)); } } //畫(huà)界面框架 以及 堆積塊---整個(gè)地圖 g.setColor(Color.red); for( int i=0;i<12;i++){//走列 for(int j=0;j<22;j++){//走行 if(map[i][j]==3){ g.drawRect(i*10, j*10, 10, 10); }else if(map[i][j]==1){ g.fillRect(i*10, j*10, 10, 10); g.setColor(Color.GREEN); g.drawRect(i*10, j*10, 10, 10); g.setColor(Color.red); } } } //顯示分?jǐn)?shù),同時(shí)為版面美觀,在界面上再加點(diǎn)東西 // 畫(huà)方塊區(qū)右側(cè)部分 g.setColor(Color.red); g.setFont(new Font("aa", Font.BOLD, 11)); g.drawString("score=" + score, 130, 20); g.setFont(new Font("aa", Font.PLAIN, 13)); g.setColor(Color.blue); g.drawString("拒絕盜版游戲,", 125, 70); g.drawString("注意自我保護(hù)。", 125, 90); g.drawString("謹(jǐn)防受騙上當(dāng)。", 125, 110); g.drawString("適度游戲益腦,", 125, 130); g.drawString("沉迷游戲傷身。", 125, 150); g.drawString("合理安排時(shí)間,", 125, 170); g.drawString("享受健康生活。", 125, 190); } class TimerKeyLister extends KeyAdapter implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { down(); } @Override public void keyPressed(KeyEvent e) { switch(e.getKeyCode()){ case KeyEvent.VK_DOWN: down(); break; case KeyEvent.VK_LEFT: left();break; case KeyEvent.VK_RIGHT: right();break; case KeyEvent.VK_UP: turn();break; case KeyEvent.VK_F1: plug(); case KeyEvent.VK_F2: time(); } } } public void plug() { score+=100; } public void time() { delay =1000; timer.setDelay(delay); } } }
運(yùn)行界面:
更多精彩游戲,請(qǐng)參考專題《java經(jīng)典小游戲》
更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot單點(diǎn)登錄實(shí)現(xiàn)過(guò)程詳細(xì)分析
這篇文章主要介紹了SpringBoot單點(diǎn)登錄實(shí)現(xiàn)過(guò)程,單點(diǎn)登錄英文全稱Single?Sign?On,簡(jiǎn)稱就是SSO。它的解釋是:在多個(gè)應(yīng)用系統(tǒng)中,只需要登錄一次,就可以訪問(wèn)其他相互信任的應(yīng)用系統(tǒng)2022-12-12java注解處理器學(xué)習(xí)在編譯期修改語(yǔ)法樹(shù)教程
這篇文章主要為大家介紹了java注解處理器學(xué)習(xí)在編譯期修改語(yǔ)法樹(shù)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Java中DataInputStream和DataOutputStream的使用方法
這篇文章主要介紹了Java中DataInputStream和DataOutputStream的使用方法,通過(guò)創(chuàng)建對(duì)象展開(kāi)具體的內(nèi)容介紹,需要的小伙伴可以參考一下2022-05-05java中l(wèi)ambda表達(dá)式簡(jiǎn)單用例
讓我們從最簡(jiǎn)單的例子開(kāi)始,來(lái)學(xué)習(xí)如何對(duì)一個(gè)string列表進(jìn)行排序。我們首先使用Java 8之前的方法來(lái)實(shí)現(xiàn)2016-09-09Java網(wǎng)絡(luò)編程實(shí)現(xiàn)多線程聊天
這篇文章主要為大家詳細(xì)介紹了Java網(wǎng)絡(luò)編程實(shí)現(xiàn)多線程聊天,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07微信js sdk invalid signature簽名錯(cuò)誤問(wèn)題的解決方法分析
這篇文章主要介紹了微信js sdk invalid signature簽名錯(cuò)誤問(wèn)題的解決方法,結(jié)合實(shí)例形式分析了微信簽名錯(cuò)誤問(wèn)題相關(guān)解決方法,需要的朋友可以參考下2019-04-04