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

20244112 2024-2025-4 《Python程序设计》实验四报告

课程:《Python程序设计》
班级: 2441
姓名: 李其鲔
学号:20244112
实验教师:王志强
实验日期:2025年5月13日
必修/选修: 公选课

1.实验内容

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
(1)编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。
(2)利用公开数据集,开展图像分类、恶意软件检测等
(3)利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。
(4)爬取天气数据,实现自动化微信提醒
(5)利用爬虫,实现自动化下载网站视频、文件等。
(6)编写小游戏:坦克大战、贪吃蛇、扫雷等等
注:在Windows/Linux系统上使用VIM、PDB、IDLE、Pycharm等工具编程实现。

2. 实验过程

(1)在本次实验当中,我准备使用Python程序编写一个小游戏。为了使用程序语言设计出这个小游戏,我需要首先写出游戏规则与流程。
a.游戏使用20张牌,包括6张Queen、6张King、6张Ace和2张Joker,Joker可以作为任何牌使用。
b.每轮游戏开始前,会随机给玩家发放包括Q、K、A、Joker在内的五张牌,电脑自己也同样随机抽取五张牌,但不告诉玩家。同时随机指定一张牌作为主牌,玩家需要根据主牌出牌,并可以撒谎。
c.由电脑选择是否质疑出牌玩家,如果电脑质疑,根据是否质疑成功决定谁进行俄罗斯轮盘赌;如果电脑不质疑,则由电脑出牌,玩家选择是否质疑。
d.盘赌成功则显示不中枪,游戏进入下一轮;盘赌失败则显示中枪,游戏失败。
e.在一个回合内,如果玩家和电脑都没有选择质疑,那么这个回合继续,玩家和电脑上一轮出的手牌这一轮不能再用,然后再按之前的步骤进行,直到有一方的手牌出完,那么另一方进行盘赌。
f.游戏进入下一轮时,重新发放手牌以及重新指定主牌。但是中枪机会不改变,也就是说六次机会用了一次,如此经过六轮则必有一人中枪。
(2)为了在Pycharm中模拟出这样一个使用扑克牌的游戏,我需要先对扑克牌进行定义。创建一个类来表示扑克牌,把牌的点数(Q、K、A、Joker)这个属性封装在类里面。打印牌的点数这个对象时,按照__str__方法里定义的格式输出。

(3)然后对于游戏中所有的手牌牌堆进行定义,包括6张Queen、6张King、6张Ace和2张Joker。用列表存储Card对象,通过random.shuffle实现洗牌,pop()方法抽牌,这样游戏基本的洗牌发牌功能就已经完备。

(4)在游戏的扑克牌以及牌堆已经被定义好了后,现在需要对玩家的一系列行为进行编写。玩家需要能够看到自己每轮的手牌,如何进行出牌,同时还需要对玩家所出的牌进行检验。那么使用列表推导式生成字符串列表,结合str()转换对象,这样来显示每一轮玩家被发到的手牌。第二,用sorted和reverse=True确保索引从大到小删除,避免索引错位,同时记录出牌历史,以免打出的手牌依旧保留。在检查玩家的手牌时,通过len()比较列表长度,快速判断操作合法性,避免无效操作。


(5)在上述的游戏基本配置编写完成后,现在我需要根据所制定的游戏规则进行游戏流程编写。首先,我需要对每一轮游戏的主牌进行定义编写,让程序能够在每轮开始时抽取一张牌面作为主牌。然后,在每轮开始时用方法封装初始化逻辑,通过实例变量传递状态,达到刷新游戏的效果。


(6)在玩家回合,使用循环和条件判断确保玩家输入合法,以输入0-4来代替玩家所要打出的牌。

(7)在电脑回合,通过min()和sample()方法限制出牌数量,使用random语言来决定电脑打出的牌。

(8)在出牌后的质疑阶段,如果是电脑选择是否质疑,那么使用根据打出的牌数来决定是否质疑,同时采用if条件语句来进行编写,通过random.random()生成随机数。如果是玩家选择是否质疑,那么用while循环使玩家输入有效选项。

(9)在质疑成功后的盘赌环节,同样使用概率以及if条件语句进行程序编写,用随机数模拟轮盘赌结果,通过input()暂停程序。

(10)最后,用while循环控制多轮游戏,通过条件判断决定游戏胜负,通过print输出游戏信息,从而完成程序编写。

3. 实验代码及运行结果

(1)实验代码

import random

