MOOC清华《面向对象程序设计》第5章:OOP版填充数字矩阵-产品级终极中文版 v 2.0(增加按行、按列填充)

之前我没有理解“行优先填充”“列优先填充”是什么意思,以为开始是从填充行开始的就叫“行优先填充”,开始从填充列开始的就叫“列优先填充”。今天看了黄震春老师的“变与不变:多态的威力”一节视频后,发现“顺时针填充”和“行优先填充”是分开作为两个不同的派生类实现的,那么难道“行优先填充”的意思是“按行填充”吗?那还是“旋转矩阵”吗?如果根据我之前的理解,仅仅靠“顺时针”和“行优先”两个描述并不能确定唯一的填充方式,因为有可能是先填充最上面一行(从左上角开始),也有可能是先填充最下面一行(从右下角开始)。

另外,黄震春老师讲到的“模板方法”中,抽象类定义算法骨架与接口(用虚函数),不同的实现类定义接口的不同的具体实现细节,然后根据需要,调用不同的实现类达到需求目标。前面两句话我都知道怎么做了,可是后面这句“根据需要来调用”应该怎么做?也是用传递参数的办法吗?

经过一上午的改进,给前一篇博文中的程序增添了“行优先”(按行填充)、“列优先”(按列填充)的实现。没有用到继承和派生、虚函数、模板方法,因为感觉我还不知道如何实现“根据不同情况发挥多态性的威力”——如果不同的派生类也是根据参数传值的方式来调用的话,我更习惯于成员函数的形式。代码如下:

//main.cpp  
#include <iostream>  
#include "Matrix.h"  
using namespace std;  
  
const int str_length = 7;//经测试,至少为7;印证了每个汉字占2个字节('\0'占一个字节)   
  
int main() {  
    int size;  
    char wise_or_anti[str_length];  
    char first_point[str_length];  
    cout << "请输入矩阵的边长 N: ";  
    cin >> size;  
    cout << "请输入填充方式(顺时针、逆时针、行优先、列优先): ";  
    cin >> wise_or_anti;  
    cout << "请输入从哪一个角开始填充(左上角、左下角、右上角、右下角): ";  
    cin >> first_point;  
      
    Matrix obj(size);  
    obj.fill_style(wise_or_anti, first_point);  
    obj.fill();  
    cout << obj;  
      
    return 0;  
}  

//Matrix.h  
#ifndef Matrix_h  
#define Matrix_h  
  
#include <iostream>  
using namespace std;  
  
class Matrix{  
    int _size;//方阵的规模   
    int *_data;//数据空间  
    int row, col;  
    char dir;//用于顺时针、逆时针、行优先、列优先时的方向判定  
    char* _wise_or_anti;//除了顺时针和逆时针以外,也可赋值为行优先或列优先  
    char* _first_point;//赋值为四个角  
    int findPosition_clockwise();//顺时针辅助函数  
    int findPosition_anticlock();//逆时针辅助函数  
	int findPosition_row_first();//行优先辅助函数 
	int findPosition_col_first();//列优先辅助函数 
      
public:  
    Matrix(int size);  
    ~Matrix();  
    void fill();  
    int fill_style(char* str1, char* str2);  
    friend ostream& operator<< (ostream& out, const Matrix& m);   
};  
  
#endif  

//Matrix.cpp  
#include <iostream>  
#include <cstring>  
#include "Matrix.h"  
using namespace std;  
  
Matrix::Matrix(int size): _size(size) {   
    _data = new int[size * size];  
    memset(_data, 0, sizeof(int) * _size * _size);  
}  
  
Matrix::~Matrix(){  
    delete _data;  
}  
  
ostream& operator<< (ostream& out, const Matrix& m){  
    for(int r = 0; r < m._size; r++){ //row  
        for(int c = 0; c < m._size; c++) //col  
            cout << *(m._data + r * m._size + c) << '\t';  
        cout << endl;  
    }  
}  
  
