• 20182324 2019-2020-2 《Python 程序设计》实验4报告


    20182324 2019-2020-2 《Python 程序设计》实验4报告

    课程:《Python 程序设计》
    班级: 1823
    姓名: yyh
    学号: 20182324
    实验教师:王志强
    实验日期:2020年6月10日
    必修/选修: 公选课

    1. 实验内容

    • Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。

    • 本次实践选择 pygame 制作微信的飞机大战游戏,采取主要代码参考网上,细节处理自己改动的方式

      • 为什么要选择 pygame ?
        爬虫太简单,只需要掌握基础 HTML 知识即可,在学习了 Web 程序开发后对爬虫有了一定的了解;数据处理是一个值得学习的领域,做好了能够实现自动化,目前已有初步了解; pygame 从来没碰过,是一片全新的值得挑战的领域;机器学习、网络安全较难,在有限的时间内暂不考虑。相比之下,从学习更多新知识的角度考虑,我选择了有一定难度与综合性,但又不至于花费太多精力,能够快速入门的 pygame 进行实验。

      • 这次实验的代码完全是自己写的吗?
        我可以很负责地说:不是。因为自己对于 pygame 完全是零基础,因此主要代码是参考网上别人写的,进行一些具有自己想法的改动。正如上学期学 Java 时王老师所说:加点代码,改点代码是理解的最好方式。

      • 为什么没有自己从头至尾地写代码?
        众所周知,互联网带来很大的一个好处就是可以借鉴。与其从什么是 pygame、怎么创建 pygame 这样一章一章地固化学习(甚至很可能学完就忘了),最后做出一个完全不实用、不好看的程序,不如直接在别人的基础上进行扩展,通过推敲与学习别人是怎么写这些代码的,从而达到理解这些方法的效果。

      • 自己在这次实验上进行了哪些改动?
        这次实验查找的网上代码主要实现了飞机的左右水平移动、发射子弹等功能。自己在其基础上,增添了飞机上下竖直移动、鼠标按键发射子弹、结果显示与统计等功能。

      • 在这些改动中学到了什么?
        通过学习既有代码,了解了 pygame 游戏代码的基本结构,了解了事件的组成,游戏的进行即是一个又一个事件的发生与重复;通过研究既有左右移动的功能,对键盘事件有了一定的认识,并在此基础上扩展至了上下左右移动(包括我们熟知的 WSAD 移动);主动学习了鼠标事件,实现了鼠标按键发射子弹的功能;主动学习了 EasyGUI,实现了登录与统计界面,也为下一步的可视化设计打了一定基础。

    2. 实验过程及结果

    • 直接借鉴的主程序就不用说了,主要谈谈自己进行的改动

    • (1) 通过 pygame.key.get_pressed() 事件判断键盘按键,实现 ↑ ↓ ← → 和 W A S D 两种按键方式对飞机进行移动

              # 右键或D
              if keys_pressed[pygame.K_RIGHT] or keys_pressed[pygame.K_d]:
                  self.hero.speed = 4
              # 左键或A
              elif keys_pressed[pygame.K_LEFT] or keys_pressed[pygame.K_a]:
                  self.hero.speed = -4
              # 上键或W
              elif keys_pressed[pygame.K_UP] or keys_pressed[pygame.K_w]:
                  self.hero.speed = -4
              # 下键或S
              elif keys_pressed[pygame.K_DOWN] or keys_pressed[pygame.K_s]:
                  self.hero.speed = 4
      

      通过按键判断是水平还是竖直方向上的移动

              if keys_pressed[pygame.K_RIGHT] or keys_pressed[pygame.K_LEFT] 
                      or keys_pressed[pygame.K_a] or keys_pressed[pygame.K_d]:
                  # 我方战机在水平方向移动
                  self.rect.x += self.speed
              elif keys_pressed[pygame.K_UP] or keys_pressed[pygame.K_DOWN] 
                      or keys_pressed[pygame.K_w] or keys_pressed[pygame.K_s]:
                  # 我方战机在竖直方向移动
                  self.rect.y += self.speed
      
    • (2) 通过 pygame.key.get_pressed() 判断键盘按键实现空格发射子弹,并通过 pygame.mouse.get_pressed() 判断鼠标按键实现鼠标左键发射子弹

              # 使用键盘提供的方法获取键盘按键 - 按键元组
              keys_pressed = pygame.key.get_pressed()
              # 使用鼠标提供的方法获取是否按下鼠标左键
              mouse_pressed = pygame.mouse.get_pressed()
              # 空格或鼠标左键发射子弹
              if keys_pressed[pygame.K_SPACE] or mouse_pressed[0]:
      
                  # 1. 创建子弹精灵
                  bullet = Bullet()
      
                  # 2. 设置精灵的位置
                  bullet.rect.bottom = self.rect.y
                  bullet.rect.centerx = self.rect.centerx
      
                  # 3. 将精灵添加到精灵组
                  self.bullets.add(bullet)
      
    • (3) 启动游戏需输入用户名,若不输入则系统自动指派一个,该用户名仅用于统计排行榜。通过 EasyGUI 的 enterbox 实现。

              # 输入用户名
              userid = g.enterbox("请输入用户名:", "登录", "20182324yyh")
              # 如果不输入用户名,则为其默认指定一个
              if userid == "" or userid == None:
                  userid = "游客" + str(random.randint(1000, 10000))
      
    • (4) 在游戏界面的左上角实时显示玩家名称与得分。通过 pygame.font.SysFont 和 screen.blit 方法实现。

              game_user = pygame.font.SysFont('simsunnsimsun', 20, True)  # 字体
              self.screen.blit(game_user.render(u'%s' % userid, True, [0, 0, 0]), [20, 20])  # 显示用户名
              game_font = pygame.font.SysFont('simsunnsimsun', 20, True)  # 字体
              self.screen.blit(game_font.render(u'当前得分:%d' % sum, True, [0, 0, 0]), [20, 40])  # 显示实时得分
      
    • (5) 游戏结束后弹框显示本次游戏的得分,并可选择查看排行榜。得分弹框通过 EasyGUI 的 ccbox 实现,排行榜通过 EasyGUI 的 textbox 实现,数据存入 sqlite 数据库中。数据库中共有三个字段:Unix 时间戳(主键)、玩家名称、玩家得分。在输出排行榜时需对 Unix 时间戳进行还原处理。

              sql()
              box = g.ccbox("用户 " + userid + "
      您本次游戏得分:" + str(sum), "游戏结束", ("确定", "排行榜"))
              if box == 0:
                  s1 = "	时间		玩家		得分		"
                  s = ""
                  yyh20182324 = sqlite3.connect("排行榜.db")
                  cursor = yyh20182324.cursor()
                  cursor.execute('select * from Ranklist order by core desc')
                  for line in cursor.fetchall():
                      # 月
                      if time.gmtime(line[0])[1] < 10:
                          month = "0" + str(time.gmtime(line[0])[1])
                      else:
                          month = str(time.gmtime(line[0])[1])
                      # 日
                      if time.gmtime(line[0])[2] < 10:
                          day = "0" + str(time.gmtime(line[0])[2])
                      else:
                          day = str(time.gmtime(line[0])[2])
                      # 时
                      if (time.gmtime(line[0])[3] + 8) % 24 < 10:
                          hour = "0" + str((time.gmtime(line[0])[3] + 8) % 24)
                      else:
                          hour = str((time.gmtime(line[0])[3] + 8) % 24)
                      # 分
                      if time.gmtime(line[0])[4] < 10:
                          minute = "0" + str(time.gmtime(line[0])[4])
                      else:
                          minute = str(time.gmtime(line[0])[4])
                      # 秒
                      if time.gmtime(line[0])[5] < 10:
                          second = "0" + str(time.gmtime(line[0])[5])
                      else:
                          second = str(time.gmtime(line[0])[5])
                      calendar = str(time.gmtime(line[0])[0]) + "-" + month + "-" + day + "  " + hour + ":" + minute + ":" + second
                      s = s + calendar + "	  	" + line[1] + "			  " + str(line[2]) + "	
      "
                  g.textbox(s1, "排行榜", s)
                  yyh20182324.close()
      

      调用数据库的方法

      # 排行榜数据库文件
      def sql():
          yyh20182324 = sqlite3.connect("排行榜.db")
          cursor = yyh20182324.cursor()
          cursor.execute('create table if not exists Ranklist(time int(10) primary key, userid text, core int)')
          cursor.execute('insert into Ranklist(time, userid, core) values (?, ?, ?)', (int(time.time()), userid, sum))
          yyh20182324.commit()
          yyh20182324.close()
      
    • (6) 游戏过程截图

    • 代码托管

    3. 实验过程中遇到的问题和解决过程

    • 问题 1 :使用pip install --upgrade pip命令升级 pip 后,安装模块时提示:ModuleNotFoundError:No module named pip._internal

    • 问题 1 解决方案:系 pip 升级失败。参考 pip升级时报错--- No module named 'pip._internal' 文章,使用 python get-pip.py --force-reinstall 命令强制重装 pip

    • 问题 2 :使用全局变量统计得分时报错 UnboundLocalError: local variable 'sum' referenced before assignment

    • 问题 2 解决方案:在函数内部对全局变量进行操作时,应先使用 global 声明,否则程序将把该变量视为未定义的局部变量

    • 问题 3 :使用 pygame.font 显示文字时报错 pygame.error: font not initialized

    • 问题 3 解决方案:在主程序开始前必须执行pygame.init()使 pygame 初始化,或执行 pygame.font.init() 使字库初始化

    • 问题 4 :pygame 无法显示多行文字,使用 " " 也无效

    • 问题4解决方案:Font.render不支持多行显示,想要显示多行文字,只能创建多个 render 对象进行逐行显示

    • 问题 5 :pygame 中文显示乱码

    • 问题 5 解决方案:字体引用不正确。可使用pygame.font.get_fonts()来查看字体名,例如 宋体 对应 simsunnsimsun ,pygame.font.SysFont('simsunnsimsun',20)

    • 问题 6 :enterbox 取消输入用户名后报错TypeError: can only concatenate str (not "NoneType") to str

    • 问题 6 解决方案:enterbox 不输入任何东西返回 None,即 Java 中的 null,表示空值。None 的类型为 NoneType,要想判断该类型,直接判断该变量值是否等于 None 即可。注意不是 null。

    其他(感悟、思考等)

    一学期的课程又结束了,一期一度的大作业真的很考验人的综合运用能力。这学期的 Python 总体而言没有上学期的 Java 累,可能也是选修课与必修课的区别。通过对 Python 的学习,真真切切地感受到它的方便快捷,不愧为今天最受欢迎的编程语言。总的来说上王老师的课能够学到很多东西,不管是主动学习还是被动学习,只有真真正正学到了才能做出成果,相比于闭卷考试,这种考核方式更值得提倡。
    我对这门课的建议是:坚持写 blog 的优良传统不要放弃
    最后:

    参考资料

  • 相关阅读:
    es6笔记6^_^generator
    es6笔记5^_^set、map、iterator
    es6笔记4^_^function
    es6笔记3^_^object
    关于eslint的使用与配置,以及prettier的使用
    关于查看本机ssh公钥以及生成公钥
    Github上传图片图床
    力扣剑指Offer:39. 数组中出现次数超过一半的数字
    计蒜客:求平均年龄Python方法
    力扣:面试题59. 滑动窗口的最大值Python题解
  • 原文地址:https://www.cnblogs.com/lolipop2019/p/13113989.html
Copyright © 2020-2023  润新知