⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mazegame.java

📁 一个迷宫游戏,最大特色是可以随机生成迷宫,可以遍历迷宫得到答案,可以在迷宫中添加追赶者.随机生成迷宫算法和遍历算法比较经典,可提供参考.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
	 */
	public void paintComponent(Graphics page) {
		super.paintComponent(page);

		// 画水平的单位墙
		page.setColor(Color.black);
		for (int i = 0; i < this.height + 1; i++)
			for (int j = 0; j < this.width; j++)
				if (horizontal[i][j] == Wall.exist)// 这个水平单位墙存在才画
					page.drawLine(j * checkSize, i * checkSize, j * checkSize
							+ checkSize, i * checkSize);

		// 画竖直的单位墙
		page.setColor(Color.black);
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width + 1; j++)
				if (vertical[i][j] == Wall.exist)// 这个竖直单位墙存在才画
					page.drawLine(j * checkSize, i * checkSize, j * checkSize,
							i * checkSize + checkSize);
		// 画终点
		page.setColor(Color.darkGray);
		page.drawString("终点", this.width * checkSize, this.height * checkSize);

		if (!solve) {// 如果解答为关,画玩家位置
			page.setColor(Color.blue);
			page.fillOval(playerColumn * checkSize, playerRow * checkSize,
					checkSize, checkSize);
		}

		if (chase && !solve) {// 如果解答为关且追赶者为开则画追赶者
			page.setColor(Color.red);
			for (Chaser chaser : chasers)
				page.fillOval(chaser.getColumn() * checkSize,
						chaser.getRow() * checkSize, checkSize, checkSize);
		}

		if (solve) {// 如果解答为"开",就画出主路径
			page.setColor(Color.green);
			for (int i = 0; i < this.height; i++)
				for (int j = 0; j < this.width; j++)
					if (checks[i][j] == Check.main)// 方格在主路径上
						page.fillOval(j * checkSize, i * checkSize, checkSize,
								checkSize);
		}

	}

	/**
	 * 在本迷宫面板上重新随机生成一个迷宫.设置同初始化的一样
	 * 这是新生成迷宫的提示:这是一个迷宫游戏.玩家是蓝点,走到右下角就赢.若途中碰到两个红点追赶者就输.请按键盘的方向键移动
	 * (建议新生成迷宫时给予玩家提示)
	 * 
	 * @param checkSize
	 *            (迷宫由单位方格构成)单位方格的边长,以像素输入
	 * @param width
	 *            迷宫的宽度.例如:宽度若为3即宽度为3个单位方格
	 * @param height
	 *            迷宫的高度.例如:高度若为3即高度为3个单位方格
	 * @param numberOfChasers
	 *            追赶者的数量(不要追赶者则为0)
	 * @param tearDownAllowed
	 *            玩家可拆墙次数限制(不可拆墙则为0,可拆无数次则为-1)
	 */
	public void newMaze(int checkSize, int width, int height,
			int numberOfChasers, int tearDownAllowed) {
		this.checkSize = checkSize;
		this.width = width;
		this.height = height;
		this.tearDownAllowed = tearDownAllowed;
		this.playerRow = 0;
		this.playerColumn = 0;// 玩家初始在左上角的方格:起点
		this.solve = false;// 不打印结果
		this.timer = new Timer(DELAY, new TimerListener());// 追赶者移动定时器

		if (numberOfChasers < 1) {
			this.chase = false;// 玩家设定追赶者为"关"
			chasers = new Chaser[0];
		} else {
			this.chase = true;
			chasers = new Chaser[numberOfChasers];// 初始化追赶者
			for (int i = 0; i < numberOfChasers; i++) {
				Random gen = new Random();
				int ranRow, ranColumn;
				ranRow = gen.nextInt(this.height);
				ranColumn = gen.nextInt(this.width);
				chasers[i] = new Chaser(ranRow, ranColumn);
			}
			chaseOn();// 开启追赶者,使其移动
		}

		this.currentResult = 0;// 游戏进行中
		this.checks = new Check[this.height][this.width];// 迷宫为height*width个方格
		this.horizontal = new Wall[this.height + 1][this.width];
		// 单位水平墙.horizontalWalls有height*width-1个
		this.vertical = new Wall[this.height][this.width + 1];
		// 单位竖直墙.horizontalWalls有(height-1)*width个
		this.notMarked = new boolean[this.height][this.width];
		// 单位方格是否有标记过(在随机生成迷宫时需要)

		// 以下为迷宫具体初始化:
		// 全部方格状态初始化为"未踏足过"
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width; j++)
				checks[i][j] = Check.notFoot;

		// 全部方格初始化为"未标记"
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width; j++)
				notMarked[i][j] = true;

		// 全部水平墙状态初始化为"存在"
		for (int i = 0; i < this.height + 1; i++)
			for (int j = 0; j < this.width; j++)
				horizontal[i][j] = Wall.exist;

		// 全部竖直墙状态初始化为"存在"
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width + 1; j++)
				vertical[i][j] = Wall.exist;

		// 迷宫左上角方格为入口,因此它的左墙为不存在
		vertical[0][0] = Wall.notExist;

		// 迷宫右下角为出口,因此它的右墙不存在
		vertical[this.height - 1][this.width] = Wall.notExist;

		// 随机生成迷宫.其实质是:拆除若干个水平墙和竖直墙以便能形成迷宫
		generate(0, 0);

		// 生成迷宫后立刻遍历,得到答案:checks[i][j]为Check.main的都是在主路径上
		// 分析Java程序设计教程书上的算法,是从首格开始的valid,但是本算法不是从首格开始.因此要从0,1开始,若不行则从1,0开始
		if (!traverse(0, 0, 0, 1))
			traverse(0, 0, 1, 0);

		// 遍历完后可能有些不在主路径上的方格未设置成Check.notMain,最好执行以下语句
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width; j++)
				if (checks[i][j] != Check.main)
					checks[i][j] = Check.notMain;

		// 新迷宫:重画
		repaint();
	}

	/**
	 * 无墙模式:新建一个没有墙的迷宫,玩家闪避过所有追赶者,走到右下角终点就赢.
	 * 
	 * @param checkSize
	 *            (迷宫由单位方格构成)单位方格的边长,以像素输入
	 * @param width
	 *            迷宫的宽度.例如:宽度若为3即宽度为3个单位方格
	 * @param height
	 *            迷宫的高度.例如:高度若为3即高度为3个单位方格
	 * @param numberOfChasers
	 *            追赶者的数量(不建议为0)
	 * @param delay
	 *            追赶者移动延迟时间(即每隔多少时间移动一次).单位:毫秒
	 */
	public void noWalls(int checkSize, int width, int height,
			int numberOfChasers,int delay){
		this.checkSize = checkSize;
		this.width = width;
		this.height = height;
		this.playerRow = 0;
		this.playerColumn = 0;// 玩家初始在左上角的方格:起点
		this.solve = false;// 不打印结果
		this.timer = new Timer(delay, new TimerListener());// 追赶者移动定时器

		if (numberOfChasers < 1) {
			this.chase = false;// 玩家设定追赶者为"关"
			chasers = new Chaser[0];
		} else {
			this.chase = true;
			chasers = new Chaser[numberOfChasers];// 初始化追赶者
			for (int i = 0; i < numberOfChasers; i++) {
				Random gen = new Random();
				int ranRow, ranColumn;
				ranRow = gen.nextInt(this.height);
				ranColumn = gen.nextInt(this.width);
				chasers[i] = new Chaser(ranRow, ranColumn);
			}
			chaseOn();// 开启追赶者,使其移动
		}

		this.currentResult = 0;// 游戏进行中
		this.checks = new Check[this.height][this.width];// 迷宫为height*width个方格
		this.horizontal = new Wall[this.height + 1][this.width];
		// 单位水平墙.horizontalWalls有height*width-1个
		this.vertical = new Wall[this.height][this.width + 1];
		// 单位竖直墙.horizontalWalls有(height-1)*width个
		this.notMarked = new boolean[this.height][this.width];
		// 单位方格是否有标记过(在随机生成迷宫时需要)

		// 以下为迷宫具体初始化:
		// 全部方格状态初始化为"未踏足过"
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width; j++)
				checks[i][j] = Check.notFoot;

		// 全部方格初始化为"未标记"
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width; j++)
				notMarked[i][j] = true;

		// 全部内部水平墙状态初始化为"不存在"
		for (int i = 0; i < this.height + 1; i++)
			for (int j = 0; j < this.width; j++)
				if(i>0&&i<this.height+1)
					horizontal[i][j] = Wall.notExist;
				else
				horizontal[i][j] = Wall.exist;

		// 全部内部竖直墙状态初始化为"不存在"
		for (int i = 0; i < this.height; i++)
			for (int j = 0; j < this.width + 1; j++)
				if(j>0&&j<this.width+1)
					vertical[i][j] = Wall.notExist;
				else
				vertical[i][j] = Wall.exist;

		// 迷宫左上角方格为入口,因此它的左墙为不存在
		vertical[0][0] = Wall.notExist;

		// 迷宫右下角为出口,因此它的右墙不存在
		vertical[this.height - 1][this.width] = Wall.notExist;

		// 新无墙迷宫:重画
		repaint();
	}
	
	/**
	 * 本方法供traverse方法调用,用于判断从i1行j1列的方格走到i2行j2列的方格是否可行
	 * 
	 * @param i1
	 *            原方格所在行数
	 * @param j1
	 *            原方格所在列数
	 * @param i2
	 *            目标方格所在行数
	 * @param j2
	 *            目标方格所在列数
	 * @return 从原格走到目标格可行则返回true;否则返回false
	 */
	private boolean valid(int i1, int j1, int i2, int j2) {
		boolean result = false;

		if (i2 >= 0 && i2 < this.height && j2 >= 0 && j2 < this.width)
			if (checks[i2][j2] == Check.notFoot) {// 保证没有越界而且目标方格未踏足过
				if (i1 == i2 - 1 && horizontal[i2][j2] == Wall.notExist)// 从上往下
					result = true;
				else if (i1 == i2 + 1 && horizontal[i1][j1] == Wall.notExist)// 从下往上
					result = true;
				else if (j1 == j2 - 1 && vertical[i2][j2] == Wall.notExist)// 从左往右
					result = true;
				else if (j1 == j2 + 1 && vertical[i1][j1] == Wall.notExist)// 从右往左
					result = true;
			}

		return result;

	}

	/**
	 * 遍历迷宫,遍历完成后就能找到主路径:checks[i][j]为Check.main的方格都在主路径上
	 * 
	 * @param i1
	 *            原方格所在行数
	 * @param j1
	 *            原方格所在列数
	 * @param i2
	 *            目标方格所在行数
	 * @param j2
	 *            目标方格所在列数
	 * @return 找到从起点到终点路径则返回true;否则返回false
	 */
	private boolean traverse(int i1, int j1, int i2, int j2) {
		boolean done = false;

		if (i1 == 0 && j1 == 0)// 起点
			checks[i1][j1] = Check.main;

		if (valid(i1, j1, i2, j2)) {
			checks[i2][j2] = Check.notMain;// 先设定为notMain表示不在主路径上

			if (i2 == this.height - 1 && j2 == this.width - 1)
				done = true; // 到达终点
			else {
				done = traverse(i2, j2, i2 + 1, j2); // down
				if (!done)
					done = traverse(i2, j2, i2, j2 + 1); // right
				if (!done)
					done = traverse(i2, j2, i2 - 1, j2); // up
				if (!done)
					done = traverse(i2, j2, i2, j2 - 1); // left
			}

			if (done) // 若done为true说明这个方格在主路径上
				checks[i2][j2] = Check.main;
		}

		return done;
	}

	/**
	 * 开启解答:迷宫中将会显示解答
	 */
	public void solveOn() {
		solve = true;
		repaint();
	}

	/**
	 * 关闭解答:迷宫中将不显示解答
	 */
	public void solveOff() {
		solve = false;
		repaint();
	}

	/**
	 * 玩家移动(当然,有墙阻挡就走不了那个方向)
	 * 
	 * @param direction
	 *            1--向左走,2--向上走,3--向右走,4--向下走
	 * @return 成功走了一步则返回true;否则返回false
	 */
	public boolean move(int direction) {
		boolean succeed = false;

		switch (direction) {
		case 1:
			if (playerColumn != 0
					&& vertical[playerRow][playerColumn] == Wall.notExist) {
				playerColumn -= 1;
				succeed = true;
			}
			break;
		case 2:
			if (playerRow != 0
					&& horizontal[playerRow][playerColumn] == Wall.notExist)// 不在第一行且没有墙阻挡
			{
				playerRow -= 1;
				succeed = true;
			}
			break;
		case 3:
			if (playerColumn != this.width - 1
					&& vertical[playerRow][playerColumn + 1] == Wall.notExist) {
				playerColumn += 1;
				succeed = true;
			}
			break;
		case 4:
			if (playerRow != this.height - 1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -