G(1856): Sokoban

Description

G
Soko-ban is a Japanese word for a warehouse worker, and the name of a classic computer game created in the 1980s. It is a one-player game with the following premise. A single worker is in an enclosed warehouse with one or more boxes. The goal is to move those boxes to a set of target locations, with the number of target locations equalling the number of boxes. The player indicates a direction of motion for the worker using the arrow keys (up, down, left, right), according to the following rules.

  • If the indicated direction of motion for the worker leads to an empty location (i.e., one that does not have a box or wall), the worker advances by one step in that direction.
  • If the indicated direction of motion would cause the worker to move into a box, and the location on the other side of the box is empty, then both the worker and the box move one spot in that direction (i.e., the worker pushes the box).
  • If the indicated direction of motion for a move would cause the worker to move into a wall, or to move into a box that has another box or a wall on its opposite side, then no motion takes place for that keystroke.

The goal is to simultaneously have all boxes on the target locations. In that case, the player is successful (and as a formality, all further keystrokes will be ignored). The game has been studied by computer scientists (in fact, one graduate student wrote his entire Ph.D. dissertation about the analysis of sokoban). Unfortunately, it turns out that finding a solution is very difficult in general, as it is both NP-hard and PSPACE-complete. Therefore, your goal will be a simpler task: simulating the progress of a game based upon a player's sequence of keystrokes. For the sake of input and output, we describe the state of a game using the following symbols:

Symbol Meaning
. empty space
# wall
+ empty target location
b box
B box on a target location
w worker
W worker on a target location

For example, the initial configuration diagrammed at the beginning of this problem appears as the first input case below.

Input

Each game begins with a line containing integers R and C, where 4 ≤ R ≤ 15 represents the number of rows, and 4 ≤ C ≤ 15 represents the number of columns. Next will be R lines representing the R rows from top to bottom, with each line having precisely C characters, from left-to-right. Finally, there is a line containing at most 50 characters describing the player's sequence of keystrokes, using the symbols U, D, L, and R respectively for up, down, left, and right. You must read that entire sequence from the input, even though a particular game might end successfully prior to the end of the sequence. The data set ends with the line 0 0.

We will guarantee that each game has precisely one worker, an equal number of boxes and locations, at least one initially misplaced box, and an outermost boundary consisting entirely of walls.

Output

For each game, you should first output a line identifying the game number, beginning at 1, and either the word complete or incomplete, designating whether or not the player successfully completed that game. Following that should be a representation of the final board configuration.

Sample Input

8 9
#########
#...#...#
#..bb.b.#
#...#w#.#
#...#b#.#
#...++++#
#...#..##
#########
ULRURDDDUULLDDD
6 7
#######
#..####
#.+.+.#
#.bb#w#
##....#
#######
DLLUDLULUURDRDDLUDRR
0 0

Sample Output

Game 1: incomplete
#########
#...#...#
#..bb...#
#...#.#.#
#...#.#.#
#...+W+B#
#...#b.##
#########
Game 2: complete
#######
#..####
#.B.B.#
#.w.#.#
##....#
#######

Hint

#include<iostream>
#include<string>
#include<vector>
using namespace std;
struct node{
	int x,y;
	node(int xx,int yy){
		x=xx,y=yy;
	}
	node(){}
};
vector<node> e;
char dir[]={'U','D','L','R'};
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
char maze[20][20];
int main(){
	int row,col,cnt=0;
	while(cin>>row>>col){
		if(row==0&&col==0) break;
		int i,j;node next,now;
		e.clear();
		for(i=0;i<row;i++)
		for(j=0;j<col;j++){
			cin>>maze[i][j];
			if(maze[i][j]=='+'||maze[i][j]=='W'||maze[i][j]=='B') e.push_back(node(i,j));  
			if(maze[i][j]=='w'||maze[i][j]=='W') now.x=i,now.y=j;
		}
		string str;cin>>str;
		bool flag=1;
		int len=str.length(); 
		for(i=0;i<len;i++){
			for(j=0;j<4;j++) if(str[i]==dir[j]) break;
			next.x=now.x+dx[j],next.y=now.y+dy[j];
			if(maze[next.x][next.y]=='#') continue;
			else if(maze[next.x][next.y]=='.'||maze[next.x][next.y]=='+') maze[next.x][next.y]='w',maze[now.x][now.y]='.',now=next;
			else {
				node temp(next.x+dx[j],next.y+dy[j]);
				if(maze[temp.x][temp.y]=='B'||maze[temp.x][temp.y]=='b'||maze[temp.x][temp.y]=='#') continue;
				else maze[temp.x][temp.y]='b',maze[next.x][next.y]='w',maze[now.x][now.y]='.',now=next;
			}
			flag=1;
			for(j=0;j<e.size();j++){
				if(maze[e[j].x][e[j].y]!='b'&&maze[e[j].x][e[j].y]!='B'){
					flag=0;break;
				}			
			}
			if(flag) break;
		}
		cout<<"Game "<<++cnt;
		if(flag) cout<<": complete"<<endl;
		else     cout<<": incomplete"<<endl;
		for(j=0;j<e.size();j++){
			 if(maze[e[j].x][e[j].y]=='b'||maze[e[j].x][e[j].y]=='B') maze[e[j].x][e[j].y]='B';
			 else if(maze[e[j].x][e[j].y]=='w') maze[e[j].x][e[j].y]='W';
			 else maze[e[j].x][e[j].y]='+';
		}
		for(i=0;i<row;i++){
			for(j=0;j<col;j++) cout<<maze[i][j];
			cout<<endl;
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值