老程序員教你一天時(shí)間完成Java迷宮小游戲
效果圖
實(shí)現(xiàn)思路
1.創(chuàng)建運(yùn)行窗口。
2.創(chuàng)建菜單。
3.繪制迷宮的每個(gè)單元。
4.通過算法計(jì)算迷宮路徑,并打通路徑,形成迷宮。
5.繪制起點(diǎn)終點(diǎn)。
6.添加鍵盤事件控制起點(diǎn)方塊移動(dòng)。
7.收尾。
迷宮算法(網(wǎng)上參考的)
1.將起點(diǎn)作為當(dāng)前迷宮單元并標(biāo)記為已訪問
2.當(dāng)還存在未標(biāo)記的迷宮單元,進(jìn)行循環(huán)
1).如果當(dāng)前迷宮單元有未被訪問過的的相鄰的迷宮單元
(1).隨機(jī)選擇一個(gè)未訪問的相鄰迷宮單元
(2).將當(dāng)前迷宮單元入棧
(3).移除當(dāng)前迷宮單元與相鄰迷宮單元的墻
(4).標(biāo)記相鄰迷宮單元并用它作為當(dāng)前迷宮單元
2).如果當(dāng)前迷宮單元不存在未訪問的相鄰迷宮單元,并且棧不空
(1).棧頂?shù)拿詫m單元出棧
(2).令其成為當(dāng)前迷宮單元
**這個(gè)算法叫做“深度優(yōu)先”,簡單來說,就是從起點(diǎn)開始走,尋找它的上下左右4個(gè)鄰居,然后隨機(jī)一個(gè)走,到走不通的時(shí)候就返回上一步繼續(xù)走,直到全部單元都走完。 **
相關(guān)圖示說明
每個(gè)單元的墻,分為上墻、右墻、下墻、左墻,把這些墻用長度為4的數(shù)組表示,元素的值為true則表示墻存在,否則墻不存在,代碼里數(shù)組的下標(biāo)方式來確定墻是否存在。
單元是根據(jù)行列來創(chuàng)建的,會用到雙循環(huán),類似表格,比如第二行用 i 來表示的話就是 1,第3列用 j 來表示就是2,那第二行第3列的元素組合起來就是(1,2)
那同理它的上鄰居就是(0,2),右鄰居(1,3),下鄰居(2,2),左鄰居(1,1),也就是上下鄰居是 i 減加1,左右鄰居是 j 減加1。
正方形4個(gè)點(diǎn)的坐標(biāo)分別為(x1,y1)(x2,y2)(x3,y3)(x4,y4),計(jì)算坐標(biāo)的公式為(其中start為相對偏移量,為了讓迷宮兩邊有些空隙):
//i代表行 j代表列 h為單元高度 //左上角坐標(biāo) this.x1=start+j*h; this.y1=start+i*h; //右上角坐標(biāo) this.x2=start+(j+1)*h; this.y2=start+i*h; //右下角坐標(biāo) this.x3=start+(j+1)*h; this.y3=start+(i+1)*h; //左下角坐標(biāo) this.x4=start+j*h; this.y4=start+(i+1)*h;
計(jì)算坐標(biāo),假如每個(gè)正方形的寬高都是40,那么(1,2)這個(gè)單元的坐標(biāo)如下圖:
5. 墻的處理,之前說到墻是以一個(gè)4個(gè)元素的數(shù)組來表示的,比如數(shù)組為:[true,true,true,true],則圖為:
如果數(shù)組為[false,true,true,true],則圖為:
6. 如果要聯(lián)通右邊的鄰居要怎么做呢?當(dāng)前單元去除右墻,右邊單元去除左墻,這樣就聯(lián)通了。
去除后就這樣,以此類推
代碼實(shí)現(xiàn)
創(chuàng)建窗口
首先創(chuàng)建一個(gè)游戲窗體類GameFrame,繼承至JFrame,用來顯示在屏幕上(window的對象),每個(gè)游戲都有一個(gè)窗口,設(shè)置好窗口標(biāo)題、尺寸、布局等就可以。
import javax.swing.JFrame; /** *窗體類 */ public class GameFrame extends JFrame { //構(gòu)造方法 public GameFrame(){ setTitle("迷宮");//設(shè)置標(biāo)題 setSize(420, 470);//設(shè)置窗體大小 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//關(guān)閉后進(jìn)程退出 setLocationRelativeTo(null);//居中 setResizable(false);//不允許變大 //setVisible(true);//設(shè)置顯示窗體 } }
創(chuàng)建面板容器GamePanel繼承至JPanel
import javax.swing.JMenuBar; import javax.swing.JPanel; /* * 畫布類 */ public class GamePanel extends JPanel{ private JMenuBar jmb = null; private GameFrame mainFrame = null; private GamePanel panel = null; private String gameFlag="start";//游戲狀態(tài) //構(gòu)造方法 public GamePanel(GameFrame mainFrame){ this.setLayout(null); this.setOpaque(false); this.mainFrame=mainFrame; this.panel =this; } }
再創(chuàng)建一個(gè)Main類,來啟動(dòng)這個(gè)窗口。
//Main類 public class Main { public static void main(String[] args) { GameFrame frame = new GameFrame(); GamePanel panel = new GamePanel(frame); frame.add(panel); frame.setVisible(true); } }
右鍵執(zhí)行這個(gè)Main類,窗口建出來了
創(chuàng)建菜單及菜單選項(xiàng)
創(chuàng)建菜單
private Font createFont(){ return new Font("思源宋體",Font.BOLD,18); } //創(chuàng)建菜單 private void createMenu() { //創(chuàng)建JMenuBar jmb = new JMenuBar(); //取得字體 Font tFont = createFont(); //創(chuàng)建游戲選項(xiàng) JMenu jMenu1 = new JMenu("游戲"); jMenu1.setFont(tFont); //創(chuàng)建幫助選項(xiàng) JMenu jMenu2 = new JMenu("幫助"); jMenu2.setFont(tFont); JMenuItem jmi1 = new JMenuItem("新游戲"); jmi1.setFont(tFont); JMenuItem jmi2 = new JMenuItem("退出"); jmi2.setFont(tFont); //jmi1 jmi2添加到菜單項(xiàng)“游戲”中 jMenu1.add(jmi1); jMenu1.add(jmi2); JMenuItem jmi3 = new JMenuItem("操作幫助"); jmi3.setFont(tFont); JMenuItem jmi4 = new JMenuItem("勝利條件"); jmi4.setFont(tFont); //jmi13 jmi4添加到菜單項(xiàng)“游戲”中 jMenu2.add(jmi3); jMenu2.add(jmi4); jmb.add(jMenu1); jmb.add(jMenu2); mainFrame.setJMenuBar(jmb); //添加監(jiān)聽 jmi1.addActionListener(this); jmi2.addActionListener(this); jmi3.addActionListener(this); jmi4.addActionListener(this); //設(shè)置指令 jmi1.setActionCommand("restart"); jmi2.setActionCommand("exit"); jmi3.setActionCommand("help"); jmi4.setActionCommand("win"); }
實(shí)現(xiàn)ActionListener并重寫方法actionPerformed
此時(shí)GamePanel是報(bào)錯(cuò)的,需重寫actionPerformed方法。
actionPerformed方法的實(shí)現(xiàn)
@Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); System.out.println(command); UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("思源宋體", Font.ITALIC, 18))); UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("思源宋體", Font.ITALIC, 18))); if ("exit".equals(command)) { Object[] options = { "確定", "取消" }; int response = JOptionPane.showOptionDialog(this, "您確認(rèn)要退出嗎", "", JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if (response == 0) { System.exit(0); } }else if("restart".equals(command)){ restart(); }else if("help".equals(command)){ JOptionPane.showMessageDialog(null, "通過鍵盤的上下左右來移動(dòng)", "提示!", JOptionPane.INFORMATION_MESSAGE); }else if("win".equals(command)){ JOptionPane.showMessageDialog(null, "移動(dòng)到終點(diǎn)獲得勝利", "提示!", JOptionPane.INFORMATION_MESSAGE); } }
此時(shí)的GamePanel代碼如下:
package main; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.plaf.FontUIResource; /* * 畫布類 */ public class GamePanel extends JPanel implements ActionListener{ private JMenuBar jmb = null; private GameFrame mainFrame = null; private GamePanel panel = null; private String gameFlag="start";//游戲狀態(tài) //構(gòu)造方法 public GamePanel(GameFrame mainFrame){ this.setLayout(null); this.setOpaque(false); this.mainFrame=mainFrame; this.panel =this; //創(chuàng)建菜單 createMenu(); } private Font createFont(){ return new Font("思源宋體",Font.BOLD,18); } //創(chuàng)建菜單 private void createMenu() { //創(chuàng)建JMenuBar jmb = new JMenuBar(); //取得字體 Font tFont = createFont(); //創(chuàng)建游戲選項(xiàng) JMenu jMenu1 = new JMenu("游戲"); jMenu1.setFont(tFont); //創(chuàng)建幫助選項(xiàng) JMenu jMenu2 = new JMenu("幫助"); jMenu2.setFont(tFont); JMenuItem jmi1 = new JMenuItem("新游戲"); jmi1.setFont(tFont); JMenuItem jmi2 = new JMenuItem("退出"); jmi2.setFont(tFont); //jmi1 jmi2添加到菜單項(xiàng)“游戲”中 jMenu1.add(jmi1); jMenu1.add(jmi2); JMenuItem jmi3 = new JMenuItem("操作幫助"); jmi3.setFont(tFont); JMenuItem jmi4 = new JMenuItem("勝利條件"); jmi4.setFont(tFont); //jmi13 jmi4添加到菜單項(xiàng)“游戲”中 jMenu2.add(jmi3); jMenu2.add(jmi4); jmb.add(jMenu1); jmb.add(jMenu2); mainFrame.setJMenuBar(jmb); //添加監(jiān)聽 jmi1.addActionListener(this); jmi2.addActionListener(this); jmi3.addActionListener(this); jmi4.addActionListener(this); //設(shè)置指令 jmi1.setActionCommand("restart"); jmi2.setActionCommand("exit"); jmi3.setActionCommand("help"); jmi4.setActionCommand("win"); } @Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); System.out.println(command); UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("思源宋體", Font.ITALIC, 18))); UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("思源宋體", Font.ITALIC, 18))); if ("exit".equals(command)) { Object[] options = { "確定", "取消" }; int response = JOptionPane.showOptionDialog(this, "您確認(rèn)要退出嗎", "", JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if (response == 0) { System.exit(0); } }else if("restart".equals(command)){ restart(); }else if("help".equals(command)){ JOptionPane.showMessageDialog(null, "通過鍵盤的上下左右來移動(dòng)", "提示!", JOptionPane.INFORMATION_MESSAGE); }else if("win".equals(command)){ JOptionPane.showMessageDialog(null, "移動(dòng)到終點(diǎn)獲得勝利", "提示!", JOptionPane.INFORMATION_MESSAGE); } } void restart(){ } }
運(yùn)行它
繪制迷宮的每個(gè)單元
初始化相關(guān)參數(shù)
public final int ROWS=20;//行 public final int COLS=20;//列 public final int H=20;//每一塊的寬高 Block[][] blocks = null;//存儲每個(gè)單元的二維數(shù)組
創(chuàng)建迷宮單元類(如果對坐標(biāo)計(jì)算不明白,可以往上翻,有圖示說明解釋)
import java.awt.Graphics; import java.util.ArrayList; import java.util.List; /* * 迷宮單元類 */ public class Block { private GamePanel panel = null; private int i=0;//二維數(shù)組的下標(biāo)i private int j=0;//二維數(shù)組的下標(biāo)j private int h=0;//寬高 private int start=6;//偏移像素 //4個(gè)頂點(diǎn)坐標(biāo) private int x1=0;//x1坐標(biāo) private int y1=0;//y1坐標(biāo) private int x2=0;//x2坐標(biāo) private int y2=0;//y2坐標(biāo) private int x3=0;//x3坐標(biāo) private int y3=0;//y3坐標(biāo) private int x4=0;//x4坐標(biāo) private int y4=0;//y4坐標(biāo) //上下左右4個(gè)墻是否顯示,true:顯示,false:隱藏 boolean[] walls=new boolean[4]; private boolean visited=false;//是否被訪問 //構(gòu)造 public Block(int i,int j,int h,GamePanel panel){ this.i=i; this.j=j; this.h=h; this.panel=panel; //計(jì)算4個(gè)頂點(diǎn)的坐標(biāo) init(); } //計(jì)算4個(gè)頂點(diǎn)的坐標(biāo) private void init() { //i代表行 j代表列 //左上角坐標(biāo) this.x1=start+j*h; this.y1=start+i*h; //右上角坐標(biāo) this.x2=start+(j+1)*h; this.y2=start+i*h; //右下角坐標(biāo) this.x3=start+(j+1)*h; this.y3=start+(i+1)*h; //左下角坐標(biāo) this.x4=start+j*h; this.y4=start+(i+1)*h; //默認(rèn)上下左右4個(gè)墻都顯示 walls[0]=true; walls[1]=true; walls[2]=true; walls[3]=true; } //繪制指示器的方法 public void draw(Graphics g) { //繪制迷宮塊 drawBlock(g); } //繪制迷宮塊 private void drawBlock(Graphics g) { //判斷上、右、下、左 的墻,true的話墻就會有,否則墻就沒有 boolean top = walls[0]; boolean right = walls[1]; boolean bottom = walls[2]; boolean left = walls[3]; if(top){//繪制上墻 g.drawLine(x1, y1, x2, y2); } if(right){//繪制右墻 g.drawLine(x2, y2, x3, y3); } if(bottom){//繪制下墻 g.drawLine(x3, y3, x4, y4); } if(left){//繪制左墻 g.drawLine(x4, y4, x1, y1); } } }
在GamePanel類中創(chuàng)建方法createBlocks
//創(chuàng)建數(shù)組內(nèi)容 private void createBlocks() { blocks = new Block[ROWS][COLS]; Block block ; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { block = new Block(i, j,H,this); blocks[i][j]=block; } } }
在構(gòu)造函數(shù)中調(diào)用此方法
//構(gòu)造方法 public GamePanel(GameFrame mainFrame){ this.setLayout(null); this.setOpaque(false); this.mainFrame=mainFrame; this.panel =this; //創(chuàng)建菜單 createMenu(); //創(chuàng)建數(shù)組內(nèi)容 createBlocks(); }
在GamePanel中重新paint方法,繪制這些方塊
public void paint(Graphics g) { super.paint(g); //繪制網(wǎng)格 drawBlock(g); } //繪制迷宮塊 private void drawBlock(Graphics g) { Block block ; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { block = blocks[i][j]; if(block!=null){ block.draw(g); } } } }
運(yùn)行可以看到一個(gè)個(gè)的方形繪制出來了
計(jì)算并打通迷宮
給每個(gè)單元都增加鄰居查找方法(Block類中)
//查找當(dāng)前單元是否有未被訪問的鄰居單元 public List<Block> findNeighbors() { //鄰居分為上下左右 List<Block> res= new ArrayList<Block>();//返回的數(shù)組 Block top = this.getNeighbor(0,false); Block right = this.getNeighbor(1,false); Block bottom = this.getNeighbor(2,false); Block left = this.getNeighbor(3,false); if(top!=null){ res.add(top); } if(right!=null){ res.add(right); } if(bottom!=null){ res.add(bottom); } if(left!=null){ res.add(left); } return res;//返回鄰居數(shù)組 } //根據(jù)方向,獲得鄰居 public Block getNeighbor(int type,boolean lose_visited) { Block neighbor; int ti=0,tj=0; if(type==0){ ti = this.i-1; tj = this.j; }else if(type==1){ ti = this.i; tj = this.j+1; }else if(type==2){ ti = this.i+1; tj = this.j; }else if(type==3){ ti = this.i; tj = this.j-1; } Block[][] blocks = panel.blocks; if(ti<0 || tj<0 || ti>=panel.ROWS || tj>=panel.COLS){//超出邊界了 neighbor = null; }else{ //首先找到這個(gè)鄰居 neighbor = blocks[ti][tj]; //判斷是否被訪問,如果被訪問了返回null if(neighbor.visited && !lose_visited){//lose_visited等于true表示忽略訪問 neighbor = null; } } return neighbor; }
計(jì)算
跟著算法來寫的代碼,唯一要注意的是我設(shè)置了一個(gè)值unVisitedCount,初始值為所有單元的數(shù)量,每當(dāng)一個(gè)單元被標(biāo)記為已訪問后,這個(gè)值就遞減1,當(dāng)值為0后就終止循環(huán),結(jié)束算法。
//線路的計(jì)算處理 private void computed(){ /* 1.將起點(diǎn)作為當(dāng)前迷宮單元并標(biāo)記為已訪問 2.當(dāng)還存在未標(biāo)記的迷宮單元,進(jìn)行循環(huán) 1).如果當(dāng)前迷宮單元有未被訪問過的的相鄰的迷宮單元 (1).隨機(jī)選擇一個(gè)未訪問的相鄰迷宮單元 (2).將當(dāng)前迷宮單元入棧 (3).移除當(dāng)前迷宮單元與相鄰迷宮單元的墻 (4).標(biāo)記相鄰迷宮單元并用它作為當(dāng)前迷宮單元 2).如果當(dāng)前迷宮單元不存在未訪問的相鄰迷宮單元,并且棧不空 (1).棧頂?shù)拿詫m單元出棧 (2).令其成為當(dāng)前迷宮單元 */ Random random = new Random(); Stack<Block> stack = new Stack<Block>();//棧 Block current = blocks[0][0];//取第一個(gè)為當(dāng)前單元 current.setVisited(true);//標(biāo)記為已訪問 int unVisitedCount=ROWS*COLS-1;//因?yàn)榈谝粋€(gè)已經(jīng)設(shè)置為訪問了 List<Block> neighbors ;//定義鄰居 Block next; while(unVisitedCount>0){ neighbors = current.findNeighbors();//查找鄰居集合(未被訪問的) if(neighbors.size()>0){//如果當(dāng)前迷宮單元有未被訪問過的的相鄰的迷宮單元 //隨機(jī)選擇一個(gè)未訪問的相鄰迷宮單元 int index = random.nextInt(neighbors.size()); next = neighbors.get(index); //將當(dāng)前迷宮單元入棧 stack.push(current); //移除當(dāng)前迷宮單元與相鄰迷宮單元的墻 this.removeWall(current,next); //標(biāo)記相鄰迷宮單元并用它作為當(dāng)前迷宮單元 next.setVisited(true); //標(biāo)記一個(gè)為訪問,則計(jì)數(shù)器遞減1 unVisitedCount--;//遞減 current = next; }else if(!stack.isEmpty()){//如果當(dāng)前迷宮單元不存在未訪問的相鄰迷宮單元,并且棧不空 /* 1.棧頂?shù)拿詫m單元出棧 2.令其成為當(dāng)前迷宮單元 */ Block cell = stack.pop(); current = cell; } } }
移除墻
//移除當(dāng)前迷宮單元與相鄰迷宮單元的墻 private void removeWall(Block current, Block next) { if(current.getI()==next.getI()){//橫向鄰居 if(current.getJ()>next.getJ()){//匹配到的是左邊鄰居 //左邊鄰居的話,要移除自己的左墻和鄰居的右墻 current.walls[3]=false; next.walls[1]=false; }else{//匹配到的是右邊鄰居 //右邊鄰居的話,要移除自己的右墻和鄰居的左墻 current.walls[1]=false; next.walls[3]=false; } }else if(current.getJ()==next.getJ()){//縱向鄰居 if(current.getI()>next.getI()){//匹配到的是上邊鄰居 //上邊鄰居的話,要移除自己的上墻和鄰居的下墻 current.walls[0]=false; next.walls[2]=false; }else{//匹配到的是下邊鄰居 //下邊鄰居的話,要移除自己的下墻和鄰居的上墻 current.walls[2]=false; next.walls[0]=false; } } }
在構(gòu)造函數(shù)中調(diào)用computed方法
//構(gòu)造方法 public GamePanel(GameFrame mainFrame){ this.setLayout(null); this.setOpaque(false); this.mainFrame=mainFrame; this.panel =this; //創(chuàng)建菜單 createMenu(); //創(chuàng)建數(shù)組內(nèi)容 createBlocks(); //計(jì)算處理線路 computed(); }
運(yùn)行效果
繪制起點(diǎn)終點(diǎn)
創(chuàng)建Rect類
package main; import java.awt.Color; import java.awt.Graphics; //開始結(jié)束方塊 public class Rect { private int i=0;//二維數(shù)組的下標(biāo)i private int j=0;//二維數(shù)組的下標(biāo)j private int x=0;//x坐標(biāo) private int y=0;//y坐標(biāo) private int h=0;//寬高 private int start=6;//偏移像素 private String type="";//start end public Rect(int i,int j,int h,String type){ this.i=i; this.j=j; this.h=h; this.type=type; } //初始化 private void init() { this.x=start+j*h+2; this.y=start+i*h+2; } //繪制 void draw(Graphics g){ //計(jì)算x、y坐標(biāo) init(); Color oColor = g.getColor(); if("start".equals(type)){//紅色 g.setColor(Color.red); }else{ g.setColor(Color.blue); } g.fillRect(x, y, h-3, h-3); g.setColor(oColor); } //移動(dòng) public void move(int type, Block[][] blocks,GamePanel panel) { //根據(jù)當(dāng)前start方形,獲得對應(yīng)的迷宮單元 Block cur = blocks[this.i][this.j]; boolean wall = cur.walls[type];//得到對應(yīng)的那面墻 if(!wall){ //得到移動(dòng)方塊對應(yīng)的單元 Block next = cur.getNeighbor(type,true); if(next!=null){ this.i = next.getI(); this.j = next.getJ(); panel.repaint(); //判斷如果i,j等于終點(diǎn)的,則表示獲得成功 if(this.i==panel.end.i && this.j==panel.end.j){ panel.gameWin(); } } } } public int getI() { return i; } public void setI(int i) { this.i = i; } public int getJ() { return j; } public void setJ(int j) { this.j = j; } }
在GamePanel類中創(chuàng)建方法,并在構(gòu)造中調(diào)用。
//創(chuàng)建開始結(jié)束的方形 private void createRects() { start = new Rect(0, 0, H, "start") ; end = new Rect(ROWS-1, COLS-1, H, "end") ; }
//構(gòu)造方法 public GamePanel(GameFrame mainFrame){ this.setLayout(null); this.setOpaque(false); this.mainFrame=mainFrame; this.panel =this; //創(chuàng)建菜單 createMenu(); //創(chuàng)建數(shù)組內(nèi)容 createBlocks(); //計(jì)算處理線路 computed(); //創(chuàng)建開始結(jié)束的方形 createRects(); }
在paint方法中繪制
@Override public void paint(Graphics g) { super.paint(g); //繪制網(wǎng)格 drawBlock(g); //繪制開始結(jié)束方向 drawRect(g); } //繪制開始結(jié)束方塊 private void drawRect(Graphics g) { end.draw(g); start.draw(g); }
運(yùn)行一下
加入鍵盤移動(dòng)監(jiān)聽
創(chuàng)建監(jiān)聽方法
//添加鍵盤監(jiān)聽 private void createKeyListener() { KeyAdapter l = new KeyAdapter() { //按下 @Override public void keyPressed(KeyEvent e) { if(!"start".equals(gameFlag)) return ; int key = e.getKeyCode(); switch (key) { //向上 case KeyEvent.VK_UP: case KeyEvent.VK_W: if(start!=null) start.move(0,blocks,panel); break; //向右 case KeyEvent.VK_RIGHT: case KeyEvent.VK_D: if(start!=null) start.move(1,blocks,panel); break; //向下 case KeyEvent.VK_DOWN: case KeyEvent.VK_S: if(start!=null) start.move(2,blocks,panel); break; //向左 case KeyEvent.VK_LEFT: case KeyEvent.VK_A: if(start!=null) start.move(3,blocks,panel); break; } } //松開 @Override public void keyReleased(KeyEvent e) { } }; //給主frame添加鍵盤監(jiān)聽 mainFrame.addKeyListener(l); }
在構(gòu)造中調(diào)用
//構(gòu)造方法 public GamePanel(GameFrame mainFrame){ this.setLayout(null); this.setOpaque(false); this.mainFrame=mainFrame; this.panel =this; //創(chuàng)建菜單 createMenu(); //創(chuàng)建數(shù)組內(nèi)容 createBlocks(); //計(jì)算處理線路 computed(); //創(chuàng)建開始結(jié)束的方形 createRects(); //添加鍵盤事件監(jiān)聽 createKeyListener(); }
運(yùn)行
收尾
此時(shí)代碼已經(jīng)基本完成,加入游戲勝利、重新開始等方法即可
//重新開始 void restart() { /*參數(shù)重置 1.游戲狀態(tài) 2.迷宮單元重置 3.重新計(jì)算線路 */ //1.游戲狀態(tài) gameFlag="start"; //2.迷宮單元重置 Block block ; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { block = blocks[i][j]; if(block!=null){ block.setVisited(false); block.walls[0]=true; block.walls[1]=true; block.walls[2]=true; block.walls[3]=true; } } } //3.計(jì)算處理線路 computed(); //開始方塊歸零 start.setI(0); start.setJ(0); //重繪 repaint(); }
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
JAVA基于Redis實(shí)現(xiàn)計(jì)數(shù)器限流的使用示例
計(jì)數(shù)器法是限流算法里最簡單也是最容易實(shí)現(xiàn)的一種算法,本文主要介紹了JAVA基于Redis實(shí)現(xiàn)計(jì)數(shù)器限流的使用示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09基于java實(shí)現(xiàn)DFA算法代碼實(shí)例
這篇文章主要介紹了基于java實(shí)現(xiàn)DFA算法代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09自己動(dòng)手用Springboot實(shí)現(xiàn)仿百度網(wǎng)盤的實(shí)踐
本項(xiàng)目基于Springboot開發(fā)實(shí)現(xiàn),前端采用BootStrap開發(fā)實(shí)現(xiàn),模仿百度網(wǎng)盤實(shí)現(xiàn)相關(guān)功能,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12IDEA解決src和resource下創(chuàng)建多級目錄的操作
這篇文章主要介紹了IDEA解決src和resource下創(chuàng)建多級目錄的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02java根據(jù)圖片中綠色像素點(diǎn)的多少進(jìn)行排序
這篇文章主要介紹了java根據(jù)圖片中綠色像素點(diǎn)的多少進(jìn)行排序,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03