ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2022-05-28 18:01:44  阅读:192  来源: 互联网

标签:邹雪梅 Python 卡牌 玩家 player 20211315 庄家 点数 dealer


目录

《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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有