推箱子c++实现代码

<p>c++  实验课的作业,话说这次算是我花的时间最长的实验课作业了,不过的确感觉自己对搜索的理解和编码能力提高了,作为一名初学者,我要学的东西还很多。。。</p><p>这次的实验是推箱子,自己YY了一个自动生成推箱子地图的算法,两重BFS,这大概也是我第一次把ACM的算法放到了实际应用中吧。下面上代码。。。。</p>
class Box
	{
	public :
		Box();
		void RandomMaze(int n);
	public :
		int x,y;
	};


class game
	{
	public:
		int WaitKey( double sec );
		void SetPos( int x, int y );
	};

typedef int Status;
typedef int ElemType;
//using namespace std;

class map
    {
    public:
        Status RandomMaze(int n,int m);
        Status PrintMaze(int n) ;
    public:
        int mazemap[20][20];
    };



//using namespace std;

class Vehicle
    {
    public:
        Vehicle();
        void show();
        void LoadMap(const char *a);
    public:
        int x,y;
    };



#include "Windows.h"
#include "game.h"
#include "ctime"
#include "conio.h"
using namespace std;

int game::WaitKey( double sec )
{
    clock_t tickStart = clock();
    clock_t tickEnd = tickStart + (clock_t)(sec * CLOCKS_PER_SEC);
    while(!kbhit())
    {
        // time out
        if( clock() >= tickEnd)
            return 0;
        Sleep(sec / 100.0); // wait
    }
    return getch();
}


void game::SetPos( int x, int y )
{
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD cursorPos = {x, y};
    SetConsoleCursorPosition(hConsole, cursorPos);
}



#include "box.h"
#include "iostream"
#include "map.h"
#include "vehicle.h"
#include "ctime"
#include "Windows.h"
typedef int Status;
typedef int ElemType;

#define OK        1
#define ERROR     0
#define TRUE      1
#define FALSE     0
#define OVERFLOW -2


Status map::RandomMaze(int n,int m)
{
    int i,j,k;
    srand(time(NULL));
    for(i=0;i<n;i++)
        mazemap[0][i]=mazemap[n-1][i]=1;
    for(j=0;j<n;j++)
        mazemap[j][0]=mazemap[j][n-1]=1;
    for(i=1;i<n-1;i++)
        for(j=1;j<n-1;j++)
        {
            k=rand()%6;    //随机生成整张的地图
            if(k==0)
                mazemap[i][j]=1;
            else
                mazemap[i][j]=0;
        }
	/*
	for(i=1;i<=m;i++)
		{
			int rand_x=rand()%19;
			int rand_y=rand()%19;
			if(rand_x>=1&&rand_y>=1)
				{
					mazemap[rand_x][rand_y]=-1;    //随机生成箱子的位置
				}
			else
				i--;
		}*/
	/*
	for(i=1;i<=m;i++)
		{
			int rand_x=rand()%19;
			int rand_y=rand()%19;
			if(rand_x>=1&&rand_y>=1)
				{
					mazemap[rand_x][rand_y]=-3;   //随机生成箱子的目标位置
				}
			else
				i--;
		}*/
    mazemap[1][0]=mazemap[1][1]=0;//标记入口出口
    return OK;
}

Status map::PrintMaze(int n)                //打印最后的足迹
{
    //printf("路径如下:\n");
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(mazemap[i][j]==0)
                printf("  ");       //代表可以走的位置
            if(mazemap[i][j]==1)
                printf("■");    // 代表墙壁
            if(mazemap[i][j]==-1||mazemap[i][j]==-4)
                printf("□");    // 代表箱子
            if(mazemap[i][j]==-2) 
                printf("○");    //代表推箱子的人
			if(mazemap[i][j]==-3)
				printf("◎");     //代表箱子的目标位置
			if(mazemap[i][j]==5)
				printf("☆");
        }
        printf("\n");
    }
     printf("\n");
    return OK;
}


#include "box.h"
#include "map.h"
#include "vehicle.h"
#include "cstring"
#include "iostream"
using namespace std;


Vehicle :: Vehicle ():x(0),y(0){};
void  Vehicle :: LoadMap(const char *a)
    {
    if(strcmp(a,"left")==0)
        {
        y--;
        }
    if(strcmp(a,"right")==0)
        {
        y++;
        }
    if(strcmp(a,"up")==0)
        {
        x--;
        }
    if(strcmp(a,"down")==0)
        {
        x++;
        }
    };
void Vehicle::show()
    {
    cout<<"<"<<x<<","<<y<<">"<<endl;
    };

#pragma once
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "conio.h"
#include "ctime"
#include "windows.h"
#include "iostream"
#include "stdlib.h"
#include "queue"
#include "vector"
#include "map.h"
#include "vehicle.h"
#include "box.h"
#include "game.h"
//#include "Clannad.h"
using namespace std;