int Matrix::fill_style(char* str1, char* str2){  
    //strcpy(_wise_or_anti, str1);//fatal error!  
    //strcpy(_first_point, str2);//fatal error!  
    _wise_or_anti = str1;  
    _first_point = str2;  
    if(strcmp(str1, "顺时针") == 0){  
        if(strcmp(str2, "左上角") == 0) return 1;  
        if(strcmp(str2, "右上角") == 0) return 2;  
        if(strcmp(str2, "右下角") == 0) return 3;  
        if(strcmp(str2, "左下角") == 0) return 4;  
    }  
    if(strcmp(str1, "逆时针") == 0){  
        if(strcmp(str2, "左上角") == 0) return 5;  
        if(strcmp(str2, "左下角") == 0) return 6;  
        if(strcmp(str2, "右下角") == 0) return 7;  
        if(strcmp(str2, "右上角") == 0) return 8;  
    }  
    if(strcmp(str1, "行优先") == 0){
    	if(strcmp(str2, "左上角") == 0) return 9;
    	if(strcmp(str2, "右上角") == 0) return 10;  
		if(strcmp(str2, "左下角") == 0) return 11;
		if(strcmp(str2, "右下角") == 0) return 12;  	
	}
	if(strcmp(str1, "列优先") == 0){
		if(strcmp(str2, "左上角") == 0) return 13;
		if(strcmp(str2, "右上角") == 0) return 14;
		if(strcmp(str2, "左下角") == 0) return 15;
		if(strcmp(str2, "右下角") == 0) return 16;
	}
}  
  
void Matrix::fill(){  
    int n = fill_style(_wise_or_anti, _first_point);  
    if(n == 1){//顺时针、左上角   
        row = 0;  
        col = -1;  
        dir = 'R';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_clockwise();  
            _data[pos] = num;  
        }  
    }  
    if(n == 2){//顺时针、右上角   
        row = -1;  
        col = _size - 1;  
        dir = 'D';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_clockwise();  
            _data[pos] = num;  
        }  
    }  
    if(n == 3){//顺时针、右下角   
        row = _size - 1;  
        col = _size;  
        dir = 'L';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_clockwise();  
            _data[pos] = num;  
        }  
    }  
    if(n == 4){//顺时针、左下角   
        row = _size;  
        col = 0;  
        dir = 'U';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_clockwise();  
            _data[pos] = num;  
        }  
    }  
    if(n == 5){//逆时针、左上角   
        row = -1;  
        col = 0;  
        dir = 'D';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_anticlock();  
            _data[pos] = num;  
        }  
    }  
    if(n == 6){//逆时针、左下角   
        row = _size - 1;  
        col = -1;  
        dir = 'R';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_anticlock();  
            _data[pos] = num;  
        }  
    }  
    if(n == 7){//逆时针、右下角   
        row = _size;  
        col = _size - 1;  
        dir = 'U';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_anticlock();  
            _data[pos] = num;  
        }  
    }  
    if(n == 8){//逆时针、右上角   
        row = 0;  
        col = _size;  
        dir = 'L';  
        for(int num = 1; num <= _size * _size; num++){  
            int pos = findPosition_anticlock();  
            _data[pos] = num;  
        }  
    } 
    if(n == 9){//行优先且向右且向下填充(左上角)
		row = 0;
		col = -1;
		dir = 'D';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_row_first();
			_data[pos] = num;
		}
	}
	if(n == 10){//行优先且向左且向下填充(右上角)
		row = 0;
		col = _size;
		dir = 'L';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_row_first();
			_data[pos] = num;
		}		
	}
	if(n == 11){//行优先且向右且向上填充(左下角)
		row = _size - 1;
		col = -1;
		dir = 'R';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_row_first();
			_data[pos] = num;
		}		
	}
	if(n == 12){//行优先且向左且向上填充(右下角)
		row = _size - 1;
		col = _size;
		dir = 'U';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_row_first();
			_data[pos] = num;
		}		
	}
	if(n == 13){//列优先且向下且向右填充(左上角)
		row = -1;
		col = 0;
		dir = 'D';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_col_first();
			_data[pos] = num;
		}		
	}
	if(n == 14){//列优先且向下且向左填充(右上角)
		row = -1;
		col = _size - 1;
		dir = 'L';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_col_first();
			_data[pos] = num;
		}		
	}
	if(n == 15){//列优先且向上且向右填充(左下角)
		row = _size;
		col = 0;
		dir = 'R';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_col_first();
			_data[pos] = num;
		}		
	}
	if(n == 16){//列优先且向上且向左填充(右下角)
		row = _size;
		col = _size - 1;
		dir = 'U';
		for(int num = 1; num <= _size * _size; num++){
			int pos = findPosition_col_first();
			_data[pos] = num;
		}		
	}
}  
  