class Card:
"""扑克牌类,表示一张牌"""

def __init__(self, rank):
    self.rank = rank  # 牌面:Q, K, A, Joker

def __str__(self):
    return self.rank

class Deck:
"""牌堆类,管理游戏使用的20张牌"""

def __init__(self):
    self.cards = []
    # 添加6张Q、6张K、6张A
    for _ in range(6):
        self.cards.append(Card("Q"))
        self.cards.append(Card("K"))
        self.cards.append(Card("A"))
    # 添加2张Joker
    self.cards.append(Card("Joker"))
    self.cards.append(Card("Joker"))
    random.shuffle(self.cards)  # 洗牌

def draw(self, num):
    """从牌堆中抽取指定数量的牌"""
    return [self.cards.pop() for _ in range(num)]

def is_empty(self):
    """检查牌堆是否为空"""
    return len(self.cards) == 0

class Player:
"""玩家类,管理玩家的手牌和状态"""

def __init__(self, name):
    self.name = name
    self.hand = []
    self.used_cards = []  # 已使用的牌
    self.played_history = []  # 出牌历史:[(cards, is_lie), ...]

def receive_cards(self, cards):
    """接收牌"""
    self.hand.extend(cards)

def show_hand(self):
    """显示玩家手牌"""
    return [str(card) for card in self.hand]

def play_cards(self, indices):
    """打出指定位置的牌"""
    played = [self.hand.pop(i) for i in sorted(indices, reverse=True)]
    self.used_cards.extend(played)

    # 记录出牌历史
    actual_main_count = sum(1 for card in played if card.rank == self.main_card.rank or card.rank == "Joker")
    is_lie = actual_main_count < len(played)
    self.played_history.append((played, is_lie))

    return played, is_lie

def has_cards(self, count):
    """检查玩家是否有足够的牌"""
    return len(self.hand) >= count

def can_play(self):
    """检查玩家是否还能出牌"""
    return len(self.hand) > 0

class Game:
"""游戏主类,管理游戏流程和逻辑"""

def __init__(self):
    self.deck = Deck()
    self.player = Player("玩家")
    self.computer = Player("电脑")
    self.current_round = 1
    self.bullet_chamber = random.randint(1, 6)  # 轮盘赌的子弹位置
    self.current_chamber = 1  # 当前轮盘位置
    self.main_card = None  # 当前主牌

def setup_round(self):
    """设置新一轮游戏"""
    print(f"\n★☆★☆★☆       第{self.current_chamber} 轮      ☆★☆★☆★")

    # 重置牌堆和玩家手牌
    self.deck = Deck()
    self.player.hand = []
    self.computer.hand = []
    self.player.used_cards = []
    self.computer.used_cards = []
    self.player.played_history = []
    self.computer.played_history = []

    # 发牌
    player_cards = self.deck.draw(5)
    computer_cards = self.deck.draw(5)
    self.player.receive_cards(player_cards)
    self.computer.receive_cards(computer_cards)

    # 随机选择主牌
    self.main_card = self.deck.draw(1)[0]
    print(f"本轮主牌是: {self.main_card}")
    print(f"你的手牌是: {self.player.show_hand()}")

    # 设置玩家和电脑的主牌引用
    self.player.main_card = self.main_card
    self.computer.main_card = self.main_card

def player_turn(self):
    """玩家回合"""
    if not self.player.can_play():
        return [], False

    while True:
        try:
            # 玩家选择要打出的牌
            print("\n请选择要打出的牌的位置 (0-4),用空格分隔(例如:0 2 4)")
            for i, card in enumerate(self.player.show_hand()):
                print(f"{i}: {card}")

            choice = input("输入数字选择牌: ").strip()

            if not choice:
                print("你必须打出至少一张牌!")
                continue

            indices = [int(x) for x in choice.split()]

            # 检查选择是否有效
            if all(0 <= i < len(self.player.hand) for i in indices) and len(set(indices)) == len(indices):
                played_cards, is_lie = self.player.play_cards(indices)
                print(f"你打出了 {len(played_cards)} 张牌。")

                return played_cards, is_lie
            else:
                print("无效的选择,请重新输入。")
        except ValueError:
            print("请输入有效的数字。")

