MOOC清华《面向对象程序设计》第5章:OOP版填充数字矩阵(采用模板方法)

先上源代码:

//main.cpp    
#include <iostream>    
#include "Matrix.h"    
using namespace std;         
    
int main() {    
    int size;      
    cout << "请输入矩阵的边长 N: ";    
    cin >> size;     
        
    AnticlockMatrix obj(size);        
    obj.fill();    
    cout << obj;    
        
    return 0;    
}  

//Matrix.h    
#ifndef Matrix_h    
#define Matrix_h    
    
#include <iostream>    
using namespace std;    
    
class Matrix{         
public:    
    int _size;//方阵的规模     
    int *_data;//数据空间    
    int row, col;    
    char dir;//用于顺时针、逆时针、行优先、列优先时的方向判定  
    Matrix(int size);    
    ~Matrix();    
    void fill();    
    virtual int findPosition() = 0;
    int fill_style(char* str1, char* str2);    
    friend ostream& operator<< (ostream& out, const Matrix& m);     
};    

class ClockwiseMatrix:public Matrix{
public:
	using Matrix::Matrix;
	int findPosition();//顺时针辅助函数 
};

class AnticlockMatrix:public Matrix{
public:
	using Matrix::Matrix;
	int findPosition();//逆时针辅助函数 
};

class RowFirstMatrix:public Matrix{
public:
	using Matrix::Matrix;
    int findPosition();//行优先辅助函数 	
};

class ColFirstMatrix:public Matrix{
public:
	using Matrix::Matrix;
    int findPosition();//列优先辅助函数   	
};
    
#endif    


//Matrix.cpp    
#include <iostream>    
#include <cstring>    
#include "Matrix.h"    
using namespace std;    
    
Matrix::Matrix(int size): _size(size), row(-1), col(0), dir('D') {     
    _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;    
    }    
}      
    
void Matrix::fill(){     
    for(int num = 1; num <= _size * _size; num++){    
        int pos = findPosition();    
        _data[pos] = num;    
    }    
}       

//ClockwiseMatrix.cpp
#include <iostream>       
#include "Matrix.h"    
using namespace std; 

int ClockwiseMatrix::findPosition(){     
    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;    
}    

//AnticlockMatrix.cpp
#include <iostream>       
#include "Matrix.h"    
using namespace std; 

int AnticlockMatrix::findPosition(){     
    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;    
}    

//RowFirstMatrix.cpp
#include <iostream>       
#include "Matrix.h"    
using namespace std; 

int RowFirstMatrix::findPosition(){  
    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;  
}  

//ColFirstMatrix.cpp
#include <iostream>       
#include "Matrix.h"    
using namespace std; 

int ColFirstMatrix::findPosition(){  
    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;  
}  

测试结果:



经验总结:

代码有两种:一种是对最终用户而言很简单,“傻瓜软件”,但是对程序员而言可能相对麻烦;另一种是对程序员而言很简单,便于修改、扩展、复用,但是对用户而言可能比较头疼。前两篇“产品级终极中文版”的代码就属于前一种,对用户很简单,也应该是一个开发人员或开发公司对产品的努力方向。而这一篇代码则属于后一种,对程序员而言可能比较简单,但是用户想切换矩阵的输出方式?就不那么方便了(比如这份代码中需要程序员修改main源码、用另外的实现类名替换现有对象的类名,还要修改Matrix源码、重新给构造函数的初始化列表赋值,而用户根本就没有选择输出方式的余地)。也许还需要设计一个总入口(未必是抽象类的,可以是独立的函数),总入口下面涵盖所有的实现类,根据输入的信息再来将流程导向不同的实现类——这样也可以做到前两篇“产品级”程序的高度——所以,这两种代码其实可以统一成一个整体:既对用户很友好,也对程序员很友好(我是边打字,边思考,边打字着的)。等有空时仔细试一试该怎么在模板方法的基础上做到“集成化”。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值