int Matrix::findPosition_clockwise(){ //clockwise为顺时针的意思   
    switch(dir){  
        case 'D':  
            if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)  
                row++;  
            else{  
                dir = 'L'; // next direction  
                col--;  
            }  
            break;  
        case 'L':  
            if(col > 0 && _data[row * _size + col - 1] == 0)  
                col--;  
            else{  
                dir = 'U'; // next direction  
                row--;  
            }  
            break;  
        case 'U':  
            if(row > 0 && _data[(row - 1) * _size + col] == 0)  
                row--;  
            else{  
                dir = 'R'; // next direction  
                col++;  
            }  
            break;  
        case 'R':  
            if(col < _size - 1 && _data[row * _size + col + 1] == 0)  
                col++;  
            else{  
                dir = 'D'; // next direction  
                row++;  
            }  
            break;  
    }  
    return row * _size + col;  
}  
  
int Matrix::findPosition_anticlock(){ //anticlock为逆时针的意思   
    switch(dir){  
        case 'D':  
            if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)  
                row++;  
            else{  
                dir = 'R'; // next direction  
                col++;  
            }  
            break;  
        case 'R':  
            if(col < _size - 1 && _data[row * _size + col + 1] == 0)  
                col++;  
            else{  
                dir = 'U'; // next direction  
                row--;  
            }  
            break;  
        case 'U':  
            if(row > 0 && _data[(row - 1) * _size + col] == 0)  
                row--;  
            else{  
                dir = 'L'; // next direction  
                col--;  
            }  
            break;  
        case 'L':  
            if(col > 0 && _data[row * _size + col - 1] == 0)  
                col--;  
            else{  
                dir = 'D'; // next direction  
                row++;  
            }  
            break;  
    }  
    return row * _size + col;  
}  

int Matrix::findPosition_row_first(){
	switch(dir){
		case 'D'://行优先且向右且向下填充(左上角)
			if(col < _size - 1 && _data[row * _size + col + 1] == 0)
				col++;
			else
				if(row < _size - 1){
					row++;
					col = 0;
				}
			break;
		case 'L'://行优先且向左且向下填充(右上角)
            if(col > 0 && _data[row * _size + col - 1] == 0)  
                col--;  
            else
            	if(row < _size - 1){
            		row++;
            		col = _size - 1;
				}
			break;
		case 'R'://行优先且向右且向上填充(左下角)
			if(col < _size - 1 && _data[row * _size + col + 1] == 0) 
				col++;
			else
				if(row > 0){
					row--;
					col = 0;
				}
			break;
		case 'U'://行优先且向左且向上填充(右下角)
			if(col > 0 && _data[row * _size + col - 1] == 0)  
            	col--; 
            else
            	if(row > 0){
            		row--;
            		col = _size - 1;
				}
			break;
	}
	return row * _size + col;
}

int Matrix::findPosition_col_first(){
	switch(dir){
		case 'D'://列优先且向下且向右填充(左上角)
            if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)  
                row++;
			else
				if(col < _size - 1){
					col++;
					row = 0;
				}
			break;
		case 'L'://列优先且向下且向左填充(右上角)
            if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)  
                row++;  
            else
            	if(col > 0){
            		col--;
            		row = 0;
				}
			break;
		case 'R'://列优先且向上且向右填充(左下角)
            if(row > 0 && _data[(row - 1) * _size + col] == 0)  
                row--; 
			else
				if(col < _size - 1){
					col++;
					row = _size - 1;
				}
			break;
		case 'U'://列优先且向上且向左填充(右下角)
            if(row > 0 && _data[(row - 1) * _size + col] == 0)  
                row--;
            else
            	if(col > 0){
            		col--;
            		row = _size - 1;
				}
			break;
	}
	return row * _size + col;
}

对新增添的功能全方位无死角测试结果:

行优先:






列优先:





关于方形矩阵的填充,除了这份代码中的“旋转填充、从外向里”和“按行或按列填充”之外,还有两种方式:第三种:旋转填充、从里向外(根据最后一个数字的落点在哪一个角,可以有四种不同情形);第四种:按对角线、扫描式填充(根据对角线有2条、每条对角线的两边分别有2个角,也可以有四种不同情形)。这两种方式又该如何实现?留待高人解决!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值