#define INF 1<<27
#define OK        1
#define ERROR     0
#define TRUE      1
#define FALSE     0
#define OVERFLOW -2
#define INIT_STACK_SIZE 100
#define INCREASESIZE    10

const int MAX_X = INF;
const int MAX_Y = INF;
const int MAX_N = 1000;

typedef int Status;
typedef int ElemType;
typedef pair <int,int>P;

//bool used[MAX_X][MAX_Y];

map A;
Vehicle V;
Box B[];
game C;

int dir[4][3]={{0,1},{0,-1},{1,0},{-1,0}};
bool  used[1000][1000];
/*
bool dfs_judge(int final_x,int final_y)    //上次用的dfs时间复杂度太高了。。。。所以换成了bfs
    {
    if(final_x==1&&final_y==0)
        return true;
    for(int i=0;i<=3;i++)
        {
        int xx=final_x+dir[i][0],yy=final_y+dir[i][1];
        if(A.mazemap[xx][yy]!=1&&!used[xx][yy])
            {
            used[xx][yy]=1;
            if(dfs_judge(xx,yy))
                return true;
            used[xx][yy]=0;
            }
        }
    return false;
    }*/

bool bfs_judge_bypeople(int final_x,int final_y)      //第一重bfs
	{
		queue<P>que;
		memset (used,0,sizeof(used));
		used[final_x][final_y]=true;
		que.push(P(final_x,final_y));
		//int cnt=0;
		while(!que.empty())
			{
				P p=que.front();
				que.pop();
				if(p.first==1&&p.second==0)
					return true;
				for(int i=0;i<=3;i++)
					{
					int nx=p.first+dir[i][0],ny=p.second+dir[i][1];
					if(A.mazemap[nx][ny]!=1&&!used[nx][ny])
                        {
						que.push(P(nx,ny));
                        used[nx][ny]=true;
                        }
					}
			}
		return false;
	}

struct node
	{
		int first,second,direction;      //用于储存坐标值和上一次的方向
		node(){}
		node(int a,int b,int c) { first=a;second=b;direction=c;}
	};

bool bfs_judge_bycase(int m)    //第二重bfs
	{
	for(int i=1;i<=m;i++)
		{
			int rand_x=rand()%19,rand_y=rand()%19,rand_c=rand()%19,rand_d=rand()%19;
			if(rand_x==rand_c&&rand_y==rand_d)
				{
				i--;
				continue;
				}
			if(rand_x>1&&rand_y>1&&bfs_judge_bypeople(rand_x,rand_y)&&rand_c>1&&rand_d>1&&A.mazemap[rand_c][rand_d]==0)
				{
				A.mazemap[rand_x][rand_y]=-1;    //随机生成箱子的位置
				A.mazemap[rand_c][rand_d]=-3;   //随机生成箱子的目标位置
				}             //构建一个箱子和目标位置的组合
			else
				{
				i--;
				continue;
				}
			memset(used,0,sizeof(used));
			used[rand_c][rand_d]=true;
			queue<node>que;
			que.push(node(rand_c,rand_d,0));     //逆推。。。。。
			bool judge=false;
			while(!que.empty())
				{
					node p = que.front();
					que.pop();
					if(A.mazemap[p.first][p.second]==-1)
						{
						//A.PrintMaze(20);
						if(!bfs_judge_bypeople(p.first+dir[p.direction][0],p.second+dir[p.direction][1]))
							continue;
						A.mazemap[p.first][p.second]=-4;
						judge=true;
						break;
						}				
					for(int j=0;j<=3;j++)
						{
						int nx=p.first+dir[j][0],ny=p.second+dir[j][1];
						if((A.mazemap[nx][ny]==-1||A.mazemap[nx][ny]==0)&&!used[nx][ny]&&A.mazemap[nx+dir[j][0]][ny+dir[j][1]]==0)
							{
							que.push(node(nx,ny,j));        //同时考虑推箱子时候人的位置
							used[nx][ny]=true;
							}
						}
				}
			if(judge==false)
				{
				A.mazemap[rand_x][rand_y]=0; 
				A.mazemap[rand_c][rand_d]=0; 
				i--;
				continue;
				}
		}
	return true;
	}
void delete_by_position(int n)
	{
	 for(int i=0;i<n;i++)
		{
        for(int j=0;j<n;j++)
			{
			if(A.mazemap[i][j]==-1||A.mazemap[i][j]==-4||A.mazemap[i][j]==-2)
				{
					C.SetPos((j)*2,i);
					printf("  ");    
				}
			}
		}
	}

