UVa227:谜题(Puzzle)

题目:

题意:有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指令:A, B, L, R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“This puzzle has no final configuration.”如下图所示:分别为执行ARRBBL0前、后的效果图:在这里插入图片描述

Sample Input:
TRGSJ
XDOKI
M VLN
WPABE
UQHCF
ARRBBL0

ABCDE
FGHIJ
KLMNO
PQRS  
TUVWX
AAA
LLLL0

ABCDE
FGHIJ
KLMNO
PQRS 
TUVWX
AAAAABBRRRLL0

Z

Sample Output:
Puzzle #1:
T R G S J
X O K L I
M D V B N
W P   A E
U Q H C F

Puzzle #2:
  A B C D
F G H I E
K L M N J
P Q R S O
T U V W X

Puzzle #3:
This puzzle has no final configuration.

注意事项:

本题中不能简单的使用cin>>来读取数据:读取初始网格时,注意读取一行带有空格的指令;读取指令时,遇到“0”才截至,注意将多行读入的指令处理为一行指令。
cin.get():从输入缓冲区读取单个字符串,且不忽略分隔符。

cin.get(char *s, size_t n);
cin.get(char *s, size_t n, streamsize delim);

//读取一行,n为目标空间大小,delim指定结束符。

1. getline()的原型是(定义在istream中的成员函数)

cin.getline(char *s, size_t n);
   cin.getline(char *s, size_t n, char delim);

//读取一行,不会将结束符或者换行符残留在输入缓冲区。
cin>>:可连续从键盘读取想要的数据(以空格、tab或者换行作为风额符)。

2. getline()的原型是(定义在string头文件中的一个全局函数)

istream& getline ( istream &is , string &str );
  istream& getline ( istream &is , string &str , char delim );

//istream &is 表示一个输入流,譬如cin;string&str表示把从输入流读入的字符串存放在这个字符串中;char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为’\n’,也就是回车换行符。

编程总结:

  1. 为重复实现的功能编写小函数调用:如,在执行每一步指令时,可以调用执行一步指令的函数;
  2. 处理读入的网格数组中的空格,分行将读入的字符串写入到网格数组中;
  3. “全局变量”与“局部变量”的处理:将5*5网格存储为全局变量,方便函数的处理;

程序代码:

#include<iostream>
#include<string>
using namespace std;

//全局变量:存放5*5网格相关数据
char puzzle[6][6];//存放网格数组
int x0, y0;//存放空格的位置(下标从0开始),第x行,第y列

//将读入的一串字符串分别存储到网格数组中去
void read(int row, string str) {
	for (int i = 0; i < 5; i++) {
		puzzle[row][i] = str[i];
		if (str[i] == ' ') {
			x0 = row;
			y0 = i;
		}
	}
}

bool move(char order) {
	int x, y;//移动后空格的坐标
	switch (order)
	{
		//上
	case 'A':
		x = x0 - 1; y = y0;
		break;
		//下
	case 'B':
		x = x0 + 1; y = y0;
		break;
		//左
	case 'L':
		x = x0; y = y0 - 1;
		break;
		//右
	case 'R':
		x = x0; y = y0 + 1;
		break;
	default:
		break;
	}

	if ((x >= 0 && x <= 4) && (y >= 0 && y <= 4)) {
		puzzle[x0][y0] = puzzle[x][y];
		puzzle[x][y] = ' ';
		x0 = x; y0 = y;

		return true;
	}
	else {
		return false;
	}
}


int main()
{
	string order;//存放指令序列
	string str;//输入网格数组时的中间存储量
	int icase = 0;//求解问题的次数

	while (1) {
		if (icase != 0)
			cin.get();//读取掉输入缓冲区的换行符

		//读取一行字符并处理 
		getline(cin, str);
		if (str[0] == 'Z')
			break;

		//不同样例间换行
		if (icase != 0)
			cout << endl;

		read(0, str);
		for (int i = 1; i <= 4; i++) {
			getline(cin, str);
			read(i, str);
		}

		//读取指令序列
		order.clear();
		int len;
		while (true) {
			string temp;
			cin >> temp;

			order += temp;
			len = order.length();

			if (order[len - 1] == '0')
				break;
		}

		//看是否有解
		bool has_result = true;
		for (int i = 0; i < len - 1; i++) {
			if (move(order[i]) == false) {
				has_result = false;
				break;
			}
		}

		cout << "Puzzle #" << ++icase << ":" << endl;

		if (has_result) {
			for (int i = 0; i < 5; i++) {
				for (int j = 0; j < 4; j++) {
					cout << puzzle[i][j] << " ";
				}
				cout << puzzle[i][4] << endl;
			}

		}
		else {
			cout << "This puzzle has no final configuration." << endl;
		}
	}

	system("pause");
	return  0;
}