洛谷P2346四子连棋 关于启发式搜索A*

结合网上题解,代码思路:

1、输入时将字符型转为整数型;

2、将黑白棋子移动转换为将空白格子为中心向四周判断黑白棋子是否可以移动

3、写check()函数判断是否有四棋连线情况,如果有则返回当前状态的步数,不然继续搜索下一步;

4、写bfs()函数先找到每个状态时空白格的位置,以空白格为中心向四周判断,如果板块有效、颜色有效则交换;要写完整四种情况

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct node{
	int map[5][5];
	int flag;//-1让白棋走,1让黑棋走 
	int step; 
};
node s;
int x[] = {1,-1,0,0};
int y[] = {0,0,1,-1};
queue<node> q;

int check(node temp)//当前状态下看有没有四子连棋 
{
	int i,j,k;
	for(int i = 1; i <= 4; i ++){
		//水平 
		if(temp.map[i][1] == temp.map[i][2] && temp.map[i][2] == temp.map[i][3] && temp.map[i][3] == temp.map[i][4])
			return 1;
		//竖直 
		if(temp.map[1][i] == temp.map[2][i] && temp.map[2][i] == temp.map[3][i] && temp.map[3][i] == temp.map[4][i])
			return 1;	
	}
	//正斜线 
	if(temp.map[1][1] == temp.map[2][2] && temp.map[2][2] == temp.map[3][3]&& temp.map[3][3] == temp.map[4][4])
		return 1;
	//反斜线 
	if(temp.map[1][4] == temp.map[2][3] && temp.map[2][3] == temp.map[3][2] && temp.map[3][2] == temp.map[4][1])
		return 1; 
	//其他情况全返0 
	return 0; 
}

int bfs()
{
	int i,j,k;
	int x1,x2,y1,y2;//记录空格位置,每次移动后都不一样 
	int xx,yy;
	s.flag = 0;//初始谁走都行
	s.step= 0;
	q.push(s);//当前状态入队
	while(!q.empty()){
		node temp;
		temp = q.front();
		q.pop();
		if(check(temp)) return temp.step;
		
		x1 = -1;//用来区别第一个空格和第二个空格 
		for(int i=1;i<=4;i++){
			for(int j=1;j<=4;j++){
				if(temp.map[i][j] == 0 && x1 == -1){
					 x1 = i;
					 y1 = j;
				}
				else if(temp.map[i][j] == 0){
					x2 = i;
					y2 = j;
					break;//两个空格都找到了直接退出双for 
				}
			}
		} 
		
		node t;
		//黑棋走 ,相当于以空白格为中心找黑色棋交换位置 
		//四个方向
		for(int i=0;i<4;i++){
			if(temp.flag == -1)//轮到白棋了 
				break;
			
			xx = x1 + x[i];
			yy = y1 + y[i];
			if(xx >= 1 && xx <= 4 && yy >= 1 && yy <= 4 && temp.map[xx][yy] == 1){//此处是黑棋
				 t = temp;
				 swap(t.map[xx][yy],t.map[x1][y1]);
				 t.flag = -1;//下一步是白棋走
				 t.step ++;
				 if(check(t))	return t.step;
				 q.push(t);
			} 
		} 
		//黑棋在第二个空白格走
		for(int i=0;i<4;i++){
			if(temp.flag == -1) break;
			xx = x2 + x[i];
			yy = y2 + y[i];
			if(xx >= 1 && xx <= 4 && yy >= 1 && yy <= 4 && temp.map[xx][yy] == 1){
				t = temp;
				swap(t.map[xx][yy],t.map[x2][y2]);
				t.step ++;
				t.flag = -1;
				if(check(t)) return t.step;
				q.push(t);
			}
		} 
		//白棋与第一个空格
		for(int i=0;i<4;i++){
			if(temp.flag == 1) break;
			xx = x1 + x[i];
			yy = y1 + y[i];
			if(xx >= 1 && xx <= 4 && yy >= 1 && yy <= 4 && temp.map[xx][yy] == 2){
				t = temp;
				swap(t.map[xx][yy],t.map[x1][y1]);
				t.step ++;
				t.flag = 1;
				if(check(t)) return t.step;
				q.push(t);
			}
		} 
		//白棋与第二个空格
		for(int i=0;i<4;i++){
			if(temp.flag == 1) break;
			xx = x2 + x[i];
			yy = y2 + y[i];
			if(xx >= 1 && xx <= 4 && yy >= 1 && yy <=4 && temp.map[xx][yy] == 2){
				t = temp;
				swap(t.map[xx][yy],t.map[x2][y2]);
				t.flag = 1;
				t.step ++;
				if(check(t)) return t.step;
				q.push(t);
			}
		} 
	} 
} 
int main()
{
	char str[5];
	for(int i=1;i<=4;i++){
		scanf("%s",str+1);
		for(int j=1;j<=4;j++){
			if(str[j] == 'B') s.map[i][j] = 1;
			else if(str[j] == 'W') s.map[i][j] = 2;
			else s.map[i][j] = 0;
		}
	s.step = 0;
	}	
	printf("%d",bfs());
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值