这一部分是实现炸弹人游戏,与之前的两个例子大同小异,只是需要注意两点
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);
}
}










