打地鼠 Whack-a-mole

文章介绍了一个使用C++编程语言实现的打地鼠游戏解决方案,采用宽度优先搜索(BFS)算法来寻找在10步内解决游戏的策略。程序首先创建地图,然后根据用户输入的地鼠位置开始搜索,通过改变地鼠状态并更新搜索队列,最终找到最少步骤的敲地鼠顺序。如果找不到10步以内的解决方案,则表示游戏无法在规定步数内获胜。
摘要由CSDN通过智能技术生成

1. (简答题)

实战题:打地鼠

内容如附件所示:

Problem 5.pdf

测试数据为:1,2,4,8,9,10,11,14   答案为:10,2,4

原始分布:

击打10号    

 

击打2号   

  

击打4号

     

要求,所示实例解以图示的方式给出,并且5组测试数据都需要测试,还要有无解数据测试,及游戏方式(给出初始状态,由用户输入敲几号,给出变化状态)。代码要给详细注释并贴图上传,运行结果贴图上传,源文件做为附件上传。


   方法一:用宽搜

#include<bits/stdc++.h> 
using namespace std;
int g[5][5];	//初始状态 
int dx[5]={0,-1,0,1,0},dy[5]={0,0,1,0,-1};	//自身和周围四个格子 

struct node{
	int map[5][5];
	int step;		//敲了几只地鼠 
	int row[15];		//存储每次敲的位置所在行数 
	int col[15];		//存储每次敲的位置所在列数 
}st,ed,en;

void bfs(int x,int y)	//第一次敲的坐标 
{
	queue<node> q;			//创立一个结构体队列 
	st.step=1;				//敲的次数变为1 
	st.row[st.step]=x;	//存储敲的地鼠所在行数 
	st.col[st.step]=y;	//存储敲的地鼠所在列数 
	
	for(int i=1;i<=4;i++)	
		for(int j=1;j<=4;j++)
			st.map[i][j]=g[i][j];	//先将敲前的地图存储 
	
	for(int i=0;i<5;i++)
		if(x+dx[i]<=4&&x+dx[i]>0&&y+dy[i]<=4&&y+dy[i]>0)
			st.map[x+dx[i]][y+dy[i]]=1-g[x+dx[i]][y+dy[i]];//把敲的地鼠周围的状态进行改变 
	
	q.push(st);					//把这个结构体存入队列中 
	
	while(!q.empty())
	{
		st=q.front();			//将第一个结构体从队列中取出
		q.pop();				//取完后将队列中第一个元素删除 
		int flag=1;				//用于判断图中的地鼠是否都在地下 
	
		for(int j=1;j<=4;j++)
		{
			for(int k=1;k<=4;k++)	
				if(st.map[j][k])	//有至少一个地鼠在地上 
				{
					flag=0;			//判断标志变为0 
					break;			//结束循环 
				}
			if(!flag)
				break;
		}
		
		if(flag)				//地鼠全在地下 
		{							//用en存储st的step与格子,比较出step最小的走法 
			if(en.step>st.step)		//将当前敲的次数与之前所求的敲的次数相比较,若这次更小,则取代 
			{
				for(int z=1;z<=st.step;z++)	//存储每次敲的坐标 
				{
					en.row[z]=st.row[z];
					en.col[z]=st.col[z];
				}
				en.step=st.step;
			}
			return;	
		}
		if(st.step>=11)		//这个代码运算量太大,就限定不敲超过十只地鼠
			return;
		for(int j=1;j<=4;j++)
			for(int k=1;k<=4;k++)
			{
				if(st.map[j][k])		//寻找露头的地鼠 
				{
					ed.step=st.step+1;	//敲地鼠次数加1 
					for(int l=1;l<=4;l++)
						for(int m=1;m<=4;m++)
							ed.map[l][m]=st.map[l][m];	//将敲前的图存储到新结构体中 	
					for(int e=0;e<5;e++)
					{
						if(j+dx[e]<=4&&j+dx[e]>=1&&k+dy[e]<=4&&k+dy[e]>=1)	//找图内的点 
							ed.map[j+dx[e]][k+dy[e]]=1-ed.map[j+dx[e]][k+dy[e]];//将所敲地鼠及其周围四格状态进行改变 
					}
			
					for(int l=1;l<=st.step;l++)				//存储之前每次敲的位置 
					{
						ed.row[l]=st.row[l];
						ed.col[l]=st.col[l];
					}
					ed.row[ed.step]=j;
					ed.col[ed.step]=k;		//存储这次敲的位置 
					q.push(ed);
				}
			}
	}
}
int main()
{
	en.step=20;	//求10步以内的解,将初始步数设为大于10的数 
	cout<<"该敲地鼠游戏共有4x4个洞,每个洞各有一只地鼠,每个地鼠的序号如下图所示:"<<endl;
	int k=1;
	
	for(int i=4;i>=1;i--) 		//构建格子(初始地图) 
		for(int j=1;j<=4;j++)
		{
			g[i][j]=k;
			k++;
		}
		
	for(int i=1;i<=4;i++)
	{
		for(int j=1;j<=4;j++)
			printf("%3d",g[i][j]);			//展示序号 
		cout<<endl;
	}
	
	cout<<"该敲地鼠的规则如下: "<<endl;
	cout<<"在初始时有部分地鼠会将头露在洞口,玩家的任务是在十步内能将所有地鼠敲入洞中,否则游戏失败!"<<endl;
	cout<<"每次敲地鼠时,周围四格内露头的地鼠也会被吓回洞内,而原本在中的地鼠则会好奇地探出头来。"<<endl;
	cout<<"请输入在洞口中露头的地鼠的序号(输入0时代表输入完毕):"; 


	for(int i=1;i<=4;i++)
		for(int j=1;j<=4;j++)
			g[i][j]=0;		//初始化为每个地鼠都没露头 
	
	while(1)
	{
		int x;
		cin>>x;
		if(x==0)
			break;
		if(x%4==0)					//例如16->4 15->3.xxx 所有要特判 
			g[5-x/4][4]=1;			//将输入的序号所指示的地鼠变为露头状态 
		else
			g[4-x/4][x%4]=1;
	}
	
	cout<<"数据载入成功,初始图如下(1代表地鼠露头,0代表地鼠没露头):"<<endl;
	
	for(int i=1;i<=4;i++)//输出 有地鼠的地图 
	{
		for(int j=1;j<=4;j++)
			cout<<g[i][j]<<" ";
		cout<<endl;
	}
	
	cout<<endl<<"正在计算玩家在十步内能否取得胜利!"<<endl;
	
	for(int i=1;i<=4;i++)    //bfs遍历 第一次锤地鼠的格子 
	{
		for(int j=1;j<=4;j++)
		{
			if(g[i][j])
			{
				bfs(i,j);
			}
		}
	}
	
	if(en.step<=10)	//步数小于等于10说明有至少一个解 
	{
		cout<<"玩家在十步内可以取得胜利,敲的顺序为:";
		for(int i=1;i<=en.step;i++)
			cout<<4*(4-en.row[i])+en.col[i]<<" ";	//将坐标转换为序号输出 
	}
	else
		cout<<"玩家在十步内无法取得胜利!"<<endl;
		
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值