4

## [C++][動動腦] 特殊矩陣 - 蛇行、螺旋、魔方陣

``````#include <stdio.h>
#include <stdlib.h>

#define SIZE 5

int main(void)
{
int x, y;
int array[SIZE][SIZE] = {0};

for (int i = 0; i < SIZE * SIZE; i++)
{
x = i / SIZE;
//奇數列由小到大，偶數列由大到小
y = x % 2 == 0 ? i % SIZE : SIZE - 1 - i % SIZE;
array[x][y] = i + 1;
}

for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
printf("%2d ", array[i][j]);
}
printf("\n");
}

system("pause");
return 0;
}
``````

``````#include <stdio.h>
#include <stdlib.h>

#define SIZE 5

//走法偏移量: 右->下->左->上
int dir_x[4] = {0, 1, 0, -1};
int dir_y[4] = {1, 0, -1, 0};

int main(void)
{
int index, x, y, temp_x, temp_y;
int array[SIZE][SIZE] = {0};

index = 0;
x = 0;
y = -1;

for (int i = 0; i < SIZE * SIZE; i++)
{
//試走，如果超出邊界或遇到已經走過的格子，index + 1 轉彎
temp_x = x + dir_x[index];
temp_y = y + dir_y[index];
if (temp_x < 0 || temp_x > SIZE - 1 ||
temp_y < 0 || temp_y > SIZE - 1 ||
array[temp_x][temp_y] != 0)
{
index = (index + 1) % 4;
}
//往下一個座標前進
x = x + dir_x[index];
y = y + dir_y[index];
array[x][y] = i + 1;
}

for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
printf("%2d ", array[i][j]);
}
printf("\n");
}

system("pause");
return 0;
}
``````

``````#include <stdio.h>
#include <stdlib.h>

#define SIZE 5

int main(void)
{
int x, y;
int array[SIZE][SIZE] = {0};

x = 0;
y = SIZE / 2;

for (int i = 0; i < SIZE * SIZE; i++)
{
//如果超過斜對角，左下往右上的最後一格，或遇到已經走過的格子，就退回並往下
if ((x < 0 && y > SIZE - 1) ||
(x >= 0 && y <= SIZE - 1 && array[x][y] != 0))
{
x = x + 2;
y = y - 1;
}
//超過邊界就將該軸座標移動到對面
x = (x + SIZE) % SIZE;
y = y % SIZE;

array[x][y] = i + 1;
//往右上前進
x = x - 1;
y = y + 1;
}

for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
printf("%2d ", array[i][j]);
}
printf("\n");
}

system("pause");
return 0;
}
``````

### 2 則留言

0

iT邦大神 1 級 ‧ 2017-11-11 12:53:09

1.最大值不限於 9
2.蛇行與螺旋的陣列可以不是正方形(eg.3x5, 7x9...)
3.三個題目用類似的方法解

