Z字型编排问题(C++)

问题:

给定一个二维原数组,输出该数组矩阵进行Z字形编排后的内容。

原二维数组示例:


输出示例:


算法描述:


个人思路:

    可以利用“走迷宫”算法的思路,先把所有可以移动的方向枚举出来,如下:

enum WAY{
	RIGHT,
	BOTTOM,
	LEFTBOTTOM,
	RIGHTTOP,
	NONE
} nextWay;

  然后利用状态机思想,在循环遍历原数组的内循环中,switch case一下当前应该走的方向,然后在走完之后确定一下下一步应该走哪个方向(注意一定要在确定下一步之前加判断防止越界)。仔细观察该问题可以发现该走法有以下几个特征:

1.第一步在左上角开始走。

2.导致下一步往右走的情况只可能是:

  1.     走了第一步。
  2.     从左下到右上移动了之后移动到了首行,并且非右上角(RIGHTTOP方向移动到了右上角便没办法再右移了),那么接下来应该往右。
  3.     从右上到左下方向移动之后到了左下角或者底边,接下来没办法继续左下移动了,所以只能朝RIGHT方向移动。

3.导致下一步往下走的情况只可能是:

  1.     当前进行了左下方向的移动,并且移动到了首列,这时候如果当前point非左下角的话,就应该往下移动。
  2.     当前进行了右上方向的移动,并且移动到了尾列,那么这时候便无法继续右上了,所以下一步只能往下方移动。

4.导致往左下方向移动的可能性只能是:

  1.     在首行向右移动了之后,下一步应该往坐下移动。
  2.     如果上一步就是往坐下移动的,且没有触碰到坐下边界,则下一步应该继续往左下移动。
  3.     当尾列往下方移动一步之后,下一步应该往左下移动。

5.导致往右上方向移动的可能性只能是:

  1.     在首列往下移动一步之后,应该往右上移动。
  2.     如果上一步就是右上移动,且下一步并不会达到右上角或者右边及顶边边界,那么还应该继续往右上移动。
  3.     上一步如果是在底边横向往右移动了一步,那么下一步应该往右上。

个人思路实现的完整代码如下:

#include <iostream>
#include <stdlib.h>
#include <typeinfo>
#include <memory>
#define SIZE 8
using namespace std;
void print (int** p){
	//输出
	for (int i = 0; i < SIZE; ++i){
		for (int j = 0; j < SIZE; ++j){
			cout << p[i][j] << '\t';
		}
		cout << endl;
	}
}
void init(int** p){
	for (int i = 0; i < SIZE; ++i){
		for (int j = 0; j < SIZE; ++j){
			p[i][j] = i*SIZE + j;
		}
	}
}
enum WAY{
	RIGHT,
	BOTTOM,
	LEFTBOTTOM,
	RIGHTTOP,
	NONE
} nextWay;
struct Point{
	int row;
	int clum;
};
int main(){
	int** p = new int*[8] ;
	int** nP = new int*[8];
	for (int i = 0; i < SIZE; ++i){
		p[i] = new int[8];
		memset(p[i], 0, sizeof(int)* 8);
		nP[i] = new int[8];
		memset(nP[i], 0, sizeof(int)* 8);
	}
	init(p);
	nextWay = NONE;
	Point curPos;
	cout << "原数组:" << endl;
	print(p);

	for (int i = 0; i < SIZE; ++i){
		for (int j = 0; j < SIZE; ++j){
			switch (nextWay){
			case RIGHT:
					curPos.clum += 1;
					if (curPos.row == 0){
						//首行右移
						nextWay = LEFTBOTTOM;
					}
					else{
						//底行右移
						nextWay = RIGHTTOP;
					}
				break;
			case BOTTOM:
				curPos.row += 1;
				if (curPos.clum == 0){
					//首列下移
					nextWay = RIGHTTOP;
				}
				else{
					//尾列下移
					nextWay = LEFTBOTTOM;
				}
				break;
			case LEFTBOTTOM:
				curPos.row += 1;
				curPos.clum -= 1;
				if (curPos.clum == 0){
					//如果已经左下移动到首列
					if (curPos.row == SIZE - 1){
						//如果移动到左下角
						nextWay = RIGHT;
					}
					else{
						//如果移动到左边首列但非左下角
						nextWay = BOTTOM;
					}
				}
				else{
					if (curPos.row == SIZE - 1){
						//如果移动底列
						nextWay = RIGHT;
					}
					else{
						//如果移动到非左边首列且非底列
						nextWay = LEFTBOTTOM;
					}
				}
				break;
			case RIGHTTOP:
				curPos.clum += 1;
				curPos.row -= 1;
				if (curPos.row == 0){
					//如果右上角移动已经移到了首行
					if (curPos.clum == SIZE - 1){
						//如果移动到了右上角
						nextWay = BOTTOM;
					}
					else{
						nextWay = RIGHT;
					}
				}
				else{
					if (curPos.clum == SIZE - 1){
						//如果移动到了最右列
						nextWay = BOTTOM;
					}
					else{
						nextWay = RIGHTTOP;
					}
				}
				break;
			case NONE:
				curPos.clum = 0;
				curPos.row = 0;
				if (curPos.clum + 1 < SIZE)
					nextWay = RIGHT;
				break;
			}
			nP[curPos.row][curPos.clum] = p[i][j];
		}
	}
	cout << endl << endl;
	cout << "输出该数组进行Z字形编排后的内容:" << endl;
	print(nP);
	delete[] p;
	delete[] nP;
	system("pause");
	return 0;
} 

注意事项:  主要是在进行下一步走法的确定时,一定要严格检查是否已经达到边界,因为如果达到了边界,则下一步的方向可能发生改变。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 游戏需求 随机给出不同的形状(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型)下落填充给定的区域,若填满一条便消掉,记分,当达到一定的分数时,过关,设置几个关卡,每关方块下落的速度不同,若在游戏中各形状填满了给定区域,为输者。 2.游戏界面需求: 良好的用户界面,有关数显示和分数显示,以及下一个方块显示。让方块在一定的区域内运动和变形,该区域用一种颜色表明 。还需用另一种颜色把该区域围起来,宽度适中,要实现美感。 3.游戏形状(方块)需求: 良好的方块形状设计,绘制七种常见的基本图形(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),各个方块要能实现它的变形,可设为顺时针或逆 时针变形,一般为逆时针。 4.输入与输出: 用户根据需要输入上(输出旋转效果)、左右(输出移动效果)、下(输出加速下沉效果)、空格(沉底)、P(暂停)、ESC(退出)。 2.游戏界面需求: 良好的用户界面,有关数显示和分数显示,以及下一个方块显示。让方块在一定的区域内运动和变形,该区域用一种颜色表明 。还需用另一种颜色把该区域围起来,宽度适中,要实现美感。 3.游戏形状(方块)需求: 良好的方块形状设计,绘制七种常见的基本图形(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),各个方块要能实现它的变形,可设为顺时针或逆 时针变形,一般为逆时针。 4.输入与输出: 用户根据需要输入上(输出旋转效果)、左右(输出移动效果)、下(输出加速下沉效果)、空格(沉底)、P(暂停)、ESC(退出)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值