python 数组前n行和后n行相加 python怎么让数组输出n行m列_python 数组前n行和后n行相加

1月16日Python前几日王爱胜老师的蓝调百香果又出题了,深度趣味编程(打擂台)|6.数阵之中灭害虫,初看这个题目没看懂,脑子里充满了各种疑问。反复看了几遍之后,大致清晰了一些,感觉自己缺少很多知识储备,但又很感兴趣,那就一步一步来吧。没办法达到梁见斌老师哪种技术达人的高度,厉害了!!深度趣味编程(打擂)|7.数阵之中灭害虫海龟版,就根据自己的水平做点儿力所能及的,并将自己的学习过程分享给大家。


先看题

在m*n的数阵中,有很多害虫(8表示),围墙(*表示),随机生成隔壁墙(1表示),随机投放药弹(0表示),药效默认第一次可以炸毁墙继续有效,以后药效持续,但不能穿墙。 

擂1:如何向左、向下、向上消灭害虫? 

擂2:如何设置药弹威力值,可以穿透相应的墙?

擂3:其他奇思妙想~~~比如,如何不投在墙上?如何获得最大药效?如何提高程序效果等。

看了这个题目之后,我并没有看王老师的初始代码,因为感觉对我来说初始代码实现起来就是一个挑战,需要自己想尝试搞定。

1、问题的初步分析

看到m*n的数阵,我头脑中第一反应是二维数组,这是在学习c++时已经根深蒂固的认识。那么在Python中实现二维数组的方法是什么呢?元素是列表类型的列表。这个基础认识我是有的,但从未实践过。对列表这部分内容,我的认识是它是python区别于其它的语言的一大特点,很灵活,也很复杂,非常重要。这个数阵的实现需要的就是列表的赋值初值,然后显示。再根据投药结果,修改列表元素,再次显示。如此循环,直至游戏结束。因此,我把问题分解为两个步。第一步,创建列表,赋初值,输出初始地图。第二步,投药,修改列表,输出修改地图

2、算法设计

感觉没啥好写的,就是:

1)输入行列数,列表赋初值

2)输出列表

3)输入投药点

4)修改列表

5)输出列表

3、代码实现

边学编写列表赋初值的代码,用了我一个多小时的时间,列表组成的列表赋值有点蒙圈,下面着重解释一下。我试试看能不能不看我前几天写好的代码,自己再写出来一遍。

1)数阵初始效果:二维列表(姑且这么叫吧)赋初值

m=int(input('行数'))n=int(input('列数'))map_m=[] #定义行列表for i in range(m):    map_n=[] #定义列列表,map_n将是map_m的元素    for j in range(n):        map_n.append(8)    map_m.append(map_n)

还好,一次写成了。现在想想看,根本没那么难。和c++二维数组赋初值的思路基本相似,就是双重循环。有所区别的是第5、7、8行。解释一下:

第5行,因为map_n是要作为列表的一个元素的,所以每次都需要从0开始,如果将第5行移至循环体外,则map_n的值会一直增加下去,说的不太清楚,你试一下就知道了。

第7、8行是列表增加新元素的命令,不能像c++那样直接赋值(也许可以,只是我不知

道)。

2、设置随机墙

设置随机墙的方法有很多,我最开始用的是下面这种方法:

import randommap_e=[1,8,8,8,8,8,8,8,8,8]m=int(input('行数'))n=int(input('列数'))map_m=[] #定义行列表for i in range(m):    map_n=[] #定义列列表,map_n将是map_m的元素    for j in range(n):        map_n.append(map_e[random.randint(0,9)])    map_m.append(map_n)

这里第2行是存储用来生成列表元素的列表,第9行使用了随机函数,随机取1和8,这里8的数量越多,1出现的概率就越低,墙的数量就越少。

后来我发现这种方法,不利于控制1的数量,完善游戏的玩法时会增加一些麻烦,但我觉得这种用8的数量来控制1的出现的频率,并且1放在列表第一个位置,这种方法是一种小聪明,刚刚想到时还兴奋了一小下。

第2种方法是由用户输入一个难度系数,然后随机生成1。

