2020-07-26 Python学习笔记30 基础结业

2020-07-26  本文已影响0人  建渐升辉

一些关于自己学习Python的经历的内容,遇到的问题和思考等,方便以后查询和复习。

声明:本人学习是在扇贝编程通过网络学习的,相关的知识、案例来源于扇贝编程。如果使用请说明来源。

第三十关是基础部分的结业部分,没有讲新的内容,是分步骤讲了一个比较复杂的变成,迷宫游戏。所以没有做导图。

这个拯救哪吒的迷宫游戏是我目前接触的最为复杂的程序了,因此学完之后用了两天的时间消化,才基本弄懂了每个部分。但是如果让我自己写,还是写不出来。一是有的命令什么的不太熟练,二是有的部分想的不够全面。

练习:拯救哪吒

main.py  主程序

from maze import Maze      导入迷宫模块

from nezha import Nezha     导入哪吒模块

from controller import Controller   导入控制程序模块

maze_list = [

  [1,1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],     基础数据迷宫墙的数字化,抽象化

  [1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],

  [1,0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],

  [1,0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],

  [1,1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1],

  [1,0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1],

  [1,0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1],

  [1,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],

  [1,1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],

  [1,0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],

  [1,0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],

  [1,0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],

  [1,1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]

]

Maze(maze_list)                    调用maze函数

nezha = Nezha(maze_list, 0, 5, 12, 7)   调用哪吒模块,初始位置和出口位置

Controller(nezha.go_up, nezha.go_down,nezha.go_left, nezha.go_right)  调用控制程序

Maze.py  迷宫模块

 

from turtle import Turtle   导入画图

class Maze(Turtle):        子承父业,Maze继承Turtle

 size = 20              正方形砖块边长为20

  def__init__(self, maze_list):

    # 需要先调用父类的初始化方法才能在初始化方法中调用父类的方法

   Turtle.__init__(self)    初始化

   self.maze_list = maze_list

    #为了加快绘图速度隐藏海龟,速度设为最快

   self.hideturtle()

   self.speed(0)

   self.draw_walls()   调用画墙函数

  defdraw_wall(self):   

    self.pendown()   先落下再抬笔,这样上下两行之间就不会有一条斜线了。

   self.begin_fill()

   self.fillcolor('#7392f6')

   for i in range(4):

     self.forward(self.size)

     self.right(90)

   self.end_fill()

    self.penup()    画出一块砖

  defdraw_walls(self):

    self.penup()

    #从 (-130, 130) 开始

   self.goto(-130, 130)

   for row in range(13):  13行

     for col in range(13):   13列

       if self.maze_list[row][col] == 1:  横竖交叉点上是1时,就画砖

         self.draw_wall()

        #右移一列

        self.goto(self.size * (col + 1) - 130,130 - self.size * row)  画下一块砖,下一列

      #下移一行

      self.goto(-130, 130 - self.size * (row +1))   画下一行第一块砖的位置

图(1) 图(2)

图(1)先抬笔后落笔,由于是抬笔所以没有画出线,只有动作,之所以出现墙,是因为有填充。最后落笔之后再到下一行,就拉出一条斜线在上下行之间,然后抬笔。

图(2)先落笔后抬笔,不仅能画出每块砖的轮廓,上下场之间也不会有斜线,因为画完之后是抬笔再到下一行的。

       #右移一列

       self.goto(self.size * (col + 1) - 130, 130 - self.size * row)  画下一块砖,下一列

     #下移一行

     self.goto(-130, 130 - self.size * (row + 1))   画下一行第一块砖的位置

这两行都去掉的话,整个模块只画出一块砖,没有到下一列,也没有到下一行

如果上一行去掉,只画出第一列,即每行的第一块砖,系统不会跳到下一列

如果只是后一行去掉的话,第一列的会画到最后一列的后面,并且向上错一行,为什么这样呢?最初我的想法应该是第一列不出现的。

经过长期的思考,愚钝的我才弄明白原因,当row=0,cul遍历0-12之后,由于第二个self.goto去掉了,画笔没有到第二行第一个砖块的位置,还在第一行最后一列的后面,此时进入下一个循环,即row=1,col=0是,调用了画砖程序,于是就继续了一块砖,然后画笔跳到第二行的第二列,即row=1,col=1,这样系统从第二行开始就从每一行的第二列开始画,而第一块砖都画到上一行的末尾了,因为没有告诉画笔要转场。

结果见下图(3)

 

图(3)

nezha.py  哪吒模块

from turtle import Turtle

class Nezha(Turtle):

  def__init__(self, maze_list, start_m, start_n,end_m, end_n):

    #前文中没有考虑出口,是没有这两个参数的。

    #父类初始化

   Turtle.__init__(self)

   self.maze_list = maze_list

   self.m = start_m

   self.n = start_n

   self.end_n = end_n

   self.end_m = end_m

   self.hideturtle()

   self.speed(0)

   self.penup()

    #移到对应的位置

    self.goto(self.n * 20 - 120, 120 - self.m *20)  #如果用130会怎样呢?

    #变成海龟

   self.shape('turtle')

   self.color('#28bea0')

   self.setheading(270)

   self.showturtle()

    #添加哪吒图片作为形状

    screen = self.getscreen()   这句话不理解

   screen.addshape('nezha.png')  实际软件环境只能用jpg格式的图片

  defreach_exit(self, m, n):   判断到达出口

   if m == self.end_m and n == self.end_n:

     self.shape('nezha.png')

     #再次变身回来成哪吒

  defcanmove(self, m, n):   限制移动范围,为零的时候才能走

   return self.maze_list[m][n] == 0

  defmove(self, m, n): #移动程序

   self.m = m

   self.n = n

   self.goto(self.n * 20 - 120, 120 - self.m * 20)

   self.reach_exit(m, n)

  defgo_up(self):

   if self.canmove(self.m - 1, self.n):

     self.setheading(90)

     self.move(self.m - 1, self.n)

  defgo_down(self):

   if self.canmove(self.m + 1, self.n):

     self.setheading(270)

     self.move(self.m + 1, self.n)

  defgo_left(self):

   if self.canmove(self.m, self.n - 1):

     self.setheading(180)

     self.move(self.m, self.n - 1)

  defgo_right(self):

   if self.canmove(self.m, self.n + 1):

     self.setheading(0)

     self.move(self.m, self.n + 1)

