最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

老程序員教你一天時(shí)間完成Java迷宮小游戲

 更新時(shí)間:2021年08月12日 09:55:03   投稿:BJT  
最近經(jīng)常在機(jī)房看同學(xué)在玩一個(gè)走迷宮的游戲,比較有趣,自己也用java寫一個(gè)實(shí)現(xiàn)隨機(jī)生成迷宮的算法,其實(shí)就是一個(gè)圖的深度優(yōu)先遍歷算法.

效果圖

在這里插入圖片描述

實(shí)現(xiàn)思路

1.創(chuàng)建運(yùn)行窗口。
2.創(chuàng)建菜單。
3.繪制迷宮的每個(gè)單元。
4.通過(guò)算法計(jì)算迷宮路徑,并打通路徑,形成迷宮。
5.繪制起點(diǎn)終點(diǎn)。
6.添加鍵盤事件控制起點(diǎn)方塊移動(dòng)。
7.收尾。

迷宮算法(網(wǎng)上參考的)

1.將起點(diǎn)作為當(dāng)前迷宮單元并標(biāo)記為已訪問(wèn)

2.當(dāng)還存在未標(biāo)記的迷宮單元,進(jìn)行循環(huán)

1).如果當(dāng)前迷宮單元有未被訪問(wèn)過(guò)的的相鄰的迷宮單元

(1).隨機(jī)選擇一個(gè)未訪問(wèn)的相鄰迷宮單元

(2).將當(dāng)前迷宮單元入棧

(3).移除當(dāng)前迷宮單元與相鄰迷宮單元的墻

(4).標(biāo)記相鄰迷宮單元并用它作為當(dāng)前迷宮單元

2).如果當(dāng)前迷宮單元不存在未訪問(wèn)的相鄰迷宮單元,并且棧不空

(1).棧頂?shù)拿詫m單元出棧

(2).令其成為當(dāng)前迷宮單元

**這個(gè)算法叫做“深度優(yōu)先”,簡(jiǎn)單來(lái)說(shuō),就是從起點(diǎn)開始走,尋找它的上下左右4個(gè)鄰居,然后隨機(jī)一個(gè)走,到走不通的時(shí)候就返回上一步繼續(xù)走,直到全部單元都走完。 **

相關(guān)圖示說(shuō)明

每個(gè)單元的墻,分為上墻、右墻、下墻、左墻,把這些墻用長(zhǎng)度為4的數(shù)組表示,元素的值為true則表示墻存在,否則墻不存在,代碼里數(shù)組的下標(biāo)方式來(lái)確定墻是否存在。

單元是根據(jù)行列來(lái)創(chuàng)建的,會(huì)用到雙循環(huán),類似表格,比如第二行用 i 來(lái)表示的話就是 1,第3列用 j 來(lái)表示就是2,那第二行第3列的元素組合起來(lái)就是(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為相對(duì)偏移量,為了讓迷宮兩邊有些空隙):

//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. 墻的處理,之前說(shuō)到墻是以一個(gè)4個(gè)元素的數(shù)組來(lái)表示的,比如數(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,用來(lái)顯示在屏幕上(window的對(duì)象),每個(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類,來(lái)啟動(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類,窗口建出來(lái)了

在這里插入圖片描述

創(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, "通過(guò)鍵盤的上下左右來(lái)移動(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, "通過(guò)鍵盤的上下左右來(lái)移動(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;//存儲(chǔ)每個(gè)單元的二維數(shù)組

創(chuàng)建迷宮單元類(如果對(duì)坐標(biāo)計(jì)算不明白,可以往上翻,有圖示說(shuō)明解釋)

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;//是否被訪問(wèn)
	//構(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的話墻就會(huì)有,否則墻就沒(méi)有
		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è)的方形繪制出來(lái)了

在這里插入圖片描述

計(jì)算并打通迷宮

給每個(gè)單元都增加鄰居查找方法(Block類中)

//查找當(dāng)前單元是否有未被訪問(wèn)的鄰居單元
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];
		//判斷是否被訪問(wèn),如果被訪問(wèn)了返回null
		if(neighbor.visited && !lose_visited){//lose_visited等于true表示忽略訪問(wèn)
			neighbor = null;
		}
	}
	return neighbor;
}

計(jì)算

跟著算法來(lái)寫的代碼,唯一要注意的是我設(shè)置了一個(gè)值unVisitedCount,初始值為所有單元的數(shù)量,每當(dāng)一個(gè)單元被標(biāo)記為已訪問(wèn)后,這個(gè)值就遞減1,當(dāng)值為0后就終止循環(huán),結(jié)束算法。

