python练手小程序--螺旋矩阵

参考: python练手项目--crossin的编程教室

[题目] 输出如图的螺旋矩阵:

1	2	3	4	

12	13	14	5	

11	16	15	6	

10	9	8	7	

[附加题] 输入一个正整数 N,输出以 N 为边长的螺旋矩阵。(比如上图就是 N 为 4 的结果)

 

1. 初步思路:

  1. 创建二维列表去存储数字, 最后输出

  2. 找出存数字的规律: 用(i, j)表示列表下标, 则:

i 的运动规律是: 0 -> 1-(n-1) -> (n-1) -> (n-2)-1 -> 1 -> 2-(n-2) -> (n-2) ...

j 的运动规律是: 0-(n-1) -> (n-1) -> (n-2)-0 -> 0 -> 1-(n-2) -> (n-2) ...

但是这样太复杂了, pass

2. 参考答案的解题思路, 自己实现代码:

[解题思路]:

  1. 由图可知,螺旋数组中的数字运动方向依次 右 -> 下 -> 左 -> 上 -> 右 这样的循环,在合适的条件下变换累加方向即可。

  2. 变换方向的条件有两个,一是遇到数组边界,二是下一位置被其他数占据。

  3. 可用一个二维列表存储数据,按照规则将列表中填上数字,最后再输出

实现代码如下: 

#! /usr/bin/env python
# coding = utf-8

def switch(list, i, j):
    #1. boundry  2. already have data
    if i >= n or j >= n:
        return True
    elif list[i][j] != 0:
        return True
    else:
        return False

def switch_direction(direction):
    # direction: right -> down -> left -> up
    if direction == 'right':
        return 'down'
    elif direction == 'down':
        return 'left'
    elif direction == 'left':
        return 'up'
    elif direction == 'up':
        return 'right'
    else:
        pass

def next_coordinary(direction, i, j):
    if direction == 'right':
        return i, j+1
    elif direction == 'down':
        return i+1, j
    elif direction == 'left':
        return i, j-1
    elif direction == 'up':
        return i-1, j

if __name__ == "__main__":
    n = int(input("please input n: "))
    list = [[0 for i in range(n)] for j in range(n)]
    i = 0
    j = 0
    direction = 'right'
    for k in xrange(1, n ** 2 + 1):
        list[i][j] = k
        if k == n**2:
            break
        i1, j1 = next_coordinary(direction, i, j)
        while switch(list, i1, j1):
            direction = switch_direction(direction)
            i1, j1 = next_coordinary(direction, i, j)
        i, j = i1, j1

    for i in range(n):
        for j in range(n):
            print "{}\t".format(list[i][j]),
        print '\n'


3. 作者给出的参考代码:

作者给出的参考代码

class Spiral:
    def __init__(self, N):
        # 构造一个二维数组
        self.matrix = [[None for i in range(N)] for j in range(N)]
        # 起始行列数
        self.row = 0
        self.col = 0
        # 数组的边界值
        self.max_row = N
        # 更换方向的标记
        self.mark = 0

    # 按需取出数组运动方向
    def derection(self, mark):
        around = [
            [self.row, self.col+1], # 向右
            [self.row+1, self.col], # 向下
            [self.row, self.col-1], # 向左
            [self.row-1, self.col]  # 向上
        ]
        return around[mark%4]

    # 针对目前位置,获取下一位置的行列数
    # 下一位置为边界则更换方向
    # 下一位置已经有元素则更换方向
    def next(self):
        # 下一位置
        i = self.derection(mark=self.mark)
        # 判断是否更换方向,不更换则更新 self.row / self.col
        if -1 not in i and self.max_row not in i:
            if self.matrix[i[0]][i[1]] is None:
                self.row,self.col = i
                return None
        # 更换方向
        self.mark += 1
        return self.next()

    def solution(self):
        # 逐一取出 1 到 n^2 值
        for i in range(1,self.max_row**2+1):
            # 按行列赋值
            self.matrix[self.row][self.col] = i
            # 退出条件
            if i == self.max_row**2:
                break
            # 更新行列值
            self.next()
        # 打印结果
        for r in self.matrix:
            for c in r:
                print('{0:^{1}}'.format(c,self.max_row), end=' ')
            print('\n')

if __name__ == '__main__':
    n = int(input('>>>'))
    s = Spiral(n)
    s.solution()

4.答案最简洁的写法

答案最简洁的写法

n=int(raw_input("N:"))
a=[[0 for i in range(1,n+1)]for j in range(1,n+1)]
x,y,i,j=0,0,0,0
while a[i][j]==0 :
        y+=1
        a[i][j]=y
        if j<n-1 and a[i][j+1]==0 and (i==0 or (i>0 and a[i-1][j]!=0 )):
        ##括号内容可保证第四个elif从下往上的顺序正常进行
            j+=1
        elif i<n-1 and a[i+1][j]==0:
            i+=1
        elif j>0 and a[i][j-1]==0:
            j-=1
        elif  i>0 and a[i-1][j]==0:
            i-=1     
for b in a:
    print
    for c in b:
        print c,

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值