hard=int(input('墙的数量'))while hard>0:    i=random.randint(0,m-1)    j=random.randint(0,n-1)    if map_m[i][j]==8:         map_m[i][j]=1         hard=hard-1

这种方法要注意随机数的重复可能性,所以加了一个if,确保生成足够的1。

3、输出列表

因为列表元素是列表的话,直接输出会如下图一样输出,这不符合我们需要的效果,我们需要按元素逐一输出。

python 数组前n行和后n行相加 python怎么让数组输出n行m列_初值_02

for i in range(m):    for j in range(n):        print(map_m[i][j],end=' ')    print()

效果如下图

python 数组前n行和后n行相加 python怎么让数组输出n行m列_初值_03

这里end=' '表示用空格结尾不换行,当一行输出结束后,再用print()输出一个换行符进行换行。现在的效果和王老师的图形相比少了外围的边框,属于美化方面的内容。为了使后续玩起来方便,我把*换成了行列号,稍显麻烦了一些。

print('  ',end='-')for i in range(n):    if i<10:        print(' '+str(i),end='-')    else:        print(i,end='-')print()for i in range(m):    if i<10:        print(' '+str(i),end='| ')    else:        print(str(i),end='| ')    for j in range(n):        print(map_m[i][j],end='  ')       print('|')

python 数组前n行和后n行相加 python怎么让数组输出n行m列_python 输出列表行数_04

至此,第一步基本实现了,但是由于第二步会经常使用输出列表,所以应该将上面的输出列表代码变为函数。

def disp_map(_map):    m=len(_map)   #取行数    n=len(_map[0])#取列数    print('  ',end='-')    for i in range(n):        if i<10:            print(' '+str(i),end='-')        else:            print(i,end='-')    print()    for i in range(m):        if i<10:            print(' '+str(i),end='| ')        else:            print(str(i),end='| ')        for j in range(n):            print(_map[i][j],end='  ')           print('|')

这里参数_map是列表类型。

我们还可以将列表的赋初值和墙的数量初值,即地图的生成定义为函数。

import randomdef draw_map():    m=int(input('行数'))    n=int(input('列数'))    map_m=[] #定义行列表    for i in range(m):        map_n=[] #定义列列表,map_n将是map_m的元素        for j in range(n):            map_n.append(8)        map_m.append(map_n)    hard=int(input('墙的数量'))    while hard>0:        i=random.randint(0,m-1)        j=random.randint(0,n-1)        if map_m[i][j]==8:             map_m[i][j]=1             hard=hard-1    return map_mdef disp_map(_map):    m=len(_map)   #取行数    n=len(_map[0])#取列数    print('  ',end='-')    for i in range(n):        if i<10:            print(' '+str(i),end='-')        else:            print(i,end='-')    print()    for i in range(m):        if i<10:            print(' '+str(i),end='| ')        else:            print(str(i),end='| ')        for j in range(n):            print(_map[i][j],end='  ')           print('|')                      start=draw_map()disp_map(start)

这里第19行return map_m很重要,要将生成的列表返回,否则将什么也得到。第40行map_m赋值给start,start就是以后要使用的地图,所第41行的参数是start。

4、输入投药点

这个比较简单,给出输入变量即可,这里包括坐标(行列号)即可,默认以一行从左向右为方向。

5、修改列表

这里稍微复杂一点儿,要考虑以下几点:

1)投药点是8

2)投药点是1

3)是否会再遇到1,如果遇到是第一次还是第二次,如果是第一次在穿墙继续,否则停止。

6、显示列表

直接调用disp_map即可

x=int(input('投药行'))y=int(input('投药列'))flag=0for i in range(y,len(start[0])):    if start[x][i]==1 and flag==1:        break    elif start[x][i]==1:        flag=1        start[x][i]=0    else:        start[x][i]=0disp_map(start)

python 数组前n行和后n行相加 python怎么让数组输出n行m列_python 输出列表行数_05

至此,最基本的功能就全实现了,至于那几个“擂”还没开始打。饭要一口一口的吃,骨头要一下一下的啃。