У меня был пойти. Это немного наивно, поскольку я не знал алгоритма. Он работает для любой матрицы, размер которой является нечетным числом.
[EDIT: теперь с комментариями]
#include <iostream>
#include <cstdlib>
#include <cassert>
using namespace std;
void printMatrix(int** mat, int s) {
for (int i = 0; i < s; ++i) {
for (int j = 0; j < s; ++j) {
cout << mat[i][j] << " ";
}
cout << "\n";
}
}
// For the matrix of size s located at mat1[src_x][src_y], shift the numbers on its
// perimeter in a counter-clockwise direction, and store the result in mat2.
void periShift(int** mat1, int src_x, int src_y, int s, int** mat2, int shift) {
// Bottom edge
for (int i = 0; i < s; ++i) {
int x = i;
int y = 0;
// Max x on this edge
int X = s - 1;
// The amount of space we have to shift x
int a = X - x;
// Clip the value to shift
if (a > shift) a = shift;
// If a < shift, the number is to be shifted round the corner (up the right side) by b places.
int b = shift - a;
mat2[src_x + x + a][src_y + y + b] = mat1[src_x + x][src_y + y];
}
// Top edge
for (int i = 0; i < s; ++i) {
int x = s - 1 - i;
int y = s - 1;
int a = x;
if (a > shift) a = shift;
int b = shift - a;
mat2[src_x + x - a][src_y + y - b] = mat1[src_x + x][src_y + y];
}
// Right edge
for (int i = 0; i < s; ++i) {
int y = i;
int x = s - 1;
int Y = s - 1;
int a = Y - y;
if (a > shift) a = shift;
int b = shift - a;
mat2[src_x + x - b][src_y + y + a] = mat1[src_x + x][src_y + y];
}
// Left edge
for (int i = 0; i < s; ++i) {
int y = s - 1 - i;
int x = 0;
int a = y;
if (a > shift) a = shift;
int b = shift - a;
mat2[src_x + x + b][src_y + y - a] = mat1[src_x + x][src_y + y];
}
}
void rotateMatrix(int** mat1, int** mat2, int s) {
// The size of the matrix's perimeter
int peri = 4 * (s - 1);
assert(peri % 8 == 0);
// As 45 degrees is an eighth of a full circle, the numbers on the matrix's perimeter
// should end up (peri/8) places counter-clockwise from where they started.
int shift = peri/8;
// Work our way out from the centre of the matrix to the edge, performing the perimeter shift
// on each submatrix. I.e. the 3x3 matrix in the middle has its perimeter shifted 1 position
// counter-clockwise, the 4x4 matrix has its position shifted 2 places, etc.
for (int i = 0; i < s/2; ++i) {
int x = i;
int y = i;
// Shift the perimeter of the submatrix
periShift(mat1, x, y, s - 2 * i, mat2, shift - i);
}
// Copy the centre value over
mat2[s/2][s/2] = mat1[s/2][s/2];
}
int main() {
int s = 0;
while (1) {
cout << "Enter matrix size:\n";
cin >> s;
if (s % 2 == 1) break;
cout << "Invalid matrix size. Must be an odd number.\n";
}
// Construct 2 matrices
int** mat1 = new int*[s];
for (int i = 0; i < s; ++i)
mat1[i] = new int[s];
int** mat2 = new int*[s];
for (int i = 0; i < s; ++i)
mat2[i] = new int[s];
// Fill first matrix with random numbers (0 .. 9)
srand(time(NULL));
for (int i = 0; i < s; ++i) {
for (int j = 0; j < s; ++j) {
mat1[i][j] = rand() % 10;
}
}
cout << "Matrix =\n";
printMatrix(mat1, s);
rotateMatrix(mat1, mat2, s);
cout << "\nRotated matrix =\n";
printMatrix(mat2, s);
// Delete matrices
for (int i = 0; i < s; ++i)
delete[] mat1[i];
delete mat1;
for (int i = 0; i < s; ++i)
delete[] mat2[i];
delete mat2;
return EXIT_SUCCESS;
}
EDIT: В теории, весь периметр сдвиг вещь не нужна, если вы можете выяснить математическую функцию, которая отображает позицию значений в матрице А, чтобы их новый положение в матрице B.
Я знаю, что внешний раунд должен быть перемещен (MatrixSize/2) и для каждого раунда u приближается к центру, это количество должно быть уменьшено на 1, и поэтому место центрального элемента не изменится. –
2D ... вот код фрагмента, который я сделал до сих пор ... проблема только в позиционировании: –
Этот вопрос появляется быть вне темы, потому что это не объясняет, в чем проблема. – brandonscript