图(4)

图(4)self.goto(self.n * 20 - 130,130 - self.m * 20)  

图(5)

图(5)self.goto(self.n * 20 - 120, 120 - self.m *20)

controller.py  控制模块

from turtle import Turtle

class Controller(Turtle):

  def__init__(self, go_up, go_down, go_left, go_right):

    #父类初始化

   Turtle.__init__(self)

    #初始值设置

   self.go_up = go_up

   self.go_down = go_down

   self.go_left = go_left

   self.go_right = go_right

    #绘制控制器

   self.hideturtle()

   self.speed(0)

   self.draw_btn('上', -162, 130)

   self.draw_btn('下', 132, 130)

   self.draw_btn('左', -162, -100)

   self.draw_btn('右', 132, -100)

    # 绑定点击事件,通过点击获得相应的位置坐标,指挥海龟的移动。点击区域移动海龟

    screen = self.getscreen()

    screen.onclick(self.handlescreenclick)   对应下文的区域定义。

  defdraw_btn(self, name, x, y):

   self.penup()

   self.goto(x, y)

   self.begin_fill()

   self.fillcolor('#000000')

   for i in range(4):

     self.forward(30)

     self.right(90)

   self.end_fill()

   self.color('#ffffff')

   self.goto(x + 7, y - 20)

   self.write(name, font = ('SimHei', 12, 'bold'))

  def handlescreenclick(self, x,y):  #屏幕点击处理,就是点击不同的位置,控制海龟的行动

    if x < 0 and y > 0:

      self.go_up()

    if x > 0 and y > 0:

      self.go_down()

    if x < 0 and y < 0:

      self.go_left()

    if x > 0 and y < 0:

      self.go_right()

# 这段程序的好处是,点击一个区域就可以调动海龟的移动,这些区域分别是四个象限,而不是只能点击一个图标。

但是不好的地方是不够直观,比如想让海龟向下的时候,点击的是第一象限,而第一象限是在迷宫偏上的位置的。

   self.draw_btn('上', -162, 130)

    self.draw_btn('下', 132, 130)

   self.draw_btn('左', -162, -100)

   self.draw_btn('右', 132, -100)

图标画出来在迷宫的四个角,也是不够直观,比如下在右上角,迷宫的上半部分。图(6)

图(6) 图7

self.draw_btn('上', -15, 162)

   self.draw_btn('下', -15, -132)

   self.draw_btn('左', -162, 15)

self.draw_btn('右', 132, 15)

图标画出来之后,分别在上下左右,这样和我们的习惯更为一致,图(7)

但是点击上下左右图标,小乌龟不变,原来不是上下左右起作用,是定义的四个象限在起作用,于是我修改了上下左右的范围:

def handlescreenclick(self, x, y):   

   if -130 < x < 130 and y > 130:

     self.go_up()

   if -130 < x < 130 and y < -130:

     self.go_down()

   if x < -130 and -130 < y < 130:

     self.go_left()

   if x > 130 and  -130 < y< 130:

     self.go_right()

这样点击迷宫的上下左右区域,就能够指挥小乌龟上下左右的移动了,比较直观,而不是四个象限,总感觉和习惯不一致。

至此,我基本对这个题目中程序理解的比较全面的。但是感觉比较薄弱的地方是,各个模块之间的调用,尤其是参数的设置以及各个模块之间数据的传递等如果不看答案,感觉还是想的不够周全。还有就是初始化的部分

在主程序中导入各个模块,前面是模块名称,后面是各个模块定义的类的名称

Maze(maze_list)

nezha = Nezha(maze_list, 0, 5, 12, 7)

Controller(nezha.go_up, nezha.go_down,nezha.go_left, nezha.go_right)

通过主程序调用各个模块,调用Maze迷宫模块要用到迷宫数字列表maze_list

调用nezha要用的模块数字列表和入口位置0,5,以及户口位置12,7

调用controller模块,要用到nezha模块中的上下左右程序。

每个模块先导入海龟绘画功能

然后建立一个类继承Turtle的画图功能

from turtle import Turtle

class Maze(Turtle):

 size = 20

  def__init__(self, maze_list):  要用到maze_list

Turtle.__init__(self) 还要对父类进行初始化,才能调用

# 需要先调用父类的初始化方法才能在初始化方法中调用父类的方法

from turtle import Turtle

class Nezha(Turtle):

  def__init__(self, maze_list, start_m, start_n, end_m, end_n):

# 要用到maze_list,开始和结束的行列数字

Turtle.__init__(self) 还要对父类进行初始化,才能调用

from turtle import Turtle

class Controller(Turtle):

  def__init__(self, go_up, go_down, go_left, go_right):

# 控制要用到后面设置的上下作用范围设置数据

Turtle.__init__(self) 还要对父类进行初始化,才能调用

初始化时设置的特征和初始化中的参数是相关的,在参数中出现,就要在后面进行初始值设置。除了self,其他参数都要进行初始值设置,或者说这些特征都要进行初始化设置。

上一篇下一篇

猜你喜欢

热点阅读