void create_by_position(int n)
	{
	 for(int i=0;i<n;i++)
		{
        for(int j=0;j<n;j++)
			{
            if(A.mazemap[i][j]==-1||A.mazemap[i][j]==-4)
				{
					C.SetPos((j)*2,i);
					printf("□");    // 代表箱子
				}
            if(A.mazemap[i][j]==-2) 
                {
					C.SetPos((j)*2,i);
					printf("○");    // 代表人的位置
				}  //代表推箱子的人
			if(A.mazemap[i][j]==5)
				{
					C.SetPos((j)*2,i);
					printf("☆");    //代表箱子的目标位置已经成功
				}
			}
		}
	}

int main(void)
    {
	printf("====请问要从上一关开始吗?==\n=需要输入1...不需要输入0======\n");
	int judge_bynumber;
	int n=20;
	scanf("%d",&judge_bynumber);
	int m;
	int cnt=0;
	if(judge_bynumber==1)
		{
		freopen("hehe.in","r",stdin);
		C.SetPos(0,0);
		for(int i=0;i<n;i++)
			{
			for(int j=0;j<n;j++)
				scanf("%d",&A.mazemap[i][j]);
			}
		scanf("%d",&m);
		scanf("%d%d%d",&V.x,&V.y,&cnt);
		fclose(stdin);
		}
	else
		{
		printf("=========请输入要的箱子数====\n");
		scanf("%d",&m);
		printf("=============地图规模为20*20======\n");
		//scanf("%d",&n);
		printf("=======请耐心等待地图生成======\n");
		printf("=======地图生成如果太久请重试======\n");
		do
			{
			//memset(used,0,sizeof(used));
			A.RandomMaze(n,m);   //生成迷宫地图
			//B.RandomMaze(n);
			//A.PrintMaze(n);
			}while(!bfs_judge_bypeople(n-2,n-1));  //广度优先搜素以保证迷宫不被堵住 (上次的深搜太费时了。。。)
		//A.PrintMaze(n);
		//A.PrintMaze(n);
		bfs_judge_bycase(m);   //采用了两重bfs。。。。保证迷宫一定可解。。。QWQ。。QWQ。。QWQ。。QWQ。。QWQ。。QWQ。。QWQ。。QWQ。。QWQ。。QWQ
		//A.PrintMaze(n);
		A.mazemap[1][0]=-2;    
		V.x=1;
		V.y=0;
		cnt=0;
		}
	C.SetPos(0,0);
    A.PrintMaze(n);                           //打印迷宫地图
    printf("\n==================迷宫.......==================");
    printf("\n说明:■不能走的区域\t◇走不通的区域");
    printf("\n    “空格”代表未到过的区域");
    printf("\n     ○代表您的所在位置");
    printf("\n     □代表箱子的位置  ");
	printf("\n     ◎代表箱子的目标位置");
	printf("\n     ☆代表已经成功的目标位置");
	printf("\n      按s键存档。。。。");
    printf("把所有的箱子推到位就算您的胜利n(*≧▽≦*)n");
    printf("\n============================================\n");
    while(1)
        {
		if(cnt==m)
			{
			C.SetPos(0,n+1);
            printf("========您太厉害了n(*≧▽≦*)n=======\n");
			break;
			}
        int k=C.WaitKey(10.0);
        if(k==224||k==0)
            continue;
		if(k==115)
			{
			freopen("hehe.in","w",stdout);
			for(int i=0;i<n;i++)
				{
				for(int j=0;j<n;j++)
					{
						printf("%d ",A.mazemap[i][j]);
					}
				printf("\n");
				}
			printf("%d %d %d %d",m,V.x,V.y,cnt);
			fclose(stdout);

			C.SetPos(0,n+1);
            //printf("========存档成功!(*≧▽≦*)=======\n");
			
			break;
			}
		if(k!=75&&k!=77&k!=72&&k!=80)
			continue;
        //printf("%d",k);
		delete_by_position(n);
        if(k==75&&A.mazemap[V.x][V.y-1]!=1)     //left
            {
				if(A.mazemap[V.x][V.y-1]==-1||A.mazemap[V.x][V.y-1]==-4)
					{
						if(A.mazemap[V.x][V.y-2]==0)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x][V.y-1]=-2;
								A.mazemap[V.x][V.y-2]=-4;
								V.LoadMap("left");
								create_by_position(n);
								C.SetPos(0,n+1);   //默默的重置了坐标。。。。只是为了输出。。。。
								continue;								
							}
						if(A.mazemap[V.x][V.y-2]==-3)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x][V.y-1]=-2;
								A.mazemap[V.x][V.y-2]=5;
								cnt++;
								V.LoadMap("left");
								create_by_position(n);
								C.SetPos(0,n+1);
								continue;
								
							}
						else
							{
							create_by_position(n);
							C.SetPos(0,n+1);
							continue;							
							}
					}
				else if(A.mazemap[V.x][V.y-1]==0)
					{
					A.mazemap[V.x][V.y]=0;
					A.mazemap[V.x][V.y-1]=-2;
					V.LoadMap("left");
					create_by_position(n);
					C.SetPos(0,n+1);
					continue;					
					}                //其实还有一种人踩到目标位置的情况。。。。懒了。。。。直接简化了。。。。
            }
        else if(k==77&&A.mazemap[V.x][V.y+1]!=1)    //right
            {
            if(A.mazemap[V.x][V.y+1]==-1||A.mazemap[V.x][V.y+1]==-4)
					{
						if(A.mazemap[V.x][V.y+2]==0)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x][V.y+1]=-2;
								A.mazemap[V.x][V.y+2]=-4;
								V.LoadMap("right");
								create_by_position(n);
								C.SetPos(0,n+1);
								continue;								
							}
						if(A.mazemap[V.x][V.y+2]==-3)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x][V.y+1]=-2;
								A.mazemap[V.x][V.y+2]=5;
								cnt++;
								V.LoadMap("right");
								create_by_position(n);
								C.SetPos(0,n+1);
								continue;								
							}
						else
							{
							create_by_position(n);
							C.SetPos(0,n+1);
							continue;							
							}
					}
				else if(A.mazemap[V.x][V.y+1]==0)
					{
					A.mazemap[V.x][V.y]=0;
					A.mazemap[V.x][V.y+1]=-2;
					V.LoadMap("right");
					create_by_position(n);
					C.SetPos(0,n+1);
					continue;					
					}
            }
        else if(k==72&&A.mazemap[V.x-1][V.y]!=1)    //up
            {
           if(A.mazemap[V.x-1][V.y]==-1||A.mazemap[V.x-1][V.y]==-4)
					{
						if(A.mazemap[V.x-2][V.y]==0)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x-1][V.y]=-2;
								A.mazemap[V.x-2][V.y]=-4;
								V.LoadMap("up");
								create_by_position(n);
								C.SetPos(0,n+1);                //默默的重置了坐标。。。。只是为了输出。。。。
								continue;							
							}
						if(A.mazemap[V.x-2][V.y]==-3)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x-1][V.y]=-2;
								A.mazemap[V.x-2][V.y]=5;
								cnt++;
								V.LoadMap("up");
								create_by_position(n);
								C.SetPos(0,n+1);
								continue;								
							}
						else
							{
							create_by_position(n);
							C.SetPos(0,n+1);
							continue;							
							}
					}
			else if(A.mazemap[V.x-1][V.y]==0)
					{
					A.mazemap[V.x][V.y]=0;
					A.mazemap[V.x-1][V.y]=-2;
					V.LoadMap("up");
					create_by_position(n);
					C.SetPos(0,n+1);
					continue;					
					}
            }
        else if(k==80&&A.mazemap[V.x+1][V.y]!=1)     //down
            {
           if(A.mazemap[V.x+1][V.y]==-1||A.mazemap[V.x+1][V.y]==-4)
					{
						if(A.mazemap[V.x+2][V.y]==0)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x+1][V.y]=-2;
								A.mazemap[V.x+2][V.y]=-4;
								V.LoadMap("down");
								create_by_position(n);
								C.SetPos(0,n+1);
								continue;								
							}
						if(A.mazemap[V.x+2][V.y]==-3)
							{
								A.mazemap[V.x][V.y]=0;
								A.mazemap[V.x+1][V.y]=-2;
								A.mazemap[V.x+2][V.y]=5;
								V.LoadMap("down");
								cnt++;
								create_by_position(n);
								C.SetPos(0,n+1);
								continue;								
							}
						else
							{
							create_by_position(n);
							C.SetPos(0,n+1);
							continue;							
							}
					}
				else if(A.mazemap[V.x+1][V.y]==0)
					{
					A.mazemap[V.x][V.y]=0;
					A.mazemap[V.x+1][V.y]=-2;
					V.LoadMap("down");
					create_by_position(n);
					C.SetPos(0,n+1);
					continue;					
					}
            }
		else
			create_by_position(n);
        C.SetPos(0,n+1);
		//SetPos((V.y)*2,V.x);
		//printf("○");
        //A.PrintMaze(n);
        /*if(V.x==n-2&&V.y==n-1)
            {
            printf("\n");
			
            //system("pause");
            getchar();
            getchar();
            break;
            }*/

        }
    return 0;
    }

其实代码还是很丑的说。。。。

                                    
展开阅读全文
博主设置当前文章不允许评论。

没有更多推荐了,返回首页