//線路的計(jì)算處理
private void computed(){
	/*
	1.將起點(diǎn)作為當(dāng)前迷宮單元并標(biāo)記為已訪問(wèn)
	2.當(dāng)還存在未標(biāo)記的迷宮單元,進(jìn)行循環(huán)
		1).如果當(dāng)前迷宮單元有未被訪問(wèn)過(guò)的的相鄰的迷宮單元
			(1).隨機(jī)選擇一個(gè)未訪問(wèn)的相鄰迷宮單元
			(2).將當(dāng)前迷宮單元入棧
			(3).移除當(dāng)前迷宮單元與相鄰迷宮單元的墻
			(4).標(biāo)記相鄰迷宮單元并用它作為當(dāng)前迷宮單元
		2).如果當(dāng)前迷宮單元不存在未訪問(wèn)的相鄰迷宮單元,并且棧不空
			(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)記為已訪問(wèn)
	int unVisitedCount=ROWS*COLS-1;//因?yàn)榈谝粋€(gè)已經(jīng)設(shè)置為訪問(wèn)了
	List<Block> neighbors ;//定義鄰居
	Block next;
	while(unVisitedCount>0){
		neighbors = current.findNeighbors();//查找鄰居集合(未被訪問(wèn)的)
		if(neighbors.size()>0){//如果當(dāng)前迷宮單元有未被訪問(wèn)過(guò)的的相鄰的迷宮單元
			//隨機(jī)選擇一個(gè)未訪問(wèn)的相鄰迷宮單元
			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è)為訪問(wèn),則計(jì)數(shù)器遞減1
			unVisitedCount--;//遞減
			current = next;
		}else if(!stack.isEmpty()){//如果當(dāng)前迷宮單元不存在未訪問(wèn)的相鄰迷宮單元,并且棧不空
			/*
				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方形,獲得對(duì)應(yīng)的迷宮單元
		Block cur = blocks[this.i][this.j];
		boolean wall = cur.walls[type];//得到對(duì)應(yīng)的那面墻	
		if(!wall){
			//得到移動(dòng)方塊對(duì)應(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é)

本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Spring實(shí)戰(zhàn)之@Autowire注解用法詳解

    Spring實(shí)戰(zhàn)之@Autowire注解用法詳解

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之@Autowire注解用法,結(jié)合實(shí)例形式詳細(xì)分析了Spring @Autowire注解具體實(shí)現(xiàn)步驟與相關(guān)使用技巧,需要的朋友可以參考下
    2019-12-12
  • java集合與數(shù)組的相同點(diǎn)和不同點(diǎn)

    java集合與數(shù)組的相同點(diǎn)和不同點(diǎn)

    今天小編就為大家分享一篇關(guān)于java集合與數(shù)組的相同點(diǎn)和不同點(diǎn),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • Java基礎(chǔ)之java處理ip的工具類

    Java基礎(chǔ)之java處理ip的工具類

    這篇文章主要介紹了Java基礎(chǔ)應(yīng)用,使用java處理ip的工具類的相關(guān)資料,需要的朋友可以參考下
    2014-10-10
  • SpringBoot中dubbo+zookeeper實(shí)現(xiàn)分布式開發(fā)的應(yīng)用詳解

    SpringBoot中dubbo+zookeeper實(shí)現(xiàn)分布式開發(fā)的應(yīng)用詳解

    這篇文章主要介紹了SpringBoot中dubbo+zookeeper實(shí)現(xiàn)分布式開發(fā)的應(yīng)用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java分布式流處理組件Producer入門詳解

    java分布式流處理組件Producer入門詳解

    這篇文章主要為大家介紹了java分布式流處理組件Producer入門詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Kotlin 基礎(chǔ)教程之反射

    Kotlin 基礎(chǔ)教程之反射

    這篇文章主要介紹了Kotlin 基礎(chǔ)教程之反射的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • RabbitMQ消息隊(duì)列之持久化機(jī)制詳解

    RabbitMQ消息隊(duì)列之持久化機(jī)制詳解

    這篇文章主要介紹了RabbitMQ消息隊(duì)列之持久化機(jī)制詳解,持久化,即將原本存在于內(nèi)存中的數(shù)據(jù)寫入到磁盤上永久保存數(shù)據(jù),防止服務(wù)宕機(jī)時(shí)內(nèi)存數(shù)據(jù)的丟失,Rabbitmq 的持久化分為隊(duì)列持久化、消息持久化和交換器持久化,需要的朋友可以參考下
    2023-08-08
  • Java跨域問(wèn)題分析與解決方法詳解

    Java跨域問(wèn)題分析與解決方法詳解

    這篇文章主要介紹了Java跨域問(wèn)題分析與解決方法,跨域問(wèn)題是在Web應(yīng)用程序中,由于同源策略的限制,導(dǎo)致瀏覽器無(wú)法發(fā)送跨域請(qǐng)求,也無(wú)法獲取跨域響應(yīng)的問(wèn)題,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • Maven的安裝+配置本地倉(cāng)庫(kù)路徑方式

    Maven的安裝+配置本地倉(cāng)庫(kù)路徑方式

    這篇文章主要介紹了Maven的安裝+配置本地倉(cāng)庫(kù)路徑方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • springboot之SpringApplication生命周期和事件機(jī)制解讀

    springboot之SpringApplication生命周期和事件機(jī)制解讀

    這篇文章主要介紹了springboot之SpringApplication生命周期和事件機(jī)制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06

最新評(píng)論

绥棱县| 甘孜| 伽师县| 阿拉善左旗| 金乡县| 塘沽区| 禄丰县| 大安市| 临澧县| 高雄市| 敖汉旗| 平和县| 淮北市| 仙游县| 中山市| 四子王旗| 灌阳县| 离岛区| 西青区| 广南县| 沭阳县| 西乡县| 兴义市| 襄垣县| 北碚区| 台湾省| 苏尼特右旗| 临猗县| 雷州市| 调兵山市| 平度市| 神农架林区| 莱芜市| 独山县| 略阳县| 大姚县| 靖边县| 营山县| 萨迦县| 图片| 巴马|