Java實(shí)現(xiàn)經(jīng)典游戲俄羅斯方塊(升級(jí)版)的示例代碼
前言
俄羅斯方塊是一款風(fēng)靡全球,從一開始到現(xiàn)在都一直經(jīng)久不衰的電腦、手機(jī)、掌上游戲機(jī)產(chǎn)品,是一款游戲規(guī)則簡(jiǎn)單,但又不缺乏樂趣的簡(jiǎn)單經(jīng)典小游戲,上手容易,適用范圍廣泛,人所共知。俄羅斯方塊游戲簡(jiǎn)單的基本規(guī)則是有小方塊組成的7種不同的規(guī)則圖形陸續(xù)從屏幕上落下,玩家操作移動(dòng)使其下落拼出一條完整的橫條,隨即會(huì)消失,玩家得分,游戲等級(jí)提高,當(dāng)沒有被消除的圖形堆積到屏幕頂端時(shí),游戲結(jié)束。
俄羅斯方塊游戲最初是由俄羅斯人阿列克謝·帕基特諾夫在1984年開發(fā)的休閑小游戲,曾幾何時(shí)它創(chuàng)造了無可匹敵的商業(yè)價(jià)值,影響了一代休閑小游戲的開發(fā)與產(chǎn)業(yè)鏈。隨著信息時(shí)代科技時(shí)代的不斷發(fā)展和變化,計(jì)算機(jī)已經(jīng)普及到每一個(gè)人的生活中,在繁忙的工作生活中,這一類休閑小游戲給人們帶來了些許的放松。
《俄羅斯方塊升級(jí)版》游戲用java語言實(shí)現(xiàn),采用了swing技術(shù)進(jìn)行了界面化處理,設(shè)計(jì)思路用了面向?qū)ο笏枷搿?/p>
主要需求
整個(gè)游戲系統(tǒng)會(huì)隨機(jī)產(chǎn)生7種由四個(gè)小方塊組成的不同形狀的方塊,經(jīng)過旋轉(zhuǎn)后得到28種狀態(tài),如果增加游戲難度,會(huì)增加六種不同形狀的方塊形狀,同樣經(jīng)過旋轉(zhuǎn)后增加24種狀態(tài)。方塊按一定的速度自由下落,玩家通過鍵盤上的上下左右按鍵控制方塊的左右移動(dòng)和旋轉(zhuǎn),將方塊落下后放在合適的位置。當(dāng)方塊落下后,如果方塊落下后有一整行被方塊填滿,那么該一整行消去。當(dāng)一行被消去時(shí),玩家得分增加10分,當(dāng)?shù)梅诌_(dá)到100分后,玩家等級(jí)增加一級(jí),速度加快一級(jí),難度加大。如果當(dāng)方塊落下后整個(gè)游戲畫布界面被占滿,則方塊不再下落,游戲宣告失敗。游戲具體的功能需求有如下幾個(gè):
游戲界面需求:游戲的良好的界面會(huì)讓玩家眼前一亮,更加能充分的感受到游戲帶來的娛樂性,放松性。本游戲的默認(rèn)背景色是深綠色,游戲主界面畫面自定義為自己的所喜歡的圖片,并可以更改,主界面方塊默認(rèn)用橘黃色,預(yù)顯方塊顏色默認(rèn)為淡紫色。背景色、前景色對(duì)比鮮明,以達(dá)到讓玩家眼前一亮的感覺,并能在游戲達(dá)到高等級(jí)狀態(tài),方塊下落速度漸高的情況下使玩家能夠清楚的分辨出下落方塊的形狀,增加游戲的刺激性。
游戲形狀需求:用數(shù)組作為存儲(chǔ)方塊52種狀態(tài)的數(shù)據(jù)結(jié)構(gòu),即初級(jí)等級(jí)長(zhǎng)條形、Z字形、反Z形、田字形、7字形、反7形、T字型一共7種形狀的向4個(gè)方向的旋轉(zhuǎn)變形,和中級(jí)等級(jí)的三種方塊12種不同的狀態(tài),高級(jí)等級(jí)的三種方塊12種不同的狀態(tài)。各個(gè)方塊可以實(shí)現(xiàn)按逆時(shí)針的旋轉(zhuǎn)方式旋轉(zhuǎn),并且方塊能否旋轉(zhuǎn)需要用條件加以判斷,如果旋轉(zhuǎn)后可能發(fā)生越界,則不能旋轉(zhuǎn),需要調(diào)整位置來保證他可以旋轉(zhuǎn)。
主要設(shè)計(jì)
以下該游戲中類的設(shè)計(jì):
MyFrame類:繼承自JFrame類,作為游戲的主類,負(fù)責(zé)對(duì)游戲的主體全局進(jìn)行控制,連接與指揮各個(gè)類的樞紐。
PreView類:繼承自JPanel類,作為操作面板類,負(fù)責(zé)安放主游戲窗口,積分板,級(jí)別控制按鈕等窗口用以控制游戲進(jìn)程。
GameCanvas類:繼承自JPanel類,ChangeBlockColor線程類動(dòng)態(tài)改變畫布類的方格顏色,畫布類通過檢查方格顏色來體現(xiàn)ChangeBlockColor方塊的移動(dòng)情況與消去狀況。
Box類:方格類,組成方塊的基本元素,主要表達(dá)方式為顏色。
Block類:作為操控方塊的類,控制方塊的移動(dòng),下落以及變形。
游戲主界面顯示模塊:
游戲主界面采用Swing組件開發(fā),并且向其注冊(cè)監(jiān)聽器,以實(shí)現(xiàn)各種控制功能,綜合游戲窗體的設(shè)計(jì),其上至少需要注冊(cè)三個(gè)監(jiān)聽器,分別是動(dòng)作監(jiān)聽器(ActionListener)、鍵盤監(jiān)聽器(KeyListener)、選項(xiàng)監(jiān)聽器(ItemListener)。
根據(jù)初步設(shè)計(jì),可以確定客戶端上所要用到的Swing組件對(duì)象有JFrame對(duì)象、JPanel對(duì)象,JLabel對(duì)象、JButton對(duì)象、JMenuBar對(duì)象、JMenu對(duì)象、JMenuItem對(duì)象、JTextField對(duì)象、JTextArea對(duì)象、JDialog對(duì)象等,至少十個(gè)Swing組件對(duì)象。
背景畫布模塊設(shè)計(jì):該游戲的主背景畫布是一個(gè)20行、12列的二維數(shù)組,方塊顯示是由相應(yīng)顏色變化來標(biāo)識(shí),主窗體用顏色填充后可形成呈現(xiàn)出來背景樣式和方塊。本游戲用繼承自JPanel的GameCanvas類控制背景畫布的顯示,用rows代表畫布的行數(shù),cols代表畫布的列數(shù),行數(shù)和列數(shù)決定著畫布擁有方格的數(shù)目。
預(yù)覽方塊模塊設(shè)計(jì):方塊和數(shù)據(jù)信息是游戲中最基本的功能模塊。Box這個(gè)類方格類,是組成塊的基本元素,用自己的顏色來表示塊的外觀 ,MyTask繼承TimerTask類用來定時(shí)下落,用計(jì)數(shù)方式來實(shí)現(xiàn)速度的改變,MyListener類繼承KeyAdapter類用來實(shí)現(xiàn)按鍵監(jiān)聽,控制方塊的上下左右。定義一個(gè)4x4方陣,共16個(gè)小格。用“0”和“1”來表示每個(gè)方格是繪制新顏色還是保留底色。
方塊移動(dòng)、旋轉(zhuǎn)模塊設(shè)計(jì):方塊的翻轉(zhuǎn)與移動(dòng)比較容易實(shí)現(xiàn),方塊移動(dòng)只需要改變方塊的橫坐標(biāo)或縱坐標(biāo),然后重新繪制方塊即可。方塊翻轉(zhuǎn)也只需要改變背景數(shù)組的值,重新繪制方即可。
本游戲方塊下落時(shí),進(jìn)行動(dòng)態(tài)繪制,實(shí)現(xiàn)Cloneable接口, 以指示 Object.clone() 方法可以合法地對(duì)該類實(shí)例進(jìn)行按字段復(fù)制。方塊的操作類BlockOperation繼承Thread類,重寫run()方法,以實(shí)現(xiàn)方塊的動(dòng)態(tài)正確下落。當(dāng)然,在線程中要判定方塊是處于moving狀態(tài)還是pausing狀態(tài)
功能截圖
游戲開始主界面:
游戲菜單:
設(shè)計(jì)方塊顏色:
代碼實(shí)現(xiàn)
MyFrame
public class MyFrame extends JFrame{ JPanel jp_pan=new JPanel(); JPanel jp_pre=new JPanel(); JPanel jp_ctrl=new JPanel(); JPanel jp_scor=new JPanel(); Zidingyi zi; JRadioButtonMenuItem jr1=new JRadioButtonMenuItem("初級(jí)",true); JRadioButtonMenuItem jr2=new JRadioButtonMenuItem("中級(jí)"); JRadioButtonMenuItem jr3=new JRadioButtonMenuItem("高級(jí)"); JLabel jt9=new JLabel("得分:0" ); static JLabel jt10=new JLabel("等級(jí):1" ); JMenu m1=new JMenu("游戲"); JMenu m2=new JMenu("幫助"); JCheckBox jc1; JSlider jsl; // Dialog dia;//創(chuàng)建對(duì)話框 static ImageIcon background = new ImageIcon(Constant.backGround1); // 把背景圖片加到label static JLabel label = new JLabel(background); // Dialog dia=new Dialog(this, "自定義", false); int scor=0;//初始化分?jǐn)?shù)為0 static int rank=0;//初始化等級(jí)為0 int highC=0; boolean upspeed=false; boolean isTime=true; boolean runstop; static boolean isRank=false; static boolean changeBack=false; public static boolean playing=false; static boolean isMusic=true; static boolean high=false; PreView pv=new PreView(); JMenuItem ji1=new JMenuItem("開局"); GameCanvas gc=new GameCanvas(20, 12);//畫出20行12列 private Block block=new Block();//當(dāng)前塊 private int newspeed=1000;//默認(rèn)當(dāng)前等級(jí)為1 MusicPlayer mp=new MusicPlayer(); Timer time=new Timer(); MyTask mytask; int temp=1; // 游戲主構(gòu)造函數(shù) public MyFrame(String str){ super(str); this.setSize(450, 570); Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();//獲取屏幕尺寸 setLocation((scrSize.width - getSize().width) / 2, (scrSize.height - getSize().height) / 2);//設(shè)置屏幕居中 this.setLayout(null); //label的大小為jframe的大小 label.setBounds(0, 0, this.getWidth(), this.getHeight()); //把label加到j(luò)frame的最底層,比jframe上的那個(gè)panel還下面 this.getLayeredPane().add(label, new Integer(Integer.MIN_VALUE)); //label比jframe上的那個(gè)panel還下面,那需要把那個(gè)panel設(shè)為透明的,不然就蓋住背景了 JPanel imagePanel = (JPanel) this.getContentPane(); imagePanel.setOpaque(false); addMenu(); //游戲開始按鈕 ji1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub // 如果游戲已經(jīng)開始,再按一次即顯示游戲結(jié)束 if (playing == true) { ji1.setText("開局"); if(isMusic==true) {mp.playStart();} gc.setGameOver(true); gc.repaint(); MyFrame.rank=11-Constant.step; MyFrame.jt10.setText("等級(jí):"+MyFrame.rank); runstop=true; block.isAlive=false; block=new Block(); mytask.cancel(); playing = false; } else { reset(); if(isMusic==true) {mp.playStart();} MyFrame.rank=11-Constant.step; MyFrame.jt10.setText("等級(jí):"+MyFrame.rank); ji1.setText("結(jié)束游戲"); playing = true; mytask=new MyTask(); time.schedule(mytask, 0, 100);//100毫秒執(zhí)行一次 Thread thread = new Thread(new play());// 調(diào)用開始游戲的方法 thread.start(); } }; }); this.add(gc);//添加游戲畫布 addRight();//添加右邊 this.setFocusable(true);//設(shè)置可獲得焦點(diǎn) this.requestFocus();//設(shè)置焦點(diǎn) this.addKeyListener(new MyListener()); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void setBackGround(){ label.setIcon(background); } /** * 定時(shí)下落,用計(jì)數(shù)方式來實(shí)現(xiàn)速度的改變 * */ private class MyTask extends TimerTask { @Override public void run() { temp++; if (temp % Constant.step == 0) { block.newL = block.x; block.newH = block.y + 1; // block.yy(); if (block.pausing == true) return; if (high == true) { block.earse(); highC++; if (highC == 4) { gc.addRow(); highC = 0; } } if (block.isMoveAble(block.newH, block.newL)) { block.earse(); block.y++; block.display(); gc.repaint(); } else { block.isAlive = false; gc.repaint(); // cancel(); } // 取消定時(shí)器任務(wù) temp = 1; } } } private class play implements Runnable { public void run() { /* if(killThread==true) return;*/ int col = (int) (Math.random() * (gc.getCols() - 3));//隨即位置生成列 int style = Constant.STYLES[(int) (Math.random() * Block.get_addl())][(int) (Math .random() * 4)]; while (playing) { if (block != null) { //判斷當(dāng)前方塊是否死亡 if (block.isAlive) { try { Thread.currentThread().sleep(100); } catch (InterruptedException ie) { ie.printStackTrace(); } continue; } } isFullLine(); // if(upspeed)//判斷是否加速,是的話則進(jìn)行調(diào)用 // upLevel(); if(isGameOver()){ if(isMusic==true) {mp.playGameOver();} gc.setGameOver(true); gc.repaint(); ji1.setText("開局"); mytask.cancel(); playing=false; return; } block = new Block(style, -1, col, gc); block.jixu();//防止在暫停時(shí)候重新開始游戲,暫停字還不消失 gc.repaint();// 將創(chuàng)建出來的方塊顯示出來 block.isAlive = true; col = (int) (Math.random() * (gc.getCols() - 3));//隨即位置生成列 style = Constant.STYLES[(int) (Math.random() * Block.get_addl())][(int) (Math .random() * 4)]; pv.setStyle(style); } } /** * 增加速度 */ private void upLevel() { if(Constant.step-1<1){ return;} Constant.step=Constant.step-1; //速度增加一級(jí) rank++; jt10.setText("等級(jí):"+rank); upspeed=false;//將標(biāo)志位至為false } /** * 判斷是否滿行,滿行則調(diào)用消行方法。 */ private void isFullLine() { // TODO Auto-generated method stub for (int i = 0; i < 20; i++) { int row = 0; boolean flag = true; for (int j = 0; j < 12; j++) { if (!gc.getBox(i, j).isColorBox()) { flag = false; break; } } if (flag == true) { row = i; gc.delete(row);//刪除行 if(isMusic==true) {mp.playEraseSound();} addScor();//增加分?jǐn)?shù) if(scor%10==0)//設(shè)置為10分增加一個(gè)等級(jí) upspeed=true;//將速度增加標(biāo)志位至為true if(upspeed==true) upLevel(); } } } /** * 得分的計(jì)算方法 */ private void addScor() { scor=scor+10; jt9.setText("得分:"+scor); } } /** * 判斷最頂層是否有被占用,游戲是否結(jié)束 */ private boolean isGameOver() { for (int i = 0; i < 12; i++) { Box box = gc.getBox(0, i); if (box.isColorBox()) return true; }return false; } private void reset() { scor=0; rank=0; jt10.setText("等級(jí):"+rank); jt9.setText("得分:"+scor); upspeed=false; playing=true; runstop=false; // block.pausing=false; // isTime=true; // block=new Block(); // block.isAlive=false; gc.setGameOver(false); gc.repaint(); gc.reset(); } /* private class MenuKeyListener extends KeyAdapter{ public void keyPressed(KeyEvent e) { int i = e.getKeyCode(); switch (i) { case KeyEvent.VK_C: System.out.println("111");; break; case KeyEvent.VK_DOWN: block.moveDown(); break; case KeyEvent.VK_LEFT: block.moveLeft(); break; } } }*/ /** * *按鍵監(jiān)聽,上下左右。 */ private class MyListener extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { // TODO Auto-generated method stub int i = e.getKeyCode(); switch (i) { case KeyEvent.VK_UP: block.moveUp(); break; case KeyEvent.VK_DOWN: block.moveDown(); break; case KeyEvent.VK_LEFT: block.moveLeft(); break; case KeyEvent.VK_RIGHT: block.moveRight(); break; case KeyEvent.VK_SPACE: block.quickDown(); break; case KeyEvent.VK_P: block.pause(); break; case KeyEvent.VK_C: block.jixu(); break; } } } /** * 菜單添加方法 */ private void addMenu() { // TODO Auto-generated method stub JMenuBar jb1=new JMenuBar(); // m1.addKeyListener(new MenuKeyListener()); //監(jiān)聽Dialog對(duì)話框,如果有等級(jí)改變則改變選擇 m1.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { // TODO Auto-generated method stub int i=Block.get_addl(); if(i==7) jr1.setSelected(true); else if(i==10) jr2.setSelected(true); else jr3.setSelected(true); } }); // JMenuItem ji1=new JMenuItem("開局(O)"); jr1.addActionListener(new MenuActionListener()); jr2.addActionListener(new MenuActionListener()); jr3.addActionListener(new MenuActionListener()); ButtonGroup bg=new ButtonGroup(); bg.add(jr1); bg.add(jr2); bg.add(jr3); JMenuItem ji2=new JMenuItem("自定義"); ji2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub zi=new Zidingyi(MyFrame.this,"自定義",false,block,gc); zi.setVisible(true); if(playing==true) block.pause(); } }); JMenuItem ji3=new JMenuItem("退出"); ji3.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub System.exit(1);//退出程序 } }); JMenuItem ji4=new JMenuItem("關(guān)于"); ji4.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub JDialog dl=new Version(MyFrame.this,"版本信息",false); } }); //調(diào)用顏色對(duì)話框設(shè)置方塊顏色 JMenuItem ji_color=new JMenuItem("方塊顏色"); ji_color.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub Color newFrontColor = JColorChooser.showDialog( MyFrame.this,"設(shè)置方塊顏色", gc.getBlockColor()); if (newFrontColor != null) gc.setBlockColor(newFrontColor); } } ); MyFrame.this.setJMenuBar(jb1); jb1.add(m1); jb1.add(m2); m1.add(ji1); m1.add(jr1); m1.add(jr2); m1.add(jr3); m1.add(ji2); m1.add(ji_color); m1.add(ji3); m2.add(ji4); } /** * 右界面的添加 */ private void addRight() { // TODO Auto-generated method stub // JTextField jt1=new JTextField("下一塊"); JLabel jt1=new JLabel("下一塊"); jt1.setFont(new Font("華文行楷", Font.BOLD, 18)); jt1.setOpaque(false); // jt1.setEditable(false); jp_pre.setLayout(null); jt1.setBounds(5, 0, 80, 20); jp_pre.add(jt1); pv.setBounds(10, 20, 102, 102); jp_pre.add(pv);//添加預(yù)覽窗口 jp_pre.setBounds(308, 5, 120, 125);//設(shè)置坐標(biāo) jp_pre.setOpaque(false);//設(shè)置背景為透明 MyFrame.this.add(jp_pre); // JTextField jt2=new JTextField("功能鍵盤" ); JLabel jt2=new JLabel("功能鍵盤"); jt2.setFont(new Font("華文行楷", Font.BOLD, 23)); // jt2.setEditable(false); jt2.setOpaque(false); // JTextField jt3=new JTextField("快速向下:↓" ); JLabel jt3=new JLabel("快速向下:↓"); jt3.setFont(new Font("華文行楷", Font.BOLD, 15)); // jt3.setEditable(false); jt3.setOpaque(false); // JTextField jt4=new JTextField("旋轉(zhuǎn):↑" ); JLabel jt4=new JLabel("旋轉(zhuǎn):↑"); jt4.setFont(new Font("華文行楷", Font.BOLD, 15)); // jt4.setEditable(false); jt4.setOpaque(false); // JTextField jt5=new JTextField("向左:←" ); JLabel jt5=new JLabel("向左:←"); jt5.setFont(new Font("華文行楷", Font.BOLD, 15)); // jt5.setEditable(false); jt5.setOpaque(false); // JTextField jt6=new JTextField("向右:→" ); JLabel jt6=new JLabel("向右:→"); jt6.setFont(new Font("華文行楷", Font.BOLD, 15)); // jt6.setEditable(false); jt6.setOpaque(false); JLabel jt11=new JLabel("一鍵下落:空格"); jt11.setFont(new Font("華文行楷", Font.BOLD, 15)); // jt6.setEditable(false); jt6.setOpaque(false); // JTextField jt7=new JTextField("暫停:P" ); JLabel jt7=new JLabel("暫停:P"); jt7.setFont(new Font("華文行楷", Font.BOLD, 15)); // jt7.setEditable(false); jt7.setOpaque(false); // JTextField jt8=new JTextField("繼續(xù):C" ); JLabel jt8=new JLabel("繼續(xù):C"); jt8.setFont(new Font("華文行楷", Font.BOLD, 15)); // jt8.setEditable(false); jt8.setOpaque(false); jp_ctrl.setLayout(new GridLayout(8, 1, 0, 0)); // jp_ctrl.setBorder(BorderFactory.createBevelBorder(EtchedBorder.LOWERED)); jp_ctrl.add(jt2); jp_ctrl.add(jt3); jp_ctrl.add(jt4); jp_ctrl.add(jt5); jp_ctrl.add(jt6); jp_ctrl.add(jt11); jp_ctrl.add(jt7); jp_ctrl.add(jt8); jp_ctrl.setOpaque(false); jp_ctrl.setBounds(310, 145, 120, 200); MyFrame.this.add(jp_ctrl); // jt9.setEditable(false); jt9.setOpaque(false); jt9.setForeground(Color.BLACK); // jt10.setEditable(false); jt10.setOpaque(false); jt10.setForeground(Color.BLACK); jp_scor.setLayout(new GridLayout(2, 1, 0, 20)); jp_scor.add(jt9); jt9.setFont(new Font("華文行楷", Font.BOLD, 26)); jt10.setFont(new Font("華文行楷", Font.BOLD, 26)); jp_scor.add(jt10); jt9.setBackground(Color.LIGHT_GRAY); jt10.setBackground(Color.LIGHT_GRAY); jp_scor.setOpaque(false); jp_scor.setBounds(320, 360, 100, 140); MyFrame.this.add(jp_scor); } /** * 菜單等級(jí)的監(jiān)聽 * */ private class MenuActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { //獲取JMenuItem對(duì)象 JMenuItem j=((JMenuItem)e.getSource()); if(j==jr1){ // newLevel=Constant.LEVEL_1; Block.set_addl(7); } if(j==jr2){ Block.set_addl(10); } if(j==jr3){ // high=true; Block.set_addl(13); } } } public static void main(String[] args) { new MyFrame("俄羅斯方塊"); } }
GameCanvas
public class GameCanvas extends JPanel { private Color backColor = Color.GRAY, frontColor = Color.orange; private int rows, cols, score = 0, scoreForLevelUpdate = 0; private Box[][] boxes; private int boxWidth=25, boxHeight=25; private boolean gameOver=false; public boolean pau=false; /** * 畫布類的構(gòu)造函數(shù) * @param rows int, 畫布的行數(shù) * @param cols int, 畫布的列數(shù) * 行數(shù)和列數(shù)決定著畫布擁有方格的數(shù)目 */ public GameCanvas(int rows, int cols) { this.rows = rows; this.cols = cols; this.setOpaque(false); boxes = new Box[rows][cols]; for (int i = 0; i < boxes.length; i++) { for (int j = 0; j < boxes[i].length; j++) { boxes[i][j] = new Box(false); } } setBounds(0, 0, 300, 500);//設(shè)置相對(duì)位置坐標(biāo) setBorder(new EtchedBorder( EtchedBorder.RAISED, Color.white, new Color(148, 145, 140))); } /** * 畫布類的構(gòu)造函數(shù) * @param rows 與public GameCanvas(int rows, int cols)同 * @param cols 與public GameCanvas(int rows, int cols)同 * @param backColor Color, 背景色 * @param frontColor Color, 前景色 */ public GameCanvas(int rows, int cols, Color backColor, Color frontColor) { this(rows, cols); this.backColor = backColor; this.frontColor = frontColor; } /** * 設(shè)置游戲背景色彩 * @param backColor Color, 背景色彩 */ public void setBackgroundColor(Color backColor) { this.backColor = backColor; } /** * 取得游戲背景色彩 * @return Color, 背景色彩 */ public Color getBackgroundColor() { return backColor; } /** * 設(shè)置游戲方塊色彩 * @param frontColor Color, 方塊色彩 */ public void setBlockColor(Color frontColor) { this.frontColor = frontColor; } /** * 取得游戲方塊色彩 * @return Color, 方塊色彩 */ public Color getBlockColor() { return frontColor; } /** * 取得畫布中方格的行數(shù) * @return int, 方格的行數(shù) */ public int getRows() { return rows; } /** * 取得畫布中方格的列數(shù) * @return int, 方格的列數(shù) */ public int getCols() { return cols; } /** * 取得游戲成績(jī) * @return int, 分?jǐn)?shù) */ public int getScore() { return score; } /** * 取得自上一次升級(jí)后的積分 * @return int, 上一次升級(jí)后的積分 */ public int getScoreForLevelUpdate() { return scoreForLevelUpdate; } /** * 得到某一行某一列的方格引用。 * @param row int, 要引用的方格所在的行 * @param col int, 要引用的方格所在的列 * @return ErsBox, 在row行col列的方格的引用 */ public Box getBox(int row, int col) { if (row < 0 || row > boxes.length - 1 || col < 0 || col > boxes[0].length - 1) return null; return boxes[row][col]; } /** * 消行 */ public void delete(int row) { //創(chuàng)建新Box存儲(chǔ)新狀態(tài),不能直接賦值,賦值只是指向同一個(gè)對(duì)象 for (int i = row; i > 0; i--) { for (int j = 0; j < 12; j++) boxes[i][j] = new Box(boxes[i - 1][j].isColorBox()); } repaint(); } /** * 自動(dòng)上漲 */ public void addRow() { for (int i = 0; i <19 ; i++) { for (int j = 0; j < 12; j++) { boxes[i][j] = new Box(boxes[i + 1][j].isColorBox()); } } for (int i = 0; i < 12; i++) { int a = (int) (Math.random() * 2); if (a == 1) boxes[19][i] = new Box(true); else boxes[19][i] = new Box(false); } repaint(); } /** * 畫組件。 * @param g 圖形設(shè)備環(huán)境 */ public void paint(Graphics g) { super.paint(g); if (gameOver) { paintGame(g); g.setColor(Color.RED); g.setFont(new Font("黑體", Font.BOLD, 80)); // g.drawString("GAME\nOVER",10, 220); g.drawString("GAME", 50, 220); g.drawString("OVER", 50, 310); } else if(pau==true){ paintGame(g); g.setColor(Color.BLUE); g.setFont(new Font("華文行楷", Font.BOLD, 40)); // g.drawString("GAME\nOVER",10, 220); g.drawString("暫停", 100, 200); g.drawString("按C繼續(xù)!", 60, 310); }else paintGame(g); } public void paintGame(Graphics g) { g.setColor(Color.BLUE); g.draw3DRect(0, 0, 298, 498, true); g.setColor(frontColor); // int a; // int key=0x8000; // int y1=0; for (int i = 0; i < boxes.length; i++) { for (int j = 0; j < boxes[i].length; j++) { if (boxes[i][j].isColorBox() == true) { g.setColor(frontColor);// 獲取方格顏色 g.fill3DRect(j * boxWidth, i * boxHeight, boxWidth, boxHeight, true);// j,i是相反過來的} } }} } /** * 設(shè)置游戲結(jié)束 */ public boolean setGameOver(boolean go){ gameOver=go; return gameOver; } /** * 重置畫布 */ public void reset() { for (int i = 0; i < boxes.length; i++) { for (int j = 0; j < boxes[i].length; j++) boxes[i][j].setColor(false); } repaint(); } }
總結(jié)
通過此次的《俄羅斯方塊升級(jí)版》游戲?qū)崿F(xiàn),讓我對(duì)swing的相關(guān)知識(shí)有了進(jìn)一步的了解,對(duì)java這門語言也有了比以前更深刻的認(rèn)識(shí)。
java的一些基本語法,比如數(shù)據(jù)類型、運(yùn)算符、程序流程控制和數(shù)組等,理解更加透徹。java最核心的核心就是面向?qū)ο笏枷耄瑢?duì)于這一個(gè)概念,終于悟到了一些。
以上就是Java實(shí)現(xiàn)經(jīng)典游戲俄羅斯方塊(升級(jí)版)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Java俄羅斯方塊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java中的線程同步與ThreadLocal無鎖化線程封閉實(shí)現(xiàn)
這篇文章主要介紹了Java中的線程同步與ThreadLocal無鎖化線程封閉實(shí)現(xiàn),Synchronized關(guān)鍵字與ThreadLocal變量的使用是Java中線程控制的基礎(chǔ),需要的朋友可以參考下2016-03-03Java中==符號(hào)與equals()的使用詳解(測(cè)試兩個(gè)變量是否相等)
下面小編就為大家?guī)硪黄狫ava中==符號(hào)與equals()的使用詳解(測(cè)試兩個(gè)變量是否相等)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07如何利用Java使用AOP實(shí)現(xiàn)數(shù)據(jù)字典轉(zhuǎn)換
這篇文章主要介紹了如何利用Java使用AOP實(shí)現(xiàn)數(shù)據(jù)字典轉(zhuǎn)換,AOP也是我們常說的面向切面編程,AOP在我們開發(fā)過程中應(yīng)用也比較多,在這里我們就基于AOP來實(shí)現(xiàn)一個(gè)數(shù)據(jù)字典轉(zhuǎn)換的案例2022-06-06詳解使用Maven構(gòu)建多模塊項(xiàng)目(圖文)
這篇文章主要介紹了詳解使用Maven構(gòu)建多模塊項(xiàng)目(圖文),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-09-09spring5 SAXParseException:cvc-elt.1: 找不到元素“beans 的聲明詳解
這篇文章主要給大家介紹了關(guān)于spring5 SAXParseException:cvc-elt.1: 找不到元素“beans 聲明的相關(guān)資料,需要的朋友可以參考下2020-08-08Java switch 語句如何使用 String 參數(shù)
這篇文章主要介紹了Java switch 語句如何使用 String 參數(shù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06Java對(duì)數(shù)組實(shí)現(xiàn)選擇排序算法的實(shí)例詳解
這篇文章主要介紹了Java對(duì)數(shù)組實(shí)現(xiàn)選擇排序算法的實(shí)例,選擇排序的比較次數(shù)為 O(N^2)而交換數(shù)為O(N),需要的朋友可以參考下2016-04-04使用JMX監(jiān)控Zookeeper狀態(tài)Java API
今天小編就為大家分享一篇關(guān)于使用JMX監(jiān)控Zookeeper狀態(tài)Java API,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03springboot打印接口調(diào)用日志的實(shí)例
這篇文章主要介紹了springboot打印接口調(diào)用日志的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09