def computer_turn(self):
    """电脑回合"""
    if not self.computer.can_play():
        return [], False

    # 电脑随机决定打出1-3张牌
    max_cards = min(3, len(self.computer.hand))
    if max_cards < 1:
        return [], False

    card_count = random.randint(1, max_cards)
    indices = random.sample(range(len(self.computer.hand)), card_count)
    played_cards, is_lie = self.computer.play_cards(indices)

    print(f"\n电脑打出了 {card_count} 张牌,声称都是 {self.main_card}。")

    return played_cards, is_lie

def computer_decision(self, player_cards_count):
    """电脑决定是否质疑"""
    # 电脑根据玩家打出的牌数决定质疑概率
    # 牌数越多,质疑概率越高
    challenge_probability = 0.3 + (player_cards_count - 1) * 0.15
    will_challenge = random.random() < challenge_probability

    if will_challenge:
        print("\n电脑质疑你。")
        return True
    else:
        print("\n电脑相信了你。")
        return False

def player_decision(self):
    """玩家决定是否质疑"""
    while True:
        choice = input("你要质疑电脑吗?(y/n): ").lower()
        if choice == 'y':
            print("\n你质疑了电脑。")
            return True
        elif choice == 'n':
            print("\n你相信了电脑。")
            return False
        else:
            print("请输入 y 或 n。")

def russian_roulette(self, player_name):
    """俄罗斯轮盘赌"""
    print(f"\n{player_name} 必须进行俄罗斯轮盘赌!")
    input("按Enter键转动轮盘...")

    print(f"轮盘转动... 停在位置 {self.current_chamber}")

    # 检查是否中枪
    if self.current_chamber == self.bullet_chamber:
        print(f"砰!{player_name} 中枪了!")
        return False  # 游戏结束
    else:
        print(f"咔嗒... {player_name} 安全!")
        self.current_chamber += 1
        return True  # 继续游戏

def handle_player_win(self):
    """处理玩家获胜的情况"""
    print("\n恭喜!你出完了所有手牌,你胜利了!")

    # 电脑可以选择是否质疑
    challenge = self.computer_decision(len(self.player.used_cards))

    if challenge:
        # 检查玩家最后一次出牌是否撒谎
        if self.player.played_history and self.player.played_history[-1][1]:
            print("电脑质疑正确。")
            result = self.russian_roulette(self.player.name)
            return result
        else:
            print("电脑质疑错误。")
            result = self.russian_roulette(self.computer.name)
            return result
    else:
        # 电脑不质疑,玩家直接获胜
        print("电脑选择不质疑,你赢得本轮胜利!")
        result = self.russian_roulette(self.computer.name)
        return result

def handle_computer_win(self):
    """处理电脑获胜的情况"""
    print("\n电脑出完了所有手牌,你输了。")

    # 玩家可以选择是否质疑
    challenge = self.player_decision()

    if challenge:
        # 检查电脑最后一次出牌是否撒谎
        if self.computer.played_history and self.computer.played_history[-1][1]:
            print("你质疑正确。")
            result = self.russian_roulette(self.computer.name)
            return result
        else:
            print("你质疑错误。")
            result = self.russian_roulette(self.player.name)
            return result
    else:
        # 玩家不质疑,电脑直接获胜
        print("你选择不质疑,电脑赢得本轮胜利。")
        result = self.russian_roulette(self.player.name)
        return result

def play_round(self):
    """进行一轮游戏"""
    self.setup_round()

    while True:
        # 玩家回合
        if self.player.can_play():
            player_cards, player_is_lie = self.player_turn()

            # 检查玩家是否出完所有牌
            if not self.player.can_play():
                return self.handle_player_win()

            # 电脑决定是否质疑
            challenge = self.computer_decision(len(player_cards))

            # 处理质疑结果
            if challenge:
                if player_is_lie:
                    print("电脑质疑正确。")
                    result = self.russian_roulette(self.player.name)
                    return result
                else:
                    print("电脑质疑错误。")
                    result = self.russian_roulette(self.computer.name)
                    return result
        else:
            print("\n你没有手牌可以出了。")

        # 电脑回合
        if self.computer.can_play():
            computer_cards, computer_is_lie = self.computer_turn()

            # 检查电脑是否出完所有牌
            if not self.computer.can_play():
                return self.handle_computer_win()

            # 玩家决定是否质疑
            player_challenge = self.player_decision()

            if player_challenge:
                if computer_is_lie:
                    print("你质疑正确。")
                    result = self.russian_roulette(self.computer.name)
                    return result
                else:
                    print("你质疑错误。")
                    result = self.russian_roulette(self.player.name)
                    return result
        else:
            print("\n电脑没有手牌可以出了")

        # 如果双方都还有牌,继续下一回合
        print(f"\n双方都还有牌,继续回合...")
        print(f"你的剩余手牌: {self.player.show_hand()}")

    self.current_round += 1
    return True  # 继续游戏

