编程语言
首页 > 编程语言> > 20211315邹雪梅《Python程序设计》实验四报告

20211315邹雪梅《Python程序设计》实验四报告

作者:互联网

目录

《Python程序设计》实验四报告

课程:《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小程序,上传华为云运行,代码上传码云

三、实验分析、设计、实现过程、结果

1.游戏规则

首先要了解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 点, 则由庄家自己选择是否要牌
注意:游戏开始后,玩家和庄家各发两张牌,庄家的第二张牌对外不可见。

2.源代码

基于以上的规则,使用 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自动关闭、可重复多局游戏、记录游戏得分等我自认为还是不错的小功能(嘿嘿)

3.运行结果

(参考老师发的链接打包生成了EXE小程序)
pycharm运行

小程序运行

华为云运行

三、代码上传到码云

四、实验过程中遇到的问题

问题1:华为云运行错误

解决方案:询问同学,并检测Python位置版本,以Python形式运行(之前错用了C语言的运行方式)

问题2:在程序编写过程中,没加一个功能几乎就要错一次
解决方案:去CSDN找大佬的博客和经验

五、全课总结,课程感想体会、意见和建议

1.全课总结

之前通过《看漫画学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)

2.课程感想体会

(1)光听不练假把式,多多实践比只是听课有用的多
(2)学会查找相关资料,学会把运用别解决类似问题的方法解决自己的问题
(3)学习不能有怠惰心理,要持之以恒的努力
一个学期的学习感觉自己在Python或者说整个编程语言、计算机知识都收获很多,之前通过自学不完整不系统的知识都串联起来了,而且通过老师几次作业也真正会运用Python了,在一次次尝试中也提高了自己解决问题的能力......总之感觉这门课“太值了”以后有学弟学妹问一定倾力推荐(手动狗头)

3.意见和建议

上课同时看投影和跟着打代码会跟不上,投影的显示还是不太清晰的(有时候会跟同学一起,她手机进入腾讯会议然后我们跟着腾讯会议的代码打,哈哈)
老师上课时候对于云班课上Word课件的改动和一起编写的小程序也建议分享一下,让我们不至于因为没跟上二“错过就遗憾终身”

六参考资料

基本都是CSDN上大佬的博客,因为太多和时间跨度大约有一个周,就不一一列举了

标签:邹雪梅,Python,卡牌,玩家,player,20211315,庄家,点数,dealer
来源: https://www.cnblogs.com/summerjam-land/p/16321448.html