# a417 - 螺旋矩陣
### 題目連結: [a417](https://zerojudge.tw/ShowProblem?problemid=a417)
### 題目解析
* 依照題目的描述,需要輸出一個連續數字的二維矩陣
* 此矩陣的數字,會隨著矩陣的大小由左上角開始不斷標號,直到中心點
### 題目類型
二維串列/矩陣/邊界問題
### 範例測資解讀
* 輸入
* 第一行只有一個數字T,代表有幾組測試資料
* 接下來有T行,每行有兩個整數N, M
* N代表矩陣長寬(正方形)
* M代表旋轉的方向(1=順時鐘, 2=逆時鐘)
* 輸出
* 輸出為一個二維矩陣,並且需要有足夠的間隔
* 輸出說名的 setw(5) 為C/C++的語法,不適用於 Python
### 其他注意事項
* 進行二維串列計算的時候需要小心並且考慮邊界問題,避免發生 list out of range 的錯誤
### 程式解析
由題目中可以瞭解,我們需要將數字依照順時鐘或逆時鐘的方式,不斷旋轉填入矩陣中,矩陣是數學上的一種特殊結構,但在這個題目其實就是使用二維串列儲存資料的意思
順時鐘的填法:

逆時鐘的填法:

要如何使用程式在二維串列中移動呢?
首先需要知道二維串列中,相連元素之間索引值的關係
移動時需要兩個索引值,定義為 r_index(上下移動), c_index(左右移動)
另外還需要旋轉方向:
* 如果是順時針,則移動方向依序為右下左上
* 如果是逆時針,則移動方向為下右上左
``` python
r_index = 0
c_index = 0
direction = 1
# 1: right
# 2: down
# 3: left
# 4: up
```
如果左上角1的位置為起始點,往下移動的話,需要調整 r_index 的位置
如果要往右移動的話,需要調整 c_index 的位置,以這兩個索引值就能達到在二維串列中移動的方法

### 轉向和邊界
當移動 r_index, c_index 的時候碰到陣列的邊界就需要進行轉向,否則會發生錯誤或是數字填錯

哪邊是陣列的邊界呢?在設計判斷條件的時候必須特別注意這個範圍
* r_index<0, r_index>=N
* c_index<0, c_index>=N
※ 除了碰到邊界需要轉向以外,也需要考慮是會碰到已填入值的位置

### 完整程式碼 (僅提供參考)
``` python=01
arr = []
for x in range(100):
arr.append([ -1 for i in range(100) ])
def show(n):
for i in range(n):
for j in range(n):
#print(arr[i][j], end=' ')
print("%5d" % arr[i][j], end='')
print()
while True:
try:
#start
N = int(input())
M = int(input())
for i in range(N):
for j in range(N):
arr[i][j] = 0
if M==1:
r_index = 0
c_index = 0
num = 1
direction = 1
# 1: right
# 2: down
# 3: left
# 4: up
while num<=N*N :
# 向右移動
if direction == 1:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
c_index +=1
#判斷邊界和轉向,修改 r_index, c_index 的計算方法
if c_index>=N or arr[r_index][c_index]>0:
c_index -=1
r_index +=1
direction = 2
else:
direction = 2
#end of if direction ==1
elif direction == 2:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
r_index +=1
if r_index>=N or arr[r_index][c_index]>0:
r_index -=1
c_index -=1
direction = 3
else:
direction = 3
#end of if direction ==2
elif direction == 3:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
c_index -=1
if c_index<0 or arr[r_index][c_index]>0:
c_index +=1
r_index -=1
direction = 4
else:
direction = 4
#end of if direction ==3
elif direction == 4:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
r_index -=1
if c_index<0 or arr[r_index][c_index]>0:
r_index +=1
c_index +=1
direction = 1
else:
direction = 1
#end of if direction ==3
#end of if M==1
else:
r_index = 0
c_index = 0
num =1
direction = 1
while num<=N*N:
if direction == 1:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
r_index +=1
if r_index >=N or arr[r_index][c_index]>0:
r_index -=1
c_index +=1
direction = 2
else:
direction = 2
#end of if direction == 1
elif direction == 2:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
c_index +=1
if c_index >=N or arr[r_index][c_index]>0:
c_index -=1
r_index -=1
direction = 3
else:
direction = 3
#end of if direction == 2
elif direction == 3:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
r_index -=1
if r_index <0 or arr[r_index][c_index]>0:
r_index +=1
c_index -=1
direction = 4
else:
direction = 4
#end of if direction == 3
elif direction == 4:
if arr[r_index][c_index] == 0:
arr[r_index][c_index] = num
num +=1
c_index -=1
if c_index <0 or arr[r_index][c_index]>0:
c_index +=1
r_index +=1
direction = 1
else:
direction = 1
#end of if direction == 4
show(N)
except:
break
```
###### tags: `基礎15題解` `APCS` `ZeroJudge`