当前位置:   article > 正文

C++实验2 控制结构和数组_7. 设有如下结构的移动将牌游戏:其中, b 表示黑色将牌, w 表是白色将牌, e 表示空

7. 设有如下结构的移动将牌游戏:其中, b 表示黑色将牌, w 表是白色将牌, e 表示空

实验二 控制结构和数组

1 实验目的
(1)灵活掌握控制结构及其逻辑特点,学会逐步求精的算法设计。
(2)学习如何把逻辑结构相同的部分抽象为函数,以提高代码的可重用性,
达到提高程序的可维护性的目的。
(3)学习使用数组作为函数参数的方法。
2 实验内容


2.1 打印温度柱状图
(1)问题描述
下图是某城市 15 天的气温变化曲线。其中标注为 A 的地方称为峰点,标记
为 B 的地方称为谷点,而标记为 C 的地方称为崮。要求编写 1 个函数输入 15 天
的气温,然后通过 3 个函数分别实现下述功能:
(1)打印每天温度的柱状图(仅考虑温度为正值的情况)。
(2)打印所有峰点的位置(该月的第几天)及峰值。如果没有,则打印没
有峰值。
(3)打印最长的崮的长度。只使用一重循环即可求出。
在这里插入图片描述
(2)问题要求
请实现以下函数声明,要求能得到如下图所示的运行结果。
在这里插入图片描述

在这里插入图片描述
源代码

/***********************************************
 文件名:WeatherForecast.cpp
 概要:  模拟天气预报,一个月的温度分析
 函数:
 1. displayTemp,显示月间温度的柱状图
 2. displayPeaks,显示月间温度中的峰值
 3. displayFlat,显示月间持续最久的温度
 4. forecasting,接收用户输入,
 调用上面的3个函数
 ************************************************/

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

int minTemp(int temp[], int n) {
	int min = temp[0];
	for (int i = 1; i < n; i++) {
		if (min > temp[i])
			min = temp[i];
	}

	return min;
}

// 显示柱状图
void displayTemp(int temp[], int n) {
	int min = minTemp(temp, n); // 先求出最低温度

	for (int i = 0; i < n; i++) {
		if (min < 0) {// 存在零下温度的时候,最低温度小于零
			cout << setw(4) << temp[i] << "  ";
			if (temp[i] < 0) {
				for (int j = 0; j < temp[i] - min; j++)
					cout << " ";
				for (int k = temp[i]; k < 0; k++)
					cout << "*";
				cout << "|" << endl;
			} else {
				for (int j = min; j < 0; j++)
					cout << " ";
				cout << "|";
				for (int k = 0; k < temp[i]; k++)
					cout << "*";
				cout << endl;
			}
		} else { // 不存在零下温度的时候
			cout << setw(4) << temp[i] << "  |";
			for (int j = 0; j < temp[i]; j++)
				cout << "*";
			cout << endl;
		}
	}
}

// 显示月间温度中的峰值
void displayPeaks(int temp[], int n) {
	bool flag = false;

	for (int i = 1; i < n - 1; i++) {
		if (temp[i - 1] < temp[i] && temp[i] > temp[i + 1]) {
			flag = true;
			cout << "Peak at day " << i + 1 << " is " << temp[i] << endl;
		}
	}

	if (!flag)
		cout << "No peaks." << endl;
}

// 显示月间持续最久的温度
void displayFlat(int temp[], int n) {
	int length = 1;
	int maxLength = 0;

	for (int i = 1; i < n; i++) {
		if (temp[i - 1] == temp[i])
			length++;
		else {
			if (length > maxLength)
				maxLength = length;
			length = 1;
		}
	}

	// 处理最长崮在最后的情况
	if (length > maxLength)
		maxLength = length;

	cout << "The length of longest flat is " << maxLength << endl;
}

