美文网首页
2020-07-26 Python学习笔记30 基础结业

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

作者: 建渐升辉 | 来源:发表于2020-07-26 22:12 被阅读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,其他参数都要进行初始值设置,或者说这些特征都要进行初始化设置。

    相关文章

      网友评论

          本文标题:2020-07-26 Python学习笔记30 基础结业

          本文链接:https://www.haomeiwen.com/subject/pvgglktx.html