``````Option Explicit
Const kMATRIX_TYPE_SNAKE = 1
Const kMATRIX_TYPE_SPIRAL = 2
Const kMATRIX_TYPE_MAGIC = 3
Const kDIRECTION_RIGHT_DOWN_LEFT = 1
Const kDIRECTION_RIGHT_DOWN_DOWN = 2
Const kDIRECTION_LEFT_DOWN = 3
Const kDIRECTION_DOWN_LEFT = 4
Const kDIRECTION_LEFT_UP = 5
Const kDIRECTION_UP_RIGHT = 6
Const kDIRECTION_MAGIC = 7
Sub Main()
Call MatrixFiller(kMATRIX_TYPE_MAGIC, 11, 11)
MsgBox "Done", vbInformation
End Sub
Sub MatrixFiller(matrixtype, maxrow, maxcol)
'=============================================================
'參數說明:
'matrixtype : SNAKE, SPIRAL, MAGIC 三種
'maxrow : 列數
'maxcol : 行數
'
'SNAKE, SPIRAL 的 maxrow, maxcol 為大於 0 整數即可
'MAGIC 的 maxrow, maxcol 均須為大於 0 單數且兩者必須相同
'=============================================================
On Error GoTo ErrorOutOfBound
Dim iLoop As Integer
Dim direction
Dim cellNow As Range
Dim bOutOfBound As Boolean
'============================
'Init Values
'============================
bOutOfBound = False
Select Case matrixtype
Case kMATRIX_TYPE_SNAKE
Range("A1").Offset(0, 0).Select
direction = kDIRECTION_RIGHT_DOWN_LEFT
Case kMATRIX_TYPE_SPIRAL
Range("A1").Offset(0, 0).Select
direction = kDIRECTION_RIGHT_DOWN_DOWN
Case kMATRIX_TYPE_MAGIC
If (maxrow <> maxcol) Or (Int(maxrow / 2) = (maxrow / 2)) Or (Int(maxcol / 2) = (maxcol / 2)) Then
MsgBox "無法計算", vbCritical
Exit Sub
End If
Range("A1").Offset(0, (maxcol - 1) / 2).Select
direction = kDIRECTION_MAGIC
End Select
ActiveCell.Value = 1
'============================
'Main Loop
'============================
For iLoop = 2 To maxrow * maxcol
bOutOfBound = False
Select Case direction
Case kDIRECTION_RIGHT_DOWN_LEFT     '往右,碰壁往下後, 接著住左
If ActiveCell.Offset(0, 1).Column > maxcol Then
ActiveCell.Offset(1, 0).Select
direction = kDIRECTION_LEFT_DOWN
Else
ActiveCell.Offset(0, 1).Select
End If
ActiveCell.Value = iLoop
Case kDIRECTION_LEFT_DOWN           '往左,碰壁往下
ActiveCell.Offset(0, -1).Select
If bOutOfBound = True Then
ActiveCell.Offset(1, 0).Select
direction = kDIRECTION_RIGHT_DOWN_LEFT
End If
Case kDIRECTION_RIGHT_DOWN_DOWN     '往右,碰壁往下後, 接著往下
If ((ActiveCell.Offset(0, 1).Column > maxcol) Or (IsEmpty(ActiveCell.Offset(0, 1).Value)) = False) Then
ActiveCell.Offset(1, 0).Select
direction = kDIRECTION_DOWN_LEFT
Else
ActiveCell.Offset(0, 1).Select
End If
Case kDIRECTION_DOWN_LEFT           '往下,碰壁往左
If (ActiveCell.Offset(1, 0).Row > maxrow) Or (IsEmpty(ActiveCell.Offset(1, 0).Value) = False) Then
ActiveCell.Offset(0, -1).Select
direction = kDIRECTION_LEFT_UP
Else
ActiveCell.Offset(1, 0).Select
End If
Case kDIRECTION_LEFT_UP           '往左,碰壁往上
ActiveCell.Offset(0, -1).Select
If bOutOfBound = True Then
ActiveCell.Offset(-1, 0).Select
direction = kDIRECTION_UP_RIGHT
Else
If (IsEmpty(ActiveCell.Value) = False) Then
ActiveCell.Offset(-1, 1).Select
direction = kDIRECTION_UP_RIGHT
End If
End If
Case kDIRECTION_UP_RIGHT           '往上,碰壁往右
If IsEmpty(ActiveCell.Offset(-1, 0).Value) Then
ActiveCell.Offset(-1, 0).Select
Else
ActiveCell.Offset(0, 1).Select
direction = kDIRECTION_RIGHT_DOWN_DOWN
End If
Case kDIRECTION_MAGIC           '往右上, 以及魔方陣的移動邏輯
ActiveCell.Offset(-1, 1).Select
If bOutOfBound = True Then              '出界, 有三種情形
If ((ActiveCell.Column = maxcol) And (ActiveCell.Row = 1)) Then '在最右上角出界
ActiveCell.Offset(1, 0).Select
ElseIf (ActiveCell.Row = 1) Then    '在最上面出界
ActiveCell.Offset(maxrow - 1, 1).Select
End If
Else
If (ActiveCell.Column > maxcol) Then        '在最右邊出界
ActiveCell.Offset(0, -1 * maxcol).Select
Else
If (IsEmpty(ActiveCell.Value) = False) Then '如果已經有值, 就移動到自己的下方
ActiveCell.Offset(2, -1).Select
End If
End If
End If
End Select
ActiveCell.Value = iLoop
Next
Exit Sub
ErrorOutOfBound:
bOutOfBound = True
Resume Next
End Sub
``````

fysh711426 iT邦研究生 2 級‧ 2017-11-11 18:00:25 檢舉

Resume Next 倒是還好

fysh711426 iT邦研究生 2 級‧ 2017-11-12 01:20:11 檢舉

0

iT邦新手 1 級 ‧ 2017-11-11 19:42:15

https://leetcode.com/

fysh711426 iT邦研究生 2 級‧ 2017-11-11 20:51:57 檢舉