def play_game(self):
    """开始游戏"""
    print("""
    ☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
    ★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
    ☆★☆                                欢迎来到Joker's Deception                                 ★☆★
    ★☆★                                    copyrigrht:besti                                    ☆★☆
    ☆★☆                                   开发日期:2025年5月13日                                   ★☆★
    ★☆★                                      学号:20244112                                      ☆★☆
    ★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
    ☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
    """)
    print("游戏规则:")
    print("- 共有20张牌: 6张Queen、6张King、6张Ace和2张Joker")
    print("- 每轮随机发放5张牌并且指定一张主牌")
    print("- 你可以选择打出任意数量的牌,并默认声称这些牌都是主牌")
    print("- 电脑会决定是否质疑你")
    print("- 如果电脑不质疑,则轮到电脑出牌,你可以选择是否质疑")
    print("- 当一方出完所有手牌后,另一方可以选择是否质疑")
    print("- 如果质疑正确,出完牌的一方接受轮盘赌")
    print("- 如果不质疑或质疑错误,出完牌的一方获胜")
    print("- 六轮内必有一方中枪")

    # 游戏主循环
    while self.current_round <= 6:
        if not self.play_round():
            print("\n游戏结束!")
            return

    # 如果六轮都没有中枪(理论上不可能)
    print("\n经过六轮激烈对决,双方都幸运地存活了下来!游戏平局!")
    # 启动游戏
    if __name__ == "__main__":
    game = Game()
    game.play_game()

(2)运行结果
https://www.bilibili.com/video/BV1fP7TzyE6s/?spm_id_from=333.1387.homepage.video_card.click&vd_source=2a75c37c1a96d67f0614c0feeb71f775

4. 全课的总结与课程感想体会、意见和建议

(1)全课总结:课程起始于对Python的初步认识,涵盖Python语法,如变量定义、数据类型(数字、字符串等)。流程控制语句(条件语句if-else、循环语句for和while)的学习,让代码具备逻辑判断和重复执行能力。在数据处理方面,深入讲解序列(列表、元组、集合 )和字符串操作,包括增删改查、切片等。函数章节则介绍函数定义、参数传递、返回值等内容,将代码模块化,提高代码复用性。面向对象部分引入类和对象概念,封装、继承、多态特性使代码结构更清晰。异常处理及程序调试章节,教会识别和处理运行时错误,使用调试工具排查问题,保障程序稳定性。文件及目录操作涉及文件读写、创建删除目录等。使用Python操作数据库,掌握连接数据库、执行SQL语句、数据增删改查,实现数据持久化存储。网络爬虫开发学习网页数据抓取技术,包括 HTTP 请求、解析网页内容。
(2)课程感想体会:通过这段时间的学习,我掌握了Python语言的基础知识和基本编程技能。能够熟练运用Python进行数据处理、编写简单的算法程序,还完成了如剪刀石头布,简易计算器,记事本,猜数字游戏等的实验。这些实验的完成不仅检验了我的学习成果,也让我获得了极大的成就感。课程初始,面对Python的基础语法,如变量定义、数据类型、条件语句和循环语句,我常常感到困惑。但随着课程的推进,通过老师生动的讲解和大量的实例演示,我逐渐理解了这些基础语法的逻辑和应用场景。在学习函数定义与调用时,我开始体会到模块化编程的魅力。在学习过程中,我也遇到了不少困难。例如,在学习正则表达式时,对于复杂的语法规则我有些许迷惑,但在阅读官方文档、翻阅资料书籍、观看教学视频后,我对正则表达式有了相对更深的了解。
(3)对于课程的意见和建议:王志强老师的Python课程生动有趣,为我打开了Python世界的大门。正如课程伊始,王志强老师在白板上所输入的程序代码:print("hello world")
print("人生苦短,我用Python")。虽然Python程序设计课程已经结束,但这并不意味着我的学习之路就此止步。在未来,我希望能够进一步深入学习Python的高级知识,如网络编程、数据库编程、Web开发等。最后,我希望王老师能够给26年课程学习学生多留作业,更好体会Python程序设计的乐趣与魅力。

参考资料

posted @ 2025-05-31 22:50  septv  阅读(79)  评论(0)    收藏  举报