课程:《Python程序设计》
班级:2113
姓名:邹雪梅
学号:20211315
实验教师:王志强
实验日期:2022年5月21日
必修/选修:公选课
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
课代表和各小组负责人收集作业(源代码、视频、综合实践报告)
注:在华为ECS服务器(OpenOuler系统)和物理机(Windows/Linux系统)上使用VIM、PDB、IDLE、Pycharm等工具编程实现。
批阅:注意本次实验不算做实验总分,前三个实验每个实验10分,累计30分。本次实践算入综合实践,打分为25分。
评分标准:
(1)程序能运行,功能丰富。(需求提交源代码,并建议录制程序运行的视频)10分
(2)综合实践报告,要体现实验分析、设计、实现过程、结果等信息,格式规范,逻辑清晰,结构合理。10分。
(3)在实践报告中,需要对全课进行总结,并写课程感想体会、意见和建议等。5分
之前用pygame实现过俄罗斯方块小游戏,所以这次没有用pygame,但是看到pygame可以加音效和开始动画等,之后可能还会在假期等时间充足的时候用pygame做游戏。本次实验通过Python实现21点小游戏,导出为EXE小程序,上传华为云运行,代码上传码云
首先要了解21点小游戏的游戏规则:
点数计算:每张牌都有点数。2 到 10 的牌的点数就是其牌面的数字,J、Q、K的点数是 10.
A有两种算法: 1 或者 11, 如果 A 算为 11 时总和大于 21,则 A 算为 1. 例如 (A, 8)是 19 点, (A,7,J)则为 18 点
爆牌:玩家手中牌的总点数超过 21 点
停牌:玩家不再要牌, 等待其他玩家操作
要牌:玩家根据自己手上的点数决定是否要牌, 如果要牌, 则系统再发一张牌给玩家. 如果要牌后总点数超过 21, 则算爆牌,玩家输掉本轮游戏;若要牌后点数为 21点, 则不能再要。如果要牌后总点数不到 21 点, 则玩家可以继续 “要牌” “停牌”
庄家持牌总点数少于 17,则必须要牌,直到超过 16,如果庄家的总点数等于或多于 17 点,则必须停牌
如果庄家手中有 A,且 A 作 11 点时大于 16点,作 1 点时小于或等于 16 点, 则由庄家自己选择是否要牌
注意:游戏开始后,玩家和庄家各发两张牌,庄家的第二张牌对外不可见。
基于以上的规则,使用 Python 实现一个简单的 21 点游戏,该游戏只有玩家和电脑两个玩家,玩家通过命令行的方式输入命令,决定是否要牌或停牌,电脑玩家要牌或停牌由程序自动控制。代码如下:
import random # 导入随机包 # 模拟要牌, 从卡牌列表中随机选择一张卡牌 import time def my_random_choose(): card = random.choice(cards) # 从卡牌列表中随机选取一张牌 flag = card[0] # flag 存放卡牌的标记 value = card[-1] # value 存放卡牌的字符串类型的值 if value == 'A': # 如果卡牌为 A return flag, value, 1 # 暂时给它的值赋为 1 elif value == '0': return flag, '10', 10 # 卡牌为 10 elif value == 'J' or value == 'Q' or value == 'K': return flag, value, 10 # 卡牌为 J, Q, K 的当作 10 else: return flag, value, int(value) # 其他卡牌, 按照卡牌上的数字计算即可 # 询问玩家是否继续要牌, 获取玩家选择 def get_Input(): Input = input('是否继续要牌(Y|N):') while Input != 'Y' and Input != 'N': # 强制要求只能输入 Y 或者 N, 其他输入一律重新输入 Input = input('是否继续要牌(Y|N):') return Input # 玩家要牌 def player_hit(): # 开始游戏,随机发给玩家两张卡牌 flag1, value1, num1 = my_random_choose() flag2, value2, num2 = my_random_choose() player_cards = [] # 玩家卡牌列表,存放玩家要的所有牌, 存放的是 flag 和 value # 如果第一张卡牌为 A, 则赋值为 11 if num1 == 1: num1 = 11 # 卡牌数值为 11 elif num1 != 1 and num2 == 1: # 如果第一张卡牌不为 A, 但是第二张卡牌为 A num2 = 11 # 卡牌数值为 11 player_total = num1 + num2 # 计算当前玩家手中卡牌总点数 # 将初始发的两张卡牌放到玩家卡牌列表中, 存放的是字符串, 所以不参与计算, 只是用于输出卡牌拥有情况 player_cards.append([flag1, value1]) player_cards.append([flag2, value2]) print('玩家手中的牌是:', [flag1, value1], [flag2, value2]) if player_total == 21: # 玩家当前点数为 21 点 # 玩家赢了 return player_total # 返回玩家点数 else: # 玩家当前点数不为 21 点 Input = get_Input() # 询问玩家是否要继续要牌 while Input == 'Y' or Input == 'N': if Input == 'Y': # 玩家继续要牌 flag, value, num = my_random_choose() # 随机抽一张卡牌给玩家 if num == 1 and (player_total + 11 <= 21): # 如果抽到了 A, 将 A 看成 11, 看一下此时手中卡牌总点数是否大于 21 num = 11 # 如果不大于 21, 可以将当前 A 赋值为 11 player_cards.append([flag, value]) # 将抽到的卡牌放到玩家卡牌列表中 print('玩家手中的牌是:', player_cards) # 输出当前拥有的卡牌 player_total += num # 计算玩家当前拥有的卡牌的总点数 if player_total > 21: # 如果玩家当前拥有的卡牌总点数大于 21 return player_total # 玩家爆牌, 返回 玩家卡牌总点数, 结束函数执行 elif Input == 'N': # 玩家不要牌 return player_total # 返回玩家当前卡牌总点数, 结束函数执行, 让庄家要牌 Input = get_Input() # 玩家之前要了牌, 但是牌的总点数小于 21, 询问玩家是否继续要牌 # 庄家要牌 def dealer_hit(num1, dealer_cards): DEALER_MIN_SCORE = 17 # 庄家手中的牌的总点数的最小值为 17, 如果小于 17, 庄家必须要牌 flag2, value2, num2 = my_random_choose() # 为庄家随机选择一张卡牌 if num1 != 11 and num2 == 1: # 庄家的第一张牌不是 A, 但是第二张卡牌是 A num2 = 11 # 给第二张卡牌赋值为 11 dealer_cards.append([flag2, value2]) # 将庄家的第二张卡牌放到庄家卡牌列表中, 用于之后输出拥有卡牌情况 dealer_total = num1 + num2 # 当庄家手中牌的总点数小于 17, 必须要牌, while dealer_total < DEALER_MIN_SCORE: flag, value, num = my_random_choose() if num == 1 and (dealer_total + 11 <= 21): num = 11 dealer_cards.append([flag, value]) print('庄家得到一张牌, 庄家手中的牌是: ', dealer_cards) dealer_total += num # 庄家手中的牌的总点数大于等于17, 必须停牌, 即返回总点数 return dealer_total # 决定赢家 def vs(player_total, dealer_total): if player_total > 21: # 如果玩家爆牌 # 玩家输 print('庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 庄家赢了!') return 1, 0 # 分别返回庄家和玩家的比分 else: if dealer_total > 21: # 庄家爆牌 print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 玩家赢了!') return 0, 1 else: if player_total == dealer_total: # 平局 print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 平局!') return 1, 1 elif player_total > dealer_total: # 都没有爆牌,但是玩家的卡牌总点数大于庄家卡牌总点数 # 玩家赢 print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 玩家赢了!') return 0, 1 else: # 庄家赢 print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 庄家赢了!') return 1, 0 def start_21_game(): player_score = 0 # 玩家得分 dealer_score = 0 # 庄家得分 Input = 'Y' round_count = 0 # 比赛的轮数 while Input == 'Y': round_count += 1 print(f'第{round_count}轮比赛开始:') flag1, value1, num1 = my_random_choose() # 从卡牌列表中随机选择一个卡牌 if num1 == 1: # 卡牌为 A num1 = 11 # 因为只有一个卡牌,所以不会爆牌,赋值为 11 dealer_cards = [] # 庄家拥有的卡牌列表 dealer_cards.append([flag1, value1]) # 将抽到的卡牌放到庄家卡牌列表中 print('庄家手中的牌是: ', [flag1, value1], '?') player_total = player_hit() # 调用玩家要牌函数, 返回值是玩家此时的卡牌总点数 dealer_total = dealer_hit(num1, dealer_cards) # 调用庄家要牌函数, 返回值是庄家此时的卡牌总点数 dealer_point, player_point = vs(player_total, dealer_total) # 根据玩家和庄家的卡牌总点数判断赢家是谁, 返回值分别是庄家和赢家当局的比分 print('------------------------------') player_score += player_point # 将玩家当局的得分加到玩家总得分上 dealer_score += dealer_point # 将庄家当局的得分加到庄家总得分上 Input = input('是否进行下一局 [Y|N]:') while Input != 'Y' and Input != 'N': print('请输入 Y or N.', end='') Input = input('请重新输入 [Y|N]:') return player_score, dealer_score if __name__ == '__main__': # 定义一个存放卡牌的列表 cards = ['♠A', '♠2', '♠3', '♠4', '♠5', '♠6', '♠7', '♠8', '♠9', '♠10', '♠J', '♠Q', '♠K', '♣A', '♣2', '♣3', '♣4', '♣5', '♣6', '♣7', '♣8', '♣9', '♣10', '♣J', '♣Q', '♣K', '♦A', '♦2', '♦3', '♦4', '♦5', '♦6', '♦7', '♦8', '♦9', '♦10', '♦J', '♦Q', '♦K'] # play_score 记录玩家的得分, dealer_score 记录庄家的得分 player_score, dealer_score = start_21_game() print(f'玩家, 庄家总比分为:{player_score}:{dealer_score}') if player_score > dealer_score: print('玩家胜出') elif player_score < dealer_score: print('庄家胜出') else: print('平局') print('游戏结束') print('10秒后自动关闭窗口') time.sleep(10)
其中10s自动关闭、可重复多局游戏、记录游戏得分等我自认为还是不错的小功能(嘿嘿)
(参考老师发的链接打包生成了EXE小程序)
pycharm运行
小程序运行
华为云运行
问题1:华为云运行错误
解决方案:询问同学,并检测Python位置版本,以Python形式运行(之前错用了C语言的运行方式)
问题2:在程序编写过程中,没加一个功能几乎就要错一次
解决方案:去CSDN找大佬的博客和经验
之前通过《看漫画学Python》自学了一下Python但是学的并不系统也没有深入。
学期初抱着多学习学习知识的心态,报名了python选修课。一学期下来果然没有失望,课程进度飞快,感触颇深。
python语言特点:
简单:Python是一种代表简单思想的语言。
易学:Python有极其简单的语法。
免费、开源:Python是FLOSS(自由/开放源码软件)之一。
高层语言:使用Python编写程序时无需考虑如何管理程序使用的内存一类的底层细节。
可移植性:Python已被移植到很多平台
解释性:可以直接从源代码运行。在计算机内部,python解释器把源代码转换为字节码的中间形式,然后再把它翻译成计算机使用的机器语言。
面向对象:python既支持面向过程编程也支持面向对象编程。
可扩展性:部分程序可以使用其他语言编写,如c/c++。
可嵌入型:可以把Python嵌入到c/c++程序中,从而提供脚本功能。
丰富的库:Python标准库确实很庞大。它可以帮助你处理各种工作,包括正则表达式、文档生成、单元测试、线程、数据库、网页浏览器、CGI、FTP、电子邮件、XML、XML-RPC、HTML、WAV文件、密码系统、GUI(图形用户界面)、Tk和其他与系统有关的操作
本学期学习的主要知识点:
变量赋值及其命名规则
运算符及其优先级
基本数据类型
循环语句
列表、元组、字典、集合及其常用功能
字符串与正则表达式
函数
面向对象程序设计
文件操作及异常处理
Python操作数据库
Python网络编程及爬虫开发(Socket)
(1)光听不练假把式,多多实践比只是听课有用的多
(2)学会查找相关资料,学会把运用别解决类似问题的方法解决自己的问题
(3)学习不能有怠惰心理,要持之以恒的努力
一个学期的学习感觉自己在Python或者说整个编程语言、计算机知识都收获很多,之前通过自学不完整不系统的知识都串联起来了,而且通过老师几次作业也真正会运用Python了,在一次次尝试中也提高了自己解决问题的能力......总之感觉这门课“太值了”以后有学弟学妹问一定倾力推荐(手动狗头)
上课同时看投影和跟着打代码会跟不上,投影的显示还是不太清晰的(有时候会跟同学一起,她手机进入腾讯会议然后我们跟着腾讯会议的代码打,哈哈)
老师上课时候对于云班课上Word课件的改动和一起编写的小程序也建议分享一下,让我们不至于因为没跟上二“错过就遗憾终身”
基本都是CSDN上大佬的博客,因为太多和时间跨度大约有一个周,就不一一列举了