用广度优先搜索方法解决放置炸弹游戏

炸弹游戏规则:在一个n*n的方阵里,每一个方格分别代表空地,敌人,墙,三种元素的分布为随机分布,现在玩家要从地图的某一个空地(已知坐标点)出发,走到一个空地上放置炸弹,炸弹可以炸毁该点对应行列上的所有敌人,但是炸弹不能炸穿墙,要求的是玩家在哪一个点放置炸弹能够炸掉最多敌人,最多炸几个?(注意:必须考虑玩家从出发点到放置炸弹点之间的可通过路径,即玩家只能通过空地走到放置炸弹点,且不能走墙外。)

/*在程序中,我们自定义一个规格不超过20*20的地图,用“#”表示墙,“ . ” 表示空地,“G”表示敌人*/

#include<stdio.h>
struct note                    //定义一个结构体来产生一个队列
{
	int x;           
	int y;
};
  char a[20][20];           //假设地图的规格不超过20*20;
  int getnum(int i,int j)    //统计在(i,j)炸掉的敌人个数的函数;
  {
	  int sum,x,y;
	  sum=0;

//将坐标i,j复制到x,y中,便于下面向上下左右四个方向统计炸掉的敌人个数的操作;

	  x=i;y=j;
	  while(a[x][y]!='#')             //确保炸弹不是放在墙上;
	  {
		  if(a[x][y]=='G')        
			  sum++;           //统计炸掉的敌人;
		  x--;                          //向上统计;
	  }
	  x=i;y=j;                           //重新定位回(i,j)点;
	  while(a[x][y]!='#')
	  {
		  if(a[x][y]=='G')
			  sum++;
		  x++;                     //向下统计;
	  }
	  x=i;y=j;
	  while(a[x][y]!='#')
	  {
		  if(a[x][y]=='G')
			  sum++;
		  y--;                         //向左统计;
	  }
	  x=i;y=j;
	  while(a[x][y]!='#')
	  {
		  if(a[x][y]=='G')
		      sum++;
		  y++;                   //向右统计;
	  }
	  return sum;               //返回炸掉的敌人个数
  }

  int main()
  {
	  struct note que[401];      //因为地图不超过20*20,所以队列的扩展不会超过400个,加上队尾,所以为401个;
	  int head,tail;                   //定义队列的队头和队尾;
	  int book[20][20]={0};     //book用来标记哪些点是已经走过的,防止重复走,标记为1时表示为走过,初始化时全为0;
	  int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};     //next数组分别表示向右,向下,向左,向上走一步;
	  int m,n,i,j,startx,starty,max=0,sum=0,mx,my,k,tx,ty;     //m,n分别为地图的规格,i,j为定义地图时for循环用到的变量,(startx,starty)为玩家起始点,max为消灭的最多敌人,sum为在每一个空地所能消灭的敌人的个数,(mx,my)为放置炸弹的坐标,k为分别进行向上下左右进行移动的标记次数,(tx,ty)为进行移动后玩家的新坐标;
	  scanf("%d%d%d%d",&m,&n,&startx,&starty);    //自定义地图;
	  for(i=0;i<=m-1;i++) 
			  scanf("%s",a[i]);
	  while(a[startx][starty]=='#'||a[startx][starty]=='G')   //判断玩家的起点是否为空地,如果不是就重新输入;
	  {
		  printf("炸弹必须放置在空地,请重新输入(startx,starty):");
          scanf("%d%d",&startx,&starty);
	  }
	  head=1;        //初始化队列;
	  tail=1;
	  que[tail].x=startx;
	  que[tail].y=starty;
	  book[startx][starty]=1;  //对玩家起点进行标记,表示已经走过;
	  tail++;            //队尾扩展;
	  max=getnum(startx,starty);    统计起点所能消灭的敌人,调用getnum函数;
	  mx=startx;
	  my=starty;
	  while(head<tail)     //必须保证队列不为空;
	  {
		  for(k=0;k<=3;k++)    //分别尝试向上下左右进行移动,共四次不同的尝试;
		  {
			  tx=que[head].x+next[k][0];      //确定移动后的坐标;
			  ty=que[head].y+next[k][1];


			  if(tx<0||tx>m-1||ty<0||ty>n-1)    //判断玩家有没有走到地图外
				  continue;

			  if(a[tx][ty]==' . '&&book[tx][ty]==0)   //确保走到的地方为空地且没有走过;
			  {
				  book[tx][ty]=1;   //先标记为走过;
				  que[tail].x=tx;     //将该点坐标加入队列;
				  que[tail].y=ty;
				  tail++;           //扩展队列;
				  sum=getnum(tx,ty);    //计算该点消灭敌人的个数;
				  if(max<sum);            //如果该点消灭的敌人个数比之前的点的个数多,就把max更新为现在的点的个数;
				  {
					  max=sum;
					  mx=tx;
					  my=ty;
				  }
			  }
		  }
		  head++;       //队列扩展的是根据已入队的点相邻的点,当一个点的相邻点都扩展入队列后,则将这个点出队,这样才能保证后面的点也能入队;
	  }


	  printf("将炸弹放在x=%d,y=%d处,可以消灭%d个敌人\n",mx,my,max);
	  getchar();getchar();
	  return 0;
  }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值