这一部分是实现炸弹人游戏,与之前的两个例子大同小异,只是需要注意两点
1. 需要增加一个在某个位置上计算可以消灭敌人数量的方法
2. 由于这个场景中不是求最短路径或者放置纸牌数字,之前的场景中放置完之后需要撤回,因为纸盒放置纸牌允许一个纸盒中放置纸牌后再拿出去,最短路径允许走到一个盒子之后再离开,之后的路径中再次走过这个格子。 而在炸弹人游戏中,目的是求每个格子可以消灭的敌人数量,从而找到最多的那个格子,所以一个格子走过之后就不需要再次走了,因此深度优先的递归之后不需要加撤回的步骤。
下面上代码:
深度优先
java:
import java.util.Scanner; public class DfsZhaDanRen { static int[][] directions = { //定义一个方向数组,分别用来取每个格子的右、下、左、上格子 {0, 1}, {1, 0}, {0, -1}, {-1, 0} }; static char[][] map = new char[50][50]; static int[][] book = new int[50][50]; public static int countEnemy(int x, int y) { int count = 0; int i = x; int j = y; while (map[i][j] != '#') { //向右计数,统计向右可以消灭的敌人个数 if (map[i][j] == 'G') { count ++; } j ++; } i = x; j = y; while (map[i][j] != '#') { //向下统计可以消灭的敌人的个数 if (map[i][j] == 'G') { count ++; } i ++; } i = x; j = y; while (map[i][j] != '#') { //向左统计可以消灭的敌人的个数 if (map[i][j] == 'G') { count ++; } j --; } i = x; j = y; while (map[i][j] != '#') { //向上统计可以消灭的敌人的个数 if (map[i][j] == 'G') { count ++; } i --; } return count; } static int maxEnemy = -1; static int i; static int j; public static void dfs(int x, int y) { int enemyNum = countEnemy(x, y); if (enemyNum > maxEnemy) { //当前位置可以消灭的敌人数如果大于最大值,则改最大值 maxEnemy = enemyNum; i = x; j = y; } for (int i = 0; i < directions.length; i++) { //分别向每个方向深入 int nextX = x + directions[i][0]; int nextY = y + directions[i][1]; if (map[nextX][nextY] == '.' && book[nextX][nextY] == 0) { book[nextX][nextY] = 1; dfs(nextX, nextY); //下一个位置的格子符合放炸弹规则,从下一格子开始深度优先搜索,注意递归完不需要book[]=0,因为这不是盒子里面放纸牌,放完之后不需要撤回,每个格子走过了就走过了,不需要撤回 } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for (int i = 0; i < n; i++) { map[i] = sc.next().toCharArray(); } book[3][3] = 1; dfs(3, 3); System.out.println("最多可消灭敌人" + maxEnemy + "个"); System.out.println("应该把炸弹放置在" + "(" + i + "," + j + ")" + "处"); } }
广度优先:
Java:
import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; public class BfsZhaDanRen { static class Site { int x; int y; public Site(int x, int y) { //定义一个位置类 this.x = x; this.y = y; } } static int[][] directions = { //定义一个方向数组,分别用来取每个格子的右、下、左、上格子 {0, 1}, {1, 0}, {0, -1}, {-1, 0} }; static char[][] map = new char[50][50]; static int[][] book = new int[50][50]; public static int countEnemy(int x, int y) { int count = 0; int i = x; int j = y; while (map[i][j] != '#') { //向右计数,统计向右可以消灭的敌人个数 if (map[i][j] == 'G') { count ++; } j ++; } i = x; j = y; while (map[i][j] != '#') { //向下统计可以消灭的敌人的个数 if (map[i][j] == 'G') { count ++; } i ++; } i = x; j = y; while (map[i][j] != '#') { //向左统计可以消灭的敌人的个数 if (map[i][j] == 'G') { count ++; } j --; } i = x; j = y; while (map[i][j] != '#') { //向上统计可以消灭的敌人的个数 if (map[i][j] == 'G') { count ++; } i --; } return count; } public static void bfs(int startX, int startY) { //寻找消灭敌人最多的位置的广度优先搜索 int maxCount = -1; //定义一个变量存储可以消灭的最多的敌人数量 int resX = 0; //定义两个变量存储消灭敌人最多的点的坐标 int resY = 0; Site startPoint = new Site(startX, startY); Queue<Site> queue = new LinkedList<Site>(); queue.offer(startPoint); //首先把起始位置入队 while (!queue.isEmpty()) { Site site = queue.poll(); book[site.x][site.y] = 1; int enemyNum = countEnemy(site.x, site.y); if (enemyNum > maxCount) { //判断当前这一位置是否能消灭最多的敌人 maxCount = enemyNum; resX = site.x; resY = site.y; } for (int[] direction : directions) { //将当前这一点附近四个方向的位置添加到队列中 int nextX = site.x + direction[0]; int nextY = site.y + direction[1]; if (book[nextX][nextY] == 0 && map[nextX][nextY] == '.') { Site nextSite = new Site(nextX, nextY); queue.offer(nextSite); } } } System.out.println("最多可以消灭" + maxCount + "个敌人"); System.out.println("应该将炸弹放置在" + "(" + resX + "," + resY + ")" + "处"); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); //读入行数 for (int i = 0; i < n; i++) { map[i] = sc.next().toCharArray(); } bfs(3, 3); } }