java代碼實(shí)現(xiàn)俄羅斯方塊
本文實(shí)例為大家分享了java實(shí)現(xiàn)俄羅斯方塊的具體代碼,供大家參考,具體內(nèi)容如下
俄羅斯方塊設(shè)計(jì)思想
俄羅斯方塊都從小玩到大吧,什么規(guī)則大家都知道了吧,以前感覺(jué)那玩意賊好玩,但是就是老贏不了,現(xiàn)在學(xué)會(huì)了自己寫一個(gè)天天練!
鍵盤操作:
左鍵:左移; 右鍵:右移;
上鍵:變換造型 下鍵:加速下掉(沒(méi)毛病吧,沒(méi)有繼續(xù)整)
任意一行的方塊滿格,這一行就消除,消除一行方塊得10分,目前小主我還沒(méi)有設(shè)置關(guān)卡,各位喜歡的寶寶們可以自己設(shè)置關(guān)卡哦;
那么那些方塊的造型到底從哪里來(lái)的呢,那就是我們自己設(shè)計(jì)的,常見(jiàn)的幾種造型就是:I型,T型,L型,田字格型等等吧,自己個(gè)加唄!
那么到底咋整的咧?其實(shí)啊就是一個(gè)4*4的數(shù)組,當(dāng)然了你開(kāi)心設(shè)計(jì)n*n也可以,你牛皮你說(shuō)了算!
那么下面舉了一個(gè)例子,用來(lái)告訴你們?yōu)樯赌銈兛匆?jiàn)的造型可以變換的原因就是這樣提前設(shè)計(jì)好,0為空,1為填充格,這樣你就可以在你的游戲里面凹造型了!
算了:直接放圖先看代碼運(yùn)行結(jié)果吧:
喜歡嗎?喜歡就直接做吧,可能代碼寫的不夠好,請(qǐng)各位大神多多包涵,我回頭也會(huì)多總結(jié),會(huì)不斷更新代碼的;
GamePanel類:游戲界面類,整個(gè)方塊掉落和顯示,游戲的邏輯斯洛都在這個(gè)類里面實(shí)現(xiàn);
package tetris; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Random; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.Timer; public class GamePanel extends JPanel implements KeyListener{ private int mapRow = 21; private int mapCol = 12; private int mapGame[][] = new int[mapRow][mapCol];//開(kāi)辟一個(gè)二維數(shù)組空間,用來(lái)存放我們的地圖信息 private Timer timer; private int score = 0;//記錄成績(jī) Random random = new Random(); private int curShapeType = -1; private int curShapeState = -1;//設(shè)置當(dāng)前的形狀類型和當(dāng)前的形狀狀態(tài) private int nextShapeType = -1; private int nextShapeState = -1;//設(shè)置下一次出現(xiàn)的方塊組的類型和狀態(tài) private int posx = 0; private int posy = 0; private final int shapes[][][] = new int[][][]{ //T字形按逆時(shí)針的順序存儲(chǔ) { {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} }, //I字形按逆時(shí)針的順序存儲(chǔ) { {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} }, //倒Z形按逆時(shí)針的順序存儲(chǔ) { {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形按逆時(shí)針的順序存儲(chǔ) { {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字形按逆時(shí)針的順序存儲(chǔ) { {0,1,0,0, 0,1,0,0, 1,1,0,0, 0,0,0,0}, {1,1,1,0, 0,0,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,0,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0} }, //L字形按逆時(shí)針的順序存儲(chǔ) { {1,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0}, {0,0,1,0, 1,1,1,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}, {1,1,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0} }, //田字形按逆時(shí)針的順序存儲(chǔ) { {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} } }; private int rowRect = 4; private int colRect = 4;//這里我們把存儲(chǔ)的圖像看成是一個(gè)4*4的二維數(shù)組,雖然在上面我們采用一維數(shù)組來(lái)存儲(chǔ),但實(shí)際還是要看成二維數(shù)組來(lái)實(shí)現(xiàn) private int RectWidth = 10; public GamePanel()//構(gòu)造函數(shù)----創(chuàng)建好地圖 { CreateRect(); initMap();//初始化這個(gè)地圖 SetWall();//設(shè)置墻 // CreateRect(); timer = new Timer(500,new TimerListener()); timer.start(); } class TimerListener implements ActionListener{ public void actionPerformed(ActionEvent e) { MoveDown(); } } public void SetWall()//第0列和第11列都是墻,第20行也是墻 { for(int i = 0; i < mapRow; i++)//先畫列 { mapGame[i][0] = 2; mapGame[i][11] = 2; } for(int j = 1; j < mapCol-1; j++)//畫最后一行 { mapGame[20][j] = 2; } } public void initMap()//初始化這個(gè)地圖,墻的ID是2,空格的ID是0,方塊的ID是1 { for(int i = 0; i < mapRow; i++) { for(int j = 0; j < mapCol; j++) { mapGame[i][j] = 0; } } } public void CreateRect()//創(chuàng)建方塊---如果當(dāng)前的方塊類型和狀態(tài)都存在就設(shè)置下一次的,如果不存在就設(shè)置當(dāng)前的并且設(shè)置下一次的狀態(tài)和類型 { if(curShapeType == -1 && curShapeState == -1)//當(dāng)前的方塊狀態(tài)都為1,表示游戲才開(kāi)始 { curShapeType = random.nextInt(shapes.length); curShapeState = random.nextInt(shapes[0].length); } else { curShapeType = nextShapeType; curShapeState = nextShapeState; } nextShapeType = random.nextInt(shapes.length); nextShapeState = random.nextInt(shapes[0].length); posx = 0; posy = 1;//墻的左上角創(chuàng)建方塊 if(GameOver(posx,posy,curShapeType,curShapeState)) { JOptionPane.showConfirmDialog(null, "游戲結(jié)束!", "提示", JOptionPane.OK_OPTION); System.exit(0); } } public boolean GameOver(int x, int y, int ShapeType, int ShapeState)//判斷游戲是否結(jié)束 { if(IsOrNoMove(x,y,ShapeType,ShapeState)) { return false; } return true; } public boolean IsOrNoMove(int x, int y, int ShapeType, int ShapeState)//判斷當(dāng)前的這個(gè)圖形是否可以移動(dòng),這里重點(diǎn)強(qiáng)調(diào)x,y的坐標(biāo)是指4*4的二維數(shù)組(描述圖形的那個(gè)數(shù)組)的左上角目標(biāo) { for(int i = 0; i < rowRect ; i++) { for(int j = 0; j < colRect; j++) { if(shapes[ShapeType][ShapeState][i*colRect+j] == 1 && mapGame[x+i][y+j] == 1 || shapes[ShapeType][ShapeState][i*colRect+j] == 1 && mapGame[x+i][y+j] == 2) { return false; } } } return true; } public void Turn()//旋轉(zhuǎn) { int temp = curShapeState; curShapeState = (curShapeState+1) % shapes[0].length; if(IsOrNoMove(posx,posy,curShapeType,curShapeState)) { } else { curShapeState = temp; } repaint(); } public void MoveDown()//向下移動(dòng) { if(IsOrNoMove(posx+1,posy,curShapeType,curShapeState)) { posx++; } else { AddToMap();//將此行固定在地圖中 CheckLine(); CreateRect();//重新創(chuàng)建一個(gè)新的方塊 } repaint(); } public void MoveLeft()//向左移動(dòng) { if(IsOrNoMove(posx,posy-1,curShapeType,curShapeState)) { posy--; } repaint(); } public void MoveRight()//向右移動(dòng) { if(IsOrNoMove(posx,posy+1,curShapeType,curShapeState)) { posy++; } repaint(); } public void AddToMap()//固定掉下來(lái)的這一圖像到地圖中 { for(int i = 0; i < rowRect; i++) { for(int j = 0; j < colRect; j++) { if(shapes[curShapeType][curShapeState][i*colRect+j] == 1) { mapGame[posx+i][posy+j] = shapes[curShapeType][curShapeState][i*colRect+j]; } } } } public void CheckLine()//檢查一下這些行中是否有滿行的 { int count = 0; for(int i = mapRow-2; i >= 0; i--) { count = 0; for(int j = 1; j < mapCol-1; j++) { if(mapGame[i][j] == 1) { count++; } else break; } if(count >= mapCol-2) { for(int k = i; k > 0; k--) { for(int p = 1; p < mapCol-1; p++) { mapGame[k][p] = mapGame[k-1][p]; } } score += 10; i++; } } } public void paint(Graphics g)//重新繪制窗口 { super.paint(g); for(int i = 0; i < rowRect; i++)//繪制正在下落的方塊 { for(int j = 0; j < colRect; j++) { if(shapes[curShapeType][curShapeState][i*colRect+j] == 1) { g.fillRect((posy+j+1)*RectWidth, (posx+i+1)*RectWidth, RectWidth, RectWidth); } } } for(int i = 0; i < mapRow; i++)//繪制地圖上面已經(jīng)固定好的方塊信息 { for(int j = 0; j < mapCol; j++) { if(mapGame[i][j] == 2)//畫墻 { g.drawRect((j+1)*RectWidth, (i+1)*RectWidth, RectWidth, RectWidth); } if(mapGame[i][j] == 1)//畫小方格 { g.fillRect((j+1)*RectWidth, (i+1)*RectWidth, RectWidth, RectWidth); } } } g.drawString("score = "+ score, 225, 15); g.drawString("下一個(gè)方塊:", 225, 50); for(int i = 0; i < rowRect; i++) { for(int j = 0; j < colRect; j++) { if(shapes[nextShapeType][nextShapeState][i*colRect+j] == 1) { g.fillRect(225+(j*RectWidth), 100+(i*RectWidth), RectWidth, RectWidth); } } } } public void NewGame()//游戲重新開(kāi)始 { score = 0; initMap(); SetWall(); CreateRect(); repaint(); } public void StopGame()//游戲暫停 { timer.stop(); } public void ContinueGame() { timer.start(); } @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { switch(e.getKeyCode()) { case KeyEvent.VK_UP://上----旋轉(zhuǎn) Turn(); break; case KeyEvent.VK_DOWN://下----向下移動(dòng) MoveDown(); break; case KeyEvent.VK_LEFT://左----向左移動(dòng) MoveLeft(); break; case KeyEvent.VK_RIGHT://右----向右移動(dòng) MoveRight(); break; } } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } }
GameFrame類:整個(gè)游戲的進(jìn)入口,好吧,說(shuō)白了就是有main()函數(shù)的類,這個(gè)類里面實(shí)現(xiàn)游戲界面的一些設(shè)計(jì),你可以理解為一個(gè)小小小小的UI;
package tetris; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; public class GameFrame extends JFrame implements ActionListener{ private int widthFrame = 500; private int heightFrame = 600; private JMenu menuone = new JMenu("游戲");//創(chuàng)建一個(gè)菜單 private JMenuItem newGame = menuone.add("重新開(kāi)始");//創(chuàng)建一個(gè)內(nèi)置菜單選項(xiàng) private JMenuItem exitGame = menuone.add("游戲退出"); private JMenuItem stopGame = menuone.add("游戲暫停"); private JMenuItem goOnGame = menuone.add("游戲繼續(xù)"); private JMenu menutwo = new JMenu("幫助");//創(chuàng)建第二個(gè)菜單 private JMenuItem aboutGame = menutwo.add("關(guān)于游戲"); GamePanel gamepanel = new GamePanel(); public GameFrame()//構(gòu)造函數(shù) { addKeyListener(gamepanel); newGame.addActionListener(this); exitGame.addActionListener(this); stopGame.addActionListener(this); goOnGame.addActionListener(this); aboutGame.addActionListener(this); this.add(gamepanel); JMenuBar menu = new JMenuBar(); menu.add(menuone); menu.add(menutwo); this.setJMenuBar(menu); this.setTitle("俄羅斯方塊"); this.setBounds(50, 10, widthFrame, heightFrame); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void actionPerformed(ActionEvent e) { if(e.getSource() == newGame)//游戲重新開(kāi)始 { gamepanel.NewGame(); } if(e.getSource() == exitGame)//游戲退出 { System.exit(0); } if(e.getSource() == stopGame)//游戲暫停 { gamepanel.StopGame(); } if(e.getSource() == goOnGame)//游戲繼續(xù) { gamepanel.ContinueGame(); } if(e.getSource() == aboutGame)//關(guān)于游戲信息 { JOptionPane.showMessageDialog(null, "左右鍵移動(dòng),向上建旋轉(zhuǎn)", "提示", JOptionPane.OK_OPTION); } } public static void main(String[] args) { new GameFrame(); } }
更多關(guān)于俄羅斯方塊的文章,請(qǐng)點(diǎn)擊查看專題:《俄羅斯方塊》
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis 返回Integer,Double,String等類型的數(shù)據(jù)操作
這篇文章主要介紹了mybatis 返回Integer,Double,String等類型的數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11Springboot項(xiàng)目啟動(dòng)成功后可通過(guò)五種方式繼續(xù)執(zhí)行
本文主要介紹了Springboot項(xiàng)目啟動(dòng)成功后可通過(guò)五種方式繼續(xù)執(zhí)行,主要包括CommandLineRunner接口,ApplicationRunner接口,ApplicationListener接口,@PostConstruct注解,InitalizingBean接口,感興趣的可以了解一下2023-12-12解決IDEA springboot"spring-boot-maven-plugin"報(bào)紅問(wèn)題
這篇文章主要介紹了解決IDEA springboot"spring-boot-maven-plugin"報(bào)紅問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04解決feignclient調(diào)用服務(wù),傳遞的中文數(shù)據(jù)成???問(wèn)題
這篇文章主要介紹了解決feignclient調(diào)用服務(wù),傳遞的中文數(shù)據(jù)成???問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Spring在多線程下@Resource注入為null的問(wèn)題
這篇文章主要介紹了Spring在多線程下@Resource注入為null的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Spring Boot 通過(guò) Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解
這篇文章主要介紹了Spring Boot 通過(guò) Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12SpringBoot+Dubbo+Zookeeper實(shí)現(xiàn)簡(jiǎn)單分布式開(kāi)發(fā)的應(yīng)用詳解
這篇文章主要介紹了SpringBoot+Dubbo+Zookeeper實(shí)現(xiàn)簡(jiǎn)單分布式開(kāi)發(fā)的應(yīng)用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Java常用正則表達(dá)式驗(yàn)證工具類RegexUtils.java
相信大家對(duì)正則表達(dá)式一定都有所了解和研究,這篇文章主要為大家分享了Java 表單注冊(cè)常用正則表達(dá)式驗(yàn)證工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Springboot+Vue+shiro實(shí)現(xiàn)前后端分離、權(quán)限控制的示例代碼
這篇文章主要介紹了Springboot+Vue+shiro實(shí)現(xiàn)前后端分離、權(quán)限控制的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07