int main() {
	int temp[15]; // 存储 15 天的温度

	cout << "Please input the tempratures:\n";

	// 输入 15 天的温度
	for (int i = 0; i < 15; i++)
		cin >> temp[i];

	cout << "\n显示柱状图如下:\n";
	displayTemp(temp, 15); // 显示柱状图

	cout << "\n显示峰值如下:\n";
	displayPeaks(temp, 15); // 求出所有的峰值温度

	cout << "\n显示崮的长度如下:\n";
	displayFlat(temp, 15); // 求出持续时间最长的温度

	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

2.2 滑动积木块游戏
(1)问题描述
滑动积木块游戏的棋盘结构及某一种将牌的初始排列结构如图所示。
在这里插入图片描述

其中,B 表示黑色将牌,W 表示白色将牌,E 表示空格。我们称将牌的排列
结构称为格局,而根据单色将牌的个数,将游戏分别称为 3 滑块或 4 滑块游戏等。
所以,上图就是 3 滑块游戏的初始格局。我们可以用字符串来代表格局,代表上
图中初始格局的字符串为 BBBWWWE。
游戏的规定走法是:
(1)任意一个将牌可以移入相邻的空格;
(2)任意一个将牌可相隔 1 个或 2 个其他的将牌跳入空格。
游戏要达到的目标是使所有白将牌都处在黑将牌的左边(左边有无空格均可),我们称为目标格局。很显然,3 滑块游戏的目标格局共有 7 种。
随着将牌的移动,我们会得到一些中间格局,例如:
滑块游戏的某个中间格局
对于某个格局,通过一次移动滑块而得到的格局,称为其后继格局。我们需
要找到某个中间格局的所有后继格局,即每种可能的走法所能得到的格局。
(2)输入
输入的第一行是一个整数 N,表示共有 N 个格局。后续紧跟 N 行,每行由
两部分构成,第一部分是一个整数 n,表示这是一个 n 滑块游戏,第二部分是 2n+1
个字符,表示该游戏的某个格局。
(3)输出
首先判断输入的格局是否是目标格局,如果是,则输出“目标格局”后结束;
4
如果不是目标格局,则按顺序(将格局看作字符串后,按照字典序排序,即
B < E < W)输出该格局的所有后继格局。例如,BBEBWWW 格局应该排在
BBWBWEW 格局的前面,因为在英文字母表中,第一个格局中的第 3 个字符 E
排在第二个格局的第 3 个字符 W 前面
(4)示例
输入
2
3 BBWBEWW
4 WWWWBBEBB
输出
结果_1
BBEBWWW
BBWBWEW
BBWBWWE
BBWEBWW
BEWBBWW
结果_2
目标格局


题目分析
  题目中没有说明输入的格局数N的范围,也没有说明每个格局的最大长度,为了简化代码,我们假设输入的格局数不超过6,每个格局的长度不超过20个字符。将所有输入的格局存储到二维数组buffer中,其定义如下

	const int MAX_N = 6;//输入的最大格局数
	const int MAX_LEN = 20;//每个格局的最大长度
	char buffer[MAX_N][MAX_LEN];
  • 1
  • 2
  • 3

  待全部格局都输入到buffer中之后,对每个格局进行遍历。首先判断当前遍历到的格局是否为目标格局,这个判断相对来说是比较容易的,可以通过找最后一个W的位置wMaxIndex和第一个B的位置bMinIndex来判断。如果满足wMaxIndex < bMinIndex,那么此格局为目标格局。举个例子,比如说下面的这个格局。

BBWBEWW

  最后一个W的位置wMaxIndex是6(从0开始),第一个B的位置bMinIndex是0。不满足上式,因此不是目标格局。
  再看另一个格局。

WWWWBBEBB

  最后一个W的位置wMaxIndex是3,第一个B的位置bMinIndex是4,满足wMaxIndex < bMinIndex,因此它是目标格局。

  若不是目标格局,后面就需要找它的后继格局。首先找到E所在的位置,根据题目要求,E之前的三个将牌都可以和E进行交换,E之后的三个将牌也可以和E交换。现在的问题是,E之前或之后是否有三个将牌?因此在交换之前,需要先判断一下是否越界。比如下面这个格局。

BBWBEWW

  E的位置index为4,它可以与第index+1个将牌交换,可以与第index+2个将牌交换,但是不能与第index+3个将牌交换,因为index+3已经越界了。
  将所有的后继格局存储下来,在输出之前按照题目要求进行排序即可。


源代码

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

//将数组str中的第i个元素和第j个元素互换
void swap(char str[], int i, int j) {
	char ch = str[i];
	str[i] = str[j];
	str[j] = ch;
}

//将result数组的前counter个进行冒泡排序,看不懂也没关系,只要知道函数的功能就行
void bubbleSort(char result[][20], int counter, int length) {
	char str[20];
	for (int i = counter - 1; i > 0; i--)
		for (int j = 0; j < i - 1; j++)
			if (strcmp(result[j + 1], result[j]) < 0) {
				strcpy(str, result[j]);
				strcpy(result[j], result[j + 1]);
				strcpy(result[j + 1], str);
			}
}

//判断sliders是否为目标格局
bool check(char* sliders,int length) {
	int wMaxIndex = 0;//最后一个白色将牌的下标
	int bMinIndex = 0;//第一个黑色将牌的下标
	for (int i = 0; i < length; i++) {
		if (sliders[i] == 'W')
			wMaxIndex = i;
		else if (sliders[i] == 'B') 
			bMinIndex = i;
	}

	if (wMaxIndex < bMinIndex)
		return true;

	return false;
}

int main() {
	//假设输入的最大格局数是6,每个格局的最大长度是20
	const int MAX_N = 6;//输入的最大格局数
	const int MAX_LEN = 20;//每个格局的最大长度
	char buffer[MAX_N][MAX_LEN];//假设输入的格局不超过6个,每个格局不超过20个字符。
	int N;

	cin >> N;

	for (int i = 0; i < N; i++) {
		int numSlider;
		cin >> numSlider;
		cin >> buffer[i];
	}

	for (int k = 0; k < N; k++) {//对每一个格局进行遍历处理
		int counter = 0;//记录该格局的后继格局数
		int length = strlen(buffer[k]);//length是当前格局的长度
		char sliders[20];
		char result[10][20];//存放该格局的所有后继格局,假设不超过10个
		cout << "结果_" << k + 1 << endl;

		strcpy(sliders, buffer[k]);//将当前格局复制到sliders中

		if (check(sliders,length)) {//检查当前格局是否为目标格局
			cout << "目标格局" << endl;
			continue;
		}

		for (int i = 0; i < 10; i++) {//将当前格局复制到二维数组result的每一维上
			strcpy(result[i], sliders);
		}

		int index = 0;
		for (; index < length; index++) { // 查找空格字符E的下标
			if (sliders[index] == 'E')
				break;
		}

		for (int offset = 1; offset < 4; offset++) {
			if (index + offset < length) {
				swap(result[counter], index, index + offset);//将空格和它右边的将牌交换
				counter++;
			}
			if (index - offset >= 0) {
				swap(result[counter], index, index - offset);//将空格和它左边的将牌交换
				counter++;
			}
		}

		bubbleSort(result, counter, length);//对当前格局的所有后继格局按照题目要求进行排序

		for (int m = 0; m < counter; m++)//输出当前格局的所有后继格局
			cout << result[m] << endl;
	}

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/378628
推荐阅读
相关标签
  

闽ICP备14008679号