zoukankan      html  css  js  c++  java
  • python 之路,200行Python代码写了个打飞机游戏!

    早就知道pygame模块,就是没怎么深入研究过,恰逢这周未没约到妹子,只能自己在家玩自己啦,一时兴起,花了几个小时写了个打飞机程序。

    很有意思,跟大家分享下。

    先看一下项目结构

    """
    PlayPlane/
    |-- bin/
    |   |-- main.py         程序运行主体程序
    |-- config/
    |   |-- settings.py     程序配置(例如: 游戏背景音乐的加载等)
    |-- material            程序素材放置(打飞机游戏素材放置)
        |-- ...
    |-- src/                程序主体模块存放
    |   |-- __init__.py 
    |   |-- bullet.py       我方飞机发射子弹实现代码存放
    |   |-- enemy.py        敌方飞机实现代码存放
    |   |-- plane.py        我方飞机实现代码存放
    |-- manage.py           程序启动文件
    |-- README.md           
    """
    

    再晒下项目成果图

    实现步骤

    一、首先在 config/settings.py 中进行以下功能的实现

    • 游戏初始化
    • 游戏混音器初始化
    • 背景音乐初始化
    • 我方飞机挂了音乐
    • 敌方飞机挂了音乐
    • 子弹发射音乐
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import pygame
    
    pygame.init()  # 游戏初始化
    pygame.mixer.init()  # 混音器初始化
    
    # 游戏背景音乐
    pygame.mixer.music.load("material/sound/game_music.wav")
    pygame.mixer.music.set_volume(0.2)
    
    # 子弹发射音乐
    bullet_sound = pygame.mixer.Sound("material/sound/bullet.wav")
    bullet_sound.set_volume(0.2)
    
    # 我方飞机挂了的音乐
    me_down_sound = pygame.mixer.Sound("material/sound/game_over.wav")
    me_down_sound.set_volume(0.2)
    
    # 敌方飞机挂了的音乐
    enemy1_down_sound = pygame.mixer.Sound("material/sound/enemy1_down.wav")
    enemy1_down_sound.set_volume(0.2)
    
    config/settings.py
    

    注:游戏素材滑动到文章底部点击链接即可下载  

    二、小试牛刀

    飞机和子弹都是可移动的,那么怎么实现让它们动起来呢(我方飞机可以玩家进行操控,敌机就是随机性的出现,子弹暂由我方飞机发射)。

    在Pygame中,所有移动对象都可看做是一个精灵(sprite),精灵之间能够进行相互的交互通信,例如如何让碰撞检测更加精准等等。

    那么先让我们先在屏幕上制作一个游戏板,根据 settings.py 配置,并让它有声音播放,首先我们在 bin/main.py 中这么写:

      我们可以直接运行它,那么我们会看到以下画面,并且还会有激情的声音吆!!!但是我们要将文件配置为绝对路径才可以运行,因为刚刚在settings中的加载的音乐文件为相对路径。

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import sys
    
    from config.settings import *
    
    
    bg_size = 480, 852  # 初始化游戏背景大小(宽, 高)
    screen = pygame.display.set_mode(bg_size)  # 设置背景对话框
    pygame.display.set_caption("飞机大战")  # 设置标题
    
    background = pygame.image.load(os.path.join(BASE_DIR, "material/image/background.png"))  # 加载背景图片,并设置为不透明
    
    
    def main():
        pygame.mixer.music.play(loops=-1)  # loops 对应的值为 -1 则音乐会无限循环播放
    
        while True:
            # 绘制背景图
            screen.blit(background, (0, 0))
    
            # 响应用户的操作(一定要有响应的用户操作)
            for event in pygame.event.get():
                if event.type == 12:  # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出
                    pygame.quit()
                    sys.exit()
    
            # 再而我们将背景图像并输出到屏幕上面
            pygame.display.flip()
    
    if __name__ == '__main__':
        main()
    

      

    接下来呢,我们将要制作我方飞机,敌方飞机和子弹如何让它们展示在游戏画板上,继而让它们变得可移动起来,请看代码实现方案...

    从游戏画板上添加飞机,首先我们应怎样在屏幕上输出飞机???

    上述讲过,pygame中的 sprite(精灵)可使一张图片或者一个静态物体动起来,那么制作飞机需要考虑并做些什么呢?

    1. 飞机的初始位置
    2. 通过按键 上下左右 来调控飞机的位置移动
    3. 飞机只能呆在制作的游戏画板中
    4. 飞机的速度
    5. 飞机死亡的加载
    6. 设定一个状态标识飞机的存活
    7. 让飞机具有动态的喷气式效果

    那么如何实现以上的功能呢?接下来结合上述的示例代码我们先将我方飞机绘制到画板上方,并且我们通过按键 J 判定我方飞机的存活状态为死亡,绘制飞机的死亡画面并重置飞机

    """
        创建飞机
        在pygame中, 所有可移动的对象均叫可看作一个精灵(sprite)
        该类并实现了碰撞方法 spritecollide
    
        我方飞机和敌方飞机指定掩膜属性以及生存状态标志位 添加 self.mask 属性(可以实现更精准的碰撞效果)
    """
    
    # 倒入精灵模块, 使飞机可以动起来
    import pygame
    
    
    class OurPlane(pygame.sprite.Sprite):
    
        def __init__(self, bg_size):
            super(OurPlane, self).__init__()
            # 确定我方飞机背景图(有俩张,可以让它们不停的切换,形成动态效果)
            self.image_one = pygame.image.load("material/image/hero1.png")
            self.image_two = pygame.image.load("material/image/hero2.png")
            # 获取我方飞机的位置
            self.rect = self.image_one.get_rect()
            # 本地化背景图片的尺寸
            self.width, self.height = bg_size[0], bg_size[1]
            # 获取飞机图像的掩膜用以更加精确的碰撞检测
            self.mask = pygame.mask.from_surface(self.image_one)
            # 定义飞机初始化位置,底部预留60像素
            self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60)
            # 设置飞机移动速度
            self.speed = 10
            # 设置飞机存活状态(True为存活, False为死亡)
            self.active = True
            # 加载飞机损毁图片
            self.destroy_images = []
            self.destroy_images.extend(
                [
                    pygame.image.load("material/image/hero_blowup_n1.png"),
                    pygame.image.load("material/image/hero_blowup_n2.png"),
                    pygame.image.load("material/image/hero_blowup_n3.png"),
                    pygame.image.load("material/image/hero_blowup_n4.png")
                ]
            )
    
        def move_up(self):
            """
            飞机向上移动的操作函数,其余移动函数方法类似
            """
            if self.rect.top > 0:  # 如果飞机尚未移动出背景区域
                self.rect.top -= self.speed
            else:  # 若即将移动出背景区域,则及时纠正为背景边缘位置
                self.rect.top = 0
    
        def move_down(self):
            """
            飞机向下移动
            """
            if self.rect.bottom < self.height - 60:
                self.rect.top += self.speed
            else:
                self.rect.bottom = self.height - 60
    
        def move_left(self):
            """
            飞机向左移动
            """
            if self.rect.left > 0:
                self.rect.left -= self.speed
            else:
                self.rect.left = 0
    
        def move_right(self):
            """
            飞机向右移动
            """
            if self.rect.right < self.
                self.rect.right += self.speed
            else:
                self.rect.right = self.width
    
        def reset(self):
            # 初始化飞机(飞机挂了, 初始化到初始位置)
            self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60)
            # 重置飞机的存活状态
            self.active = True
    

      

    上面的代码写了一个 我们的飞机 (OurPlane) 类,它初始化了一些属性以及 上下左右 移动的方法和重置方法,接下来将要运用它展示到游戏画板上面

    由于飞机是一直存在的,接下我们主程序 main 下面的死循环中这样写

    def main():
        pygame.mixer.music.play(loops=-1)  # loops 对应的值为 -1 则音乐会无限循环播放
    
        our_plane = OurPlane(bg_size)  # 初始化
        switch_image = False  # 定义飞机的切图效果标识
    
        while True:
            # 绘制背景图
            screen.blit(background, (0, 0))
    
            # 飞机状态是存活
            if our_plane.active:
    
                if switch_image:
                    screen.blit(our_plane.image_one, our_plane.rect)
                else:
                    screen.blit(our_plane.image_two, our_plane.rect)
    
                switch_image = not switch_image  # 让切图状态不停的变换
            else:
                pass
    
            # 响应用户的操作(一定要有响应的用户操作)
            for event in pygame.event.get():
                if event.type == 12:  # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出
                    pygame.quit()
                    sys.exit()
    
            # 再而我们将背景图像并输出到屏幕上面
            pygame.display.flip()
    
    if __name__ == '__main__':
        main()
    1.在屏幕上绘制飞机
    def main():
        pygame.mixer.music.play(loops=-1)  # loops 对应的值为 -1 则音乐会无限循环播放
    
        our_plane = OurPlane(bg_size)  # 初始化
        switch_image = False  # 定义飞机的切图效果标识
    
        while True:
            # 绘制背景图
            screen.blit(background, (0, 0))
    
            # 飞机状态是存活
            if our_plane.active:
    
                if switch_image:
                    screen.blit(our_plane.image_one, our_plane.rect)
                else:
                    screen.blit(our_plane.image_two, our_plane.rect)
    
                switch_image = not switch_image  # 让切图状态不停的变换
            else:
                pass
    
            # 获得用户所有的键盘输入序列(如果用户通过键盘发出“向上”的指令,其他类似)
            key_pressed = pygame.key.get_pressed()
            if key_pressed[K_w] or key_pressed[K_UP]:
                our_plane.move_up()
            if key_pressed[K_s] or key_pressed[K_DOWN]:
                our_plane.move_down()
            if key_pressed[K_a] or key_pressed[K_LEFT]:
                our_plane.move_left()
            if key_pressed[K_d] or key_pressed[K_RIGHT]:
                our_plane.move_right()
    
            # 响应用户的操作(一定要有响应的用户操作)
            for event in pygame.event.get():
                if event.type == 12:  # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出
                    pygame.quit()
                    sys.exit()
    
            # 再而我们将背景图像并输出到屏幕上面
            pygame.display.flip()
    
    if __name__ == '__main__':
        main()
    2.让飞机上下左右动起来
    def main():
        pygame.mixer.music.play(loops=-1)  # loops 对应的值为 -1 则音乐会无限循环播放
    
        our_plane = OurPlane(bg_size)  # 初始化
        switch_image = False  # 定义飞机的切图效果标识
    
        our_plane_destroy_index = 0
    
        while True:
            # 绘制背景图
            screen.blit(background, (0, 0))
    
            # 飞机状态是存活(如果按键 为 J, 让飞机死亡并绘制爆炸效果)
            if our_plane.active:
    
                if switch_image:
                    screen.blit(our_plane.image_one, our_plane.rect)
                else:
                    screen.blit(our_plane.image_two, our_plane.rect)
    
                switch_image = not switch_image  # 让切图状态不停的变换
            else:
                """
                飞机死亡也是进行按顺序的图片切换, 那么在死循环之外定义索引
                """
                me_destroy_index = (our_plane_destroy_index + 1) % 4
                if me_destroy_index == 1:
                    me_down_sound.play()  # 爆炸声音效果
                    our_plane.reset()  # 初始化飞机
                if our_plane_destroy_index >= len(our_plane.destroy_images):
                    our_plane_destroy_index = 0
                else:
                    screen.blit(our_plane.destroy_images[our_plane_destroy_index], our_plane.rect)
    
                our_plane_destroy_index += 1
    
            # 获得用户所有的键盘输入序列(如果用户通过键盘发出“向上”的指令,其他类似)
            key_pressed = pygame.key.get_pressed()
            if key_pressed[K_w] or key_pressed[K_UP]:
                our_plane.move_up()
            if key_pressed[K_s] or key_pressed[K_DOWN]:
                our_plane.move_down()
            if key_pressed[K_a] or key_pressed[K_LEFT]:
                our_plane.move_left()
            if key_pressed[K_d] or key_pressed[K_RIGHT]:
                our_plane.move_right()
    
            # 按键为 j 飞机更改存活标识
            if key_pressed[K_j]:
                our_plane.active = False
    
            # 响应用户的操作(一定要有响应的用户操作)
            for event in pygame.event.get():
                if event.type == 12:  # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出
                    pygame.quit()
                    sys.exit()
    
            # 再而我们将背景图像并输出到屏幕上面
            pygame.display.flip()
    3.按键为 j 绘制飞机的死亡状态

    那么上述的功能都已经实现了,接下来就开始真正的"打飞机"

    三、接下来可以制作我方飞机,敌方战机,子弹等,这些功能均在 src/ 目录下实现

    • 我方飞机根据按键上下左右进行移动,初始化位置,喷气式图片加载切换及重置效果等
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    """
        创建飞机
        在pygame中, 所有可移动的对象均叫可看作一个精灵(sprite)
        该类并实现了碰撞方法 spritecollide
    
        我方飞机和敌方飞机指定掩膜属性以及生存状态标志位 添加 self.mask 属性(可以实现更精准的碰撞效果)
    """
    
    # 倒入精灵模块, 使飞机可以动起来
    import pygame
    
    
    class OurPlane(pygame.sprite.Sprite):
    
        def __init__(self, bg_size):
            super(OurPlane, self).__init__()
            # 确定我方飞机背景图
            self.image_one = pygame.image.load("material/image/hero1.png")
            self.image_two = pygame.image.load("material/image/hero2.png")
            # 获取我方飞机的位置
            self.rect = self.image_one.get_rect()
            # 本地化背景图片的尺寸
            self.width, self.height = bg_size[0], bg_size[1]
            # 获取飞机图像的掩膜用以更加精确的碰撞检测
            self.mask = pygame.mask.from_surface(self.image_one)
            # 定义飞机初始化位置,底部预留60像素
            self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60)
            # 设置飞机移动速度
            self.speed = 10
            # 设置飞机存活状态(True为存活, False为死亡)
            self.active = True
            # 加载飞机损毁图片
            self.destroy_images = []
            self.destroy_images.extend(
                [
                    pygame.image.load("material/image/hero_blowup_n1.png"),
                    pygame.image.load("material/image/hero_blowup_n2.png"),
                    pygame.image.load("material/image/hero_blowup_n3.png"),
                    pygame.image.load("material/image/hero_blowup_n4.png")
                ]
            )
    
        def move_up(self):
            """
            飞机向上移动的操作函数,其余移动函数方法类似
            """
            if self.rect.top > 0:  # 如果飞机尚未移动出背景区域
                self.rect.top -= self.speed
            else:  # 若即将移动出背景区域,则及时纠正为背景边缘位置
                self.rect.top = 0
    
        def move_down(self):
            if self.rect.bottom < self.height - 60:
                self.rect.top += self.speed
            else:
                self.rect.bottom = self.height - 60
    
        def move_left(self):
            if self.rect.left > 0:
                self.rect.left -= self.speed
            else:
                self.rect.left = 0
    
        def move_right(self):
            if self.rect.right < self.
                self.rect.right += self.speed
            else:
                self.rect.right = self.width
    
        def reset(self):
            # 初始化飞机(飞机挂了, 初始化到初始位置)
            self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60)
            self.active = True
    
    src/plane.py
    src/plane.py
    • 敌方飞机随机移动出现及重置(制作出我方飞机之后,敌机和子弹其实都是大同小异的)
    • #! /usr/bin/env python
      # -*- coding: utf-8 -*-
      
      """
          定义敌机
      """
      
      from random import randint
      
      import pygame
      
      
      class SmallEnemy(pygame.sprite.Sprite):
          """
          定义小飞机敌人
          """
          def __init__(self, bg_size):
              super(SmallEnemy, self).__init__()
              self.image = pygame.image.load("material/image/enemy1.png")
              self.rect = self.image.get_rect()
              self.width, self.height = bg_size[0], bg_size[1]
              self.mask = pygame.mask.from_surface(self.image)  # 获取飞机图像的掩膜用以更加精确的碰撞检测
              self.speed = 2
              # 定义敌机出现的位置, 保证敌机不会在程序已开始就立即出现
              self.rect.left, self.rect.top = (
                  randint(0, self.width - self.rect.width),  randint(-5 * self.rect.height, -5),
              )
              self.active = True
              # 加载飞机损毁图片
              self.destroy_images = []
              self.destroy_images.extend(
                  [
                      pygame.image.load("material/image/enemy1_down1.png"),
                      pygame.image.load("material/image/enemy1_down2.png"),
                      pygame.image.load("material/image/enemy1_down3.png"),
                      pygame.image.load("material/image/enemy1_down4.png")
                  ]
              )
      
          def move(self):
              """
              定义敌机的移动函数
              :return:
              """
              if self.rect.top < self.height:
                  self.rect.top += self.speed
              else:
                  self.reset()
      
          def reset(self):
              """
              当敌机向下移动出屏幕时, 以及敌机死亡
              :return:
              """
              self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width), randint(-5 * self.rect.height, 0))
              self.active = True
      src/enemy.py
    • 子弹按照我方飞机正中上方发射及频率调控,重置
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    """
        子弹的实现
    """
    
    import pygame
    
    
    class Bullet(pygame.sprite.Sprite):
    
        def __init__(self, position):
            super(Bullet, self).__init__()
            self.image = pygame.image.load("material/image/bullet1.png")
            self.rect = self.image.get_rect()
            self.rect.left, self.rect.top = position
            self.speed = 30
            self.active = True
            self.mask = pygame.mask.from_surface(self.image)
    
        def move(self):
            """
            子弹移动, 超出屏幕范围, 则设置死亡
            :return:
            """
            if self.rect.top < 0:
                self.active = False
            else:
                self.rect.top -= self.speed
    
        def reset(self, position):
            """
            复位函数
            :param position:
            :return:
            """
            self.rect.left, self.rect.top = position
            self.active = True
    
    src/bullet.py
    src/bullet.py

    在上面的内容中,使用面向对象的形式制作了游戏中可移动的对象并继承 pygame.sprite.Sprite 

    四、然后在 bin/main.py 中进行主体功能的实现

    • 初始化背景图及大小
    • 我方飞机移动及发射子弹
    • 敌方飞机移动
    • 我方飞机和敌方飞机碰撞检测
    • 键盘按键监测效果
    • 我方飞机和敌方飞机挂了效果绘制
    import sys
    
    from pygame.locals import *
    
    from config.settings import *
    from src.plane import OurPlane
    from src.enemy import SmallEnemy
    from src.bullet import Bullet
    
    
    bg_size = 480, 852  # 初始化游戏背景大小(宽, 高)
    screen = pygame.display.set_mode(bg_size)  # 设置背景对话框
    pygame.display.set_caption("飞机大战")  # 设置标题
    
    background = pygame.image.load("material/image/background.png")  # 加载背景图片,并设置为不透明
    
    # 获取我方飞机
    our_plane = OurPlane(bg_size)
    
    
    def add_small_enemies(group1, group2, num):
        """
        添加小型敌机
        指定个敌机对象添加到精灵组(sprite.group)
        参数group1、group2是两个精灵组类型的形参,用以存储多个精灵对象(敌机)。
        需要注意的一点是group既然是特定的精灵组结构体,在向其内部添加精灵对象时需要调用其对应的成员函数add()
        :return:
        """
        for i in range(num):
            small_enemy = SmallEnemy(bg_size)
            group1.add(small_enemy)
            group2.add(small_enemy)
    
    
    def main():
        # 响应音乐
        pygame.mixer.music.play(-1)  # loops 接收该参数, -1 表示无限循环(默认循环播放一次)
        running = True
        switch_image = False  # 切换飞机的标识位(使飞机具有喷气式效果)
        delay = 60  # 对一些效果进行延迟, 效果更好一些
    
        enemies = pygame.sprite.Group()  # 生成敌方飞机组(一种精灵组用以存储所有敌机精灵)
        small_enemies = pygame.sprite.Group()  # 敌方小型飞机组(不同型号敌机创建不同的精灵组来存储)
    
        add_small_enemies(small_enemies, enemies, 4)  # 生成若干敌方小型飞机
    
        # 定义子弹, 各种敌机和我方敌机的毁坏图像索引
        bullet_index = 0
        e1_destroy_index = 0
        me_destroy_index = 0
    
        # 定义子弹实例化个数
        bullet1 = []
        bullet_num = 6
        for i in range(bullet_num):
            bullet1.append(Bullet(our_plane.rect.midtop))
    
        while running:
    
            # 绘制背景图
            screen.blit(background, (0, 0))
    
            # 微信的飞机貌似是喷气式的, 那么这个就涉及到一个帧数的问题
            clock = pygame.time.Clock()
            clock.tick(60)
    
            # 绘制我方飞机的两种不同的形式
            if not delay % 3:
                switch_image = not switch_image
    
            for each in small_enemies:
                if each.active:
                    # 随机循环输出小飞机敌机
                    for e in small_enemies:
                        e.move()
                        screen.blit(e.image, e.rect)
                else:
                    if e1_destroy_index == 0:
                        enemy1_down_sound.play()
                    screen.blit(each.destroy_images[e1_destroy_index], each.rect)
                    e1_destroy_index = (e1_destroy_index + 1) % 4
                    if e1_destroy_index == 0:
                        each.reset()
    
            # 当我方飞机存活状态, 正常展示
            if our_plane.active:
                if switch_image:
                    screen.blit(our_plane.image_one, our_plane.rect)
                else:
                    screen.blit(our_plane.image_two, our_plane.rect)
    
                # 飞机存活的状态下才可以发射子弹
                if not (delay % 10):  # 每十帧发射一颗移动的子弹
                    bullet_sound.play()
                    bullets = bullet1
                    bullets[bullet_index].reset(our_plane.rect.midtop)
                    bullet_index = (bullet_index + 1) % bullet_num
    
                for b in bullets:
                    if b.active:  # 只有激活的子弹才可能击中敌机
                        b.move()
                        screen.blit(b.image, b.rect)
                        enemies_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
                        if enemies_hit:  # 如果子弹击中飞机
                            b.active = False  # 子弹损毁
                            for e in enemies_hit:
                                e.active = False  # 小型敌机损毁
    
            # 毁坏状态绘制爆炸的场面
            else:
                if not (delay % 3):
                    screen.blit(our_plane.destroy_images[me_destroy_index], our_plane.rect)
                    me_destroy_index = (me_destroy_index + 1) % 4
                    if me_destroy_index == 0:
                        me_down_sound.play()
                        our_plane.reset()
    
            # 调用 pygame 实现的碰撞方法 spritecollide (我方飞机如果和敌机碰撞, 更改飞机的存活属性)
            enemies_down = pygame.sprite.spritecollide(our_plane, enemies, False, pygame.sprite.collide_mask)
            if enemies_down:
                our_plane.active = False
                for row in enemies:
                    row.active = False
    
            # 响应用户的操作
            for event in pygame.event.get():
                if event.type == 12:  # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出
                    pygame.quit()
                    sys.exit()
    
            if delay == 0:
                delay = 60
            delay -= 1
    
            # 获得用户所有的键盘输入序列(如果用户通过键盘发出“向上”的指令,其他类似)
            key_pressed = pygame.key.get_pressed()
            if key_pressed[K_w] or key_pressed[K_UP]:
                our_plane.move_up()
            if key_pressed[K_s] or key_pressed[K_DOWN]:
                our_plane.move_down()
            if key_pressed[K_a] or key_pressed[K_LEFT]:
                our_plane.move_left()
            if key_pressed[K_d] or key_pressed[K_RIGHT]:
                our_plane.move_right()
    
            # 绘制图像并输出到屏幕上面
            pygame.display.flip()
    bin/main.py

    五、畅汗淋漓,一气呵成打飞机

    from bin.main import main
    
    
    if __name__ == '__main__':
        """
        环境: python3 + pygame
        running 起来就可以打飞机了O(∩_∩)O~.
        """
        main()
    

      

    最终效果!

    完整项目代码 : https://github.com/triaquae/jerkoff 

    另外,本项目所用到的基础知识视频 已上传至 路飞学城 ,需要者自取! http://luffy.oldboyedu.com/course/detail/python/5 

  • 相关阅读:
    48. Rotate Image
    47. Permutations II
    46. Permutations
    45. Jump Game II
    44. Wildcard Matching
    43. Multiply Strings
    42. Trapping Rain Water
    41. First Missing Positive
    40. Combination Sum II
    39. Combination Sum
  • 原文地址:https://www.cnblogs.com/alex3714/p/7966656.html
Copyright © 2011-2022 走看看