课程设计推箱子(可以自动推箱子)

博客链接

自动推箱子部分使用双重bfs实现,注释有点多,代码有点乱见谅

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define N 101
using namespace std;
char map[N][N];
char YON;
int  show, judge, boom, ph, addb, endgame;
int stax, stay, boxx, boxy, endx, endy, addbx, addby;
int vis[N][N][4], flag[N][N]; // vis用来保存箱子和人的状态
int i, j, step, n, m, showtime, cnt;
int dir[4][2]={-1,0,1,0,0,-1,0,1};
char P[4]= {'W','S','A','D'}; // w,a,s,d分别对应键盘是的按键 
char M[4]= {'w','s','a','d'};
string temp, res;
struct Node
{
    int x,y;
    int px,py;
    string ans;
};
int check(int x,int y) // 边界检查 
{
    if(x < 1 || x > n || y < 1 || y > n || map[x][y] == 5) 
		return 0;
    return 1;
}
queueq;
queueque;
/*
	用嵌套BFS,外层BFS是找从箱子到终点找一条箱子移动的路径,用内层BFS来判断人能否从上一个点走到这一个点 .	
	箱子是可以经过一个点多次的,但是同一个点移动往同一个方向只能一次
*/
int bfs_person(Node a,Node c) // 搜索人的位置 
{
    memset(flag,0,sizeof(flag));
    Node next,b;
    b.x=a.px, b.y=a.py;
    b.ans="";
    while(!q.empty()) // 清空队列
        q.pop();
    q.push(b);
    flag[b.x][b.y]=1;
    while(!q.empty())
    {
        Node now=q.front();
        q.pop();
        if(now.x==a.x&&now.y==a.y)
        {
            temp=now.ans;
            return 1;
        }
        for(int i=0; i<4; i++) // 搜索玩家的4个方向
        {
            next=now;
            next.x+=dir[i][0];
            next.y+=dir[i][1];
            if(!check(next.x,next.y)||(next.x==c.x&&next.y==c.y)) continue;
            if(flag[next.x][next.y]) continue;
            flag[next.x][next.y]=1;
            next.ans=now.ans+M[i]; // 如果是可行解则把M中的方向键加入字符串中 
            q.push(next);
        }
    }
    return 0;
}
string bfs_box() // 搜索箱子的位置 
{
    Node next,pre;
    Node st;
    memset(vis,0,sizeof(vis));
    st.ans = "";
    st.px = stax;  // 玩家位置 
    st.py = stay;
    st.x = boxx;  // 箱子位置 
    st.y = boxy;
    while(!que.empty()) // 清空队列 
        que.pop();
    que.push(st);
    while(!que.empty())
    {
        Node now = que.front();
        que.pop();
        if(map[now.x][now.y] == 4) // 当箱子到达终点时 
            return now.ans;
        for(i=0; i < 4; i++)  // 搜索箱子的4个方向 
        {
            next = now;
            next.x += dir[i][0];
            next.y += dir[i][1];
            if(!check(next.x, next.y) || vis[next.x][next.y][i]) 
				continue;
            pre=now;
            if(i == 0) 
				pre.x = pre.x + 1;
            else if(i == 1) 
				pre.x = pre.x - 1;
            else if(i == 2) 
				pre.y = pre.y + 1;
            else if(i == 3) 
				pre.y = pre.y - 1;
            if(!check(pre.px, pre.py) || !bfs_person(pre, now)) 
				continue;
            vis[next.x][next.y][i] = 1;
            next.ans = now.ans + temp;
            next.ans = next.ans + P[i]; // 如果是可行解则把P中的方向键加入字符串中
            next.px = now.x;
			next.py = now.y;
            que.push(next);
        }
    }
    return "-1"; // 无解返回-1 
}
void gotoxy(int x,int y) // 将光标移动到指定坐标 
{
	COORD pos = {x,y};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOut,pos);
}
void color(int x) // 给文字上色 
{
	if(x >= 0 && x <= 15)
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x);
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7);	
}
void createmap() // 随机生成地图
{
	int wall[N][N];
	srand(time(NULL));
	for(i=0;i> n;
		if(n > 100)
			cout << "输入错误请重新输入:";
	}while(n > 100);
	cout << "请输入一个数来决定障碍物密度(输入的数字越小,障碍物越多,n>=4):";
	do
	{
		cin >> m;
		if(m < 4)
			cout << "输入错误请重新输入:";
	}while(m < 4);
	cout << "请输入一个数来决定地图中炸弹补给点的个数(n<=5):";
	do
	{
		cin >> addb;	
		if(addb > 5)
			cout << "输入错误请重新输入:";
	}while(addb > 5);
	cout << "地图太大,地图生成的速度可能会很慢";
}
void tips() // 提示栏 
{
	gotoxy(n+2,0);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-"; 
	gotoxy(n+2,1);
	color(2);
	printf("'%c'为小人(玩家可以通过键盘的w,s,a,d控制)",1);
	gotoxy(n+2,2);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,3);
	color(2);
	printf("'%c'为箱子(玩家可以推动,但不可以拉)",3);
	gotoxy(n+2,4);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,5);
	color(2);
	printf("'%c'为墙体(玩家和箱子都不可以穿过)",5);
	gotoxy(n+2,6);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,7);
	color(2);
	printf("'%c'为炸弹补给点,到达该地方炸弹数量+2",6);
	gotoxy(n+2,8);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,9);
	color(2);
	printf("'.'为自动寻路时玩家和箱子的路径");
	gotoxy(n+2,10);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,11);
	color(2);
	printf("' '为玩家和箱子都可以通过的地方"); 
	gotoxy(n+2,12);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,13);
	color(2);
	cout << "按下h自动寻路";
	gotoxy(n+2,14);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,15);
	color(2);
	cout << "按下p判断当前是否有解";
	gotoxy(n+2,16);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,17);
	color(2);
	cout << "按下b破坏周围墙体"; 
	gotoxy(n+2,18);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
	gotoxy(n+2,19);
	color(2);
	cout << "按下q提前结束游戏";
	gotoxy(n+2,20);
	color(3);
	cout << "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-";
}
void ismap() // 地图一定有解 
{
	do // 用do--while可以先随机生成一次地图,如果不符合则继续生成 
	{
		createmap(); 
		createbox();
		addboom();
		cnt++;
		res = bfs_box();
		if(res == "-1")
		{
			for(i=0;i 0)
	{
		map[stax-1][stay] = 0;
		map[stax+1][stay] = 0;
		map[stax][stay-1] = 0;
		map[stax][stay+1] = 0;
		map[stax-1][stay-1] = 0;
		map[stax+1][stay-1] = 0;
		map[stax-1][stay+1] = 0;
		map[stax+1][stay+1] = 0;
		boom--;
	}
	else
	{
		gotoxy(n+2,21);
		color(4);
		cout << "你的炸弹用完了,输入任意键继续游戏......";
		getch(); 
	}
}
int main()
{
	while(1)
	{
		system("cls"); // 如果开始游戏则清屏 
		// 各个变量初始化 
		endgame = 0;
		ph = 0;
		judge = 0;
		show = 0;
		cnt = 0;
		stax = 1;
		stay = 1; 
		showtime = 100;
		res = "";
		memset(map,0,sizeof(map));
		menu();
		ismap();
		while(1) // 游戏主题部分 
		{
			system("cls");
			color(8);
			drawmap(); // 打印地图 
			tips();
			gotoxy(stay,stax); // 打印玩家符号 
			color(5);
			printf("%c",1);
			gotoxy(boxy,boxx); // 打印箱子符号 
			color(4);
			printf("%c",3);
			// 以下是打印一些游戏提示 
			gotoxy(0,n+1);
			color(7);
			cout << "当前移动步数:" << step;
			gotoxy(0,n+2);
			color(7);
			cout << "当前玩家坐标:" << '(' << stax << ',' << stay << ')';
			gotoxy(0,n+3);
			color(7);
			cout << "生成地图数:" << cnt << endl;
			gotoxy(0,n+4);
			color(7);
			cout << "炸弹剩余数:";
			for(i=0;i> showtime; 
				automove(res);
				// 初始化
				showtime = 100;
				show = 0; 
			} 
			gotoxy(0,n+8); 
			// 判断游戏胜利或者失败
			if(res == "-1")
			{
				cout << "你失败了,是否开始新的游戏Y/N?"; 
				cin >> YON ;
				YON = tolower(YON);
				break;
			}
			if(boxx == endx && boxy == endy)
			{
				cout << "你赢了,是否开始新的游戏Y/N?";
				cin >> YON;
				YON = tolower(YON);
				break;
			}
			if(endgame == 1)
			{
				cout << "你提前结束了游戏,是否开始新的游戏Y/N?";
				cin >> YON;
				YON = tolower(YON);
				break;
			}
		}
		if(YON == 'n') // 判断是否需要开始新的游戏  
			break;
		if(YON == 'y')
			continue;
	}
}

你可能感兴趣的:(c语言,推箱子,双重bfs,寻路算法)