先上源代码:
//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源码、重新给构造函数的初始化列表赋值,而用户根本就没有选择输出方式的余地)。也许还需要设计一个总入口(未必是抽象类的,可以是独立的函数),总入口下面涵盖所有的实现类,根据输入的信息再来将流程导向不同的实现类——这样也可以做到前两篇“产品级”程序的高度——所以,这两种代码其实可以统一成一个整体:既对用户很友好,也对程序员很友好(我是边打字,边思考,边打字着的)。等有空时仔细试一试该怎么在模板方法的基础上做到“集成化”。