Skip to content

Latest commit

 

History

History
597 lines (445 loc) · 15.2 KB

File metadata and controls

597 lines (445 loc) · 15.2 KB
Error in user YAML: (<unknown>): found a tab character that violate indentation while scanning a plain scalar at line 3 column 3
---
- oeasy Python 0116
- 这是 oeasy 系统化 Python 教程,从基础一步步讲,扎实、完整、不跳步。愿意花时间学,就能真正学会。
- 本教程同步发布在: 
	- 个人网站: `https://oeasy.org` 
	- 蓝桥云课: `https://www.lanqiao.cn/courses/3584` 
	- GitHub: `https://github.com/overmind1980/oeasy-python-tutorial` 
	- Gitee: `https://gitee.com/overmind1980/oeasypython` 
---

用列表乱序shuffle来洗牌抓拍玩升级拖拉机

回忆

  • 配套视频
  • 上次我们了解了
    1. 定点插入 insert
      • 相对原来的 追加append
    2. 定点删除 pop
      • 相对原来的 按值删除 remove

图片描述

  • 排好序 之后 可以打乱顺序吗?

乱序

图片描述

  • 好像来自我们熟悉的包
    • random

random.shuffle

import random
nl = list(range(4))
random.shuffle(nl)
nl
random.shuffle(nl)
nl
  • 效果

图片描述

  • shuffle 之前 见过吗?

回忆

  • 以前用的是
    • random.randint
      • 得到 随机整数
    • random.choice
      • 选择 一个 列表项

图片描述

  • shuflle怎么理解?

help

import random
help(random.shuffle)
  • 在原地
    • 打乱列表的次序

图片描述

  • 次序了 有啥好的吗?

shuffle

  • 随机安排角色

图片描述

  • 随机抓牌

图片描述

  • shuffle 本身就是洗牌的意思

洗牌

  • 一副牌54张

图片描述

  • 每张牌一个编号
    • 把牌洗开

洗牌

import random 
poker_list = list(range(54))
random.shuffle(poker_list)
print(poker_list)
  • 牌洗好了
    • 不过洗的是牌的序号

图片描述

  • 扑克字符

扑克字符

  • 要先 把 扑克牌 换成 字符

图片描述

  • unicode中包含扑克的字符

图片描述

  • 把 相关范围 都 遍历一遍

遍历范围

import random
for n in range(0x1f0a0, 0x1f0ff):
	print(chr(n), end = " ")
  • 输出结果

图片描述

  • 为什么JQK之外还有C?

花色来历

  • 唐宋的叶子戏

图片描述

  • 传入波斯、阿拉伯

    • 经过意大利、德国
    • 骑士牌 (Cavalier/Knight)
    • 是欧洲传统扑克牌的一部分
  • 现在是英法花色 成为主流

    • 在此基础上 构成了 美式扑克
  • 这些排面有什么说法?

排面

  • 人物也完成了 本地化

图片描述

  • 四大天王(king) 都来自英法

图片描述

  • 人物有什么含义

人物含义

牌面 花色 对应角色 核心身份
K 红桃♥ 查理曼大帝 法兰克国王,西欧统一者
黑桃♠ 大卫王 以色列国王,《圣经》人物
梅花♣ 亚历山大大帝 马其顿国王,欧亚非征服者
方块♦ 凯撒大帝 罗马独裁官,罗马帝国奠基者
Q 红桃♥ 朱迪思 犹太女英雄,《圣经》外典人物
黑桃♠ 雅典娜 希腊神话智慧与战争女神
梅花♣ 阿金尼 传说爱神(原型关联伊丽莎白一世)
方块♦ 拉结 《圣经》中雅各的妻子
J 红桃♥ 拉海尔 法国骑士,圣女贞德追随者
黑桃♠ 奥吉尔 查理曼大帝的圣骑士
梅花♣ 兰斯洛特 亚瑟王圆桌骑士,圣杯守护者
方块♦ 赫克托尔 特洛伊王子,神话勇士
  • King > Queen > Jack(侍从)

图片描述

  • 为什么是 黑红梅方 四个花色?

花色

  • 4组花色
    • 代表四季

图片描述

  • 为什么是54张?

54张牌

  • 52张正牌正好代表
    • 一年中有52个星期

图片描述

  • 为什么 黑桃A 那么不同?

印花税

  • 1712年
    • 英国开始征收
      • 印花税
      • stamp duty
    • 每一副牌必须有纳税的痕迹才能离开工厂

图片描述

  • 执行人 给
    • 缴税纸牌的第一张
    • 也就是黑桃A
      • 盖上墨水戳
      • 牌面 比K还大
  • 想要 洗真正的牌
    • 可以吗?

提问

图片描述

代码

图片描述

# 生成仅含 Unicode 字符的 54 张扑克牌列表
deck = []

# 花色偏移:0=黑桃 1=红桃 2=梅花 3=方块
suits_offset = [0, 1, 2, 3]
# 牌面偏移:对应 A-K,跳过无效的 12、15
ranks_offset = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]

# 生成 4花色×13张牌,同时记录草花K的编码
club_k_code = None
for suit in suits_offset:
    for rank in ranks_offset:
        code = 0x1F0A0 + suit * 16 + rank
        deck.append(chr(code))
        # 捕获草花K的编码(花色偏移2,牌面偏移14)
        if suit == 2 and rank == 14:
            club_k_code = code

# 小王编码 = 草花K编码 + 1
joker_small_code = 0x1F0DF
# 大王编码 = 小王编码 + 12(按 Unicode 实际排版逻辑)
joker_big_code = 0x1F0CF

# 添加大小王
deck.append(chr(joker_small_code))
deck.append(chr(joker_big_code))

# 验证长度和输出
print(f"牌组长度: {len(deck)}")
print(f"草花K编码: 0x{club_k_code:X}, 字符: {chr(club_k_code)}")
print(f"小王编码: 0x{joker_small_code:X}, 字符: {chr(joker_small_code)}")
print(f"大王编码: 0x{joker_big_code:X}, 字符: {chr(joker_big_code)}")
print("\n完整牌组:")
print(" ".join(deck))
print(len(deck))

调整颜色

图片描述

效果

图片描述

BLACK_FG = "\033[30m"   # 黑色前景
RED_FG = "\033[31m"     # 红色前景
WHITE_BG = "\033[47m"   # 白色背景
RESET = "\033[0m"       # 重置所有样式

deck = []
colored_deck = []

# 花色偏移: 0=黑桃 1=红桃 2=方块 3=梅花,绑定对应前景色
suits = {
    0: BLACK_FG,
    1: RED_FG,
    2: RED_FG,
    3: BLACK_FG
}
# 有效牌面偏移 (A-K)
ranks_offset = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]

# 生成 4花色×13张牌,记录草花K编码
club_k_code = None
for suit_offset, fg_color in suits.items():
    for rank in ranks_offset:
        code = 0x1F0A0 + suit_offset * 16 + rank
        card_char = chr(code)
        deck.append(card_char)
        # 拼接:前景色+白色背景+字符+重置
        colored_card = f"{fg_color}{WHITE_BG}{card_char}{RESET}"
        colored_deck.append(colored_card)
        # 捕获草花K编码
        if suit_offset == 2 and rank == 14:
            club_k_code = code

# 处理大小王
joker_small_code = 0x1F0DF  # 小王:草花K+1
joker_big_code = 0x1F0CF           # 大王标准编码

# 小王:白背景+黑前景;大王:保持原样
joker_small = f"{BLACK_FG}{WHITE_BG}{chr(joker_small_code)}{RESET}"
joker_big = chr(joker_big_code)

# 加入两个列表
deck.append(chr(joker_small_code))
deck.append(chr(joker_big_code))
colored_deck.append(joker_small)
colored_deck.append(joker_big)

# 验证与输出
for card in colored_deck:
    print(card, end=" ")

洗牌

  • 洗牌

图片描述

import random
BLACK_FG = "\033[30m"   # 黑色前景
RED_FG = "\033[31m"     # 红色前景
WHITE_BG = "\033[47m"   # 白色背景
RESET = "\033[0m"       # 重置所有样式

deck = []
colored_deck = []

# 花色偏移: 0=黑桃 1=红桃 2=方块 3=梅花,绑定对应前景色
suits = {
    0: BLACK_FG,
    1: RED_FG,
    2: RED_FG,
    3: BLACK_FG
}
# 有效牌面偏移 (A-K)
ranks_offset = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]

# 生成 4花色×13张牌,记录草花K编码
club_k_code = None
for suit_offset, fg_color in suits.items():
    for rank in ranks_offset:
        code = 0x1F0A0 + suit_offset * 16 + rank
        card_char = chr(code)
        deck.append(card_char)
        # 拼接:前景色+白色背景+字符+重置
        colored_card = f"{fg_color}{WHITE_BG}{card_char}{RESET}"
        colored_deck.append(colored_card)
        # 捕获草花K编码
        if suit_offset == 2 and rank == 14:
            club_k_code = code

# 处理大小王
joker_small_code = 0x1F0DF  # 小王:草花K+1
joker_big_code = 0x1F0CF           # 大王标准编码

# 小王:白背景+黑前景;大王:保持原样
joker_small = f"{BLACK_FG}{WHITE_BG}{chr(joker_small_code)}{RESET}"
joker_big = chr(joker_big_code)

# 加入两个列表
deck.append(chr(joker_small_code))
deck.append(chr(joker_big_code))
colored_deck.append(joker_small)
colored_deck.append(joker_big)

random.shuffle(colored_deck)

# 验证与输出
for card in colored_deck:
    print(card, end=" ")

洗牌结果

图片描述

  • 扑克有啥玩法呢?

升级

  • 4个人
    • 每人抓12轮
    • 总共抓48张
    • 还剩6张
    • 扣为底牌

图片描述

  • 底牌归当前轮的庄家

抓牌

import random
BLACK_FG = "\033[30m"   # 黑色前景
RED_FG = "\033[31m"     # 红色前景
WHITE_BG = "\033[47m"   # 白色背景
RESET = "\033[0m"       # 重置所有样式

deck = []
colored_deck = []

# 花色偏移: 0=黑桃 1=红桃 2=方块 3=梅花,绑定对应前景色
suits = {
    0: BLACK_FG,
    1: RED_FG,
    2: RED_FG,
    3: BLACK_FG
}
# 有效牌面偏移 (A-K)
ranks_offset = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]

# 生成 4花色×13张牌,记录草花K编码
club_k_code = None
for suit_offset, fg_color in suits.items():
    for rank in ranks_offset:
        code = 0x1F0A0 + suit_offset * 16 + rank
        card_char = chr(code)
        deck.append(card_char)
        # 拼接:前景色+白色背景+字符+重置
        colored_card = f"{fg_color}{WHITE_BG}{card_char}{RESET}"
        colored_deck.append(colored_card)
        # 捕获草花K编码
        if suit_offset == 2 and rank == 14:
            club_k_code = code

# 处理大小王
joker_small_code = 0x1F0DF  # 小王:草花K+1
joker_big_code = 0x1F0CF           # 大王标准编码

# 小王:白背景+黑前景;大王:保持原样
joker_small = f"{BLACK_FG}{WHITE_BG}{chr(joker_small_code)}{RESET}"
joker_big = chr(joker_big_code)

# 加入两个列表
deck.append(chr(joker_small_code))
deck.append(chr(joker_big_code))
colored_deck.append(joker_small)
colored_deck.append(joker_big)

random.shuffle(colored_deck)

dong = colored_deck[0:48:4]
nan = colored_deck[1:48:4]
xi = colored_deck[2:48:4]
bei = colored_deck[3:48:4]
di = colored_deck[-6:]
print("\n东:" + " ".join(dong))
print("南:" + " ".join(nan))
print("西:" + " ".join(xi))
print("北:" + " ".join(bei))
print("底:" + " ".join(di))
  • 抓牌結果

图片描述

  • 牌抓到手里 还是要理一理的

最終代碼

import random
BLACK_FG = "\033[30m"   # 黑色前景
RED_FG = "\033[31m"     # 红色前景
WHITE_BG = "\033[47m"   # 白色背景
RESET = "\033[0m"       # 重置所有样式

deck = []
colored_deck = []

# 花色偏移: 0=黑桃 1=红桃 2=方块 3=梅花,绑定对应前景色
suits = {
    0: BLACK_FG,
    1: RED_FG,
    2: RED_FG,
    3: BLACK_FG
}
# 有效牌面偏移 (A-K)
ranks_offset = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]

# 生成 4花色×13张牌,记录草花K编码
club_k_code = None
for suit_offset, fg_color in suits.items():
    for rank in ranks_offset:
        code = 0x1F0A0 + suit_offset * 16 + rank
        card_char = chr(code)
        deck.append(card_char)
        # 拼接:前景色+白色背景+字符+重置
        colored_card = f"{fg_color}{WHITE_BG}{card_char}{RESET}"
        colored_deck.append(colored_card)
        # 捕获草花K编码
        if suit_offset == 2 and rank == 14:
            club_k_code = code

# 处理大小王
joker_small_code = 0x1F0DF  # 小王:草花K+1
joker_big_code = 0x1F0CF           # 大王标准编码

# 小王:白背景+黑前景;大王:保持原样
joker_small = f"{BLACK_FG}{WHITE_BG}{chr(joker_small_code)}{RESET}"
joker_big = chr(joker_big_code)

# 加入两个列表
deck.append(chr(joker_small_code))
deck.append(chr(joker_big_code))
colored_deck.append(joker_small)
colored_deck.append(joker_big)

random.shuffle(colored_deck)

dong = colored_deck[0:48:4]
nan = colored_deck[1:48:4]
xi = colored_deck[2:48:4]
bei = colored_deck[3:48:4]
di = colored_deck[-6:]
dong.sort()
nan.sort()
xi.sort()
bei.sort()

print("\n东:" + " ".join(dong))
print("南:" + " ".join(nan))
print("西:" + " ".join(xi))
print("北:" + " ".join(bei))
print("底:" + " ".join(di))
  • 这样同样花色就被理顺了

列表函數总结

  • 列表所有方法

图片描述

  • 再复习一遍
功能类别 方法名称 操作说明(简化)
🔹 元素添加 append 列表末尾添加单个元素(任意类型)
extend 末尾批量添加可迭代对象元素(展开)
insert 指定索引位置插入单个元素,后续元素后移
🔹 元素删除 remove 查找并删除第一个匹配 value 的元素
pop 删除并返回指定索引元素,默认删最后一个
clear 清空列表所有元素,保留列表对象
🔹 查找与统计 index 查找并返回第一个匹配 value 的索引
count 统计 value 元素出现的次数
🔹 排序与反转 sort 原地排序,支持自定义规则
reverse 原地反转列表元素顺序
🔹 复制操作 copy 返回列表的浅拷贝新列表
  • 需要有所突破了

总结

  • 这次 我们了解了 无序
    • 排序 可以 让列表 有序
    • 随机 可以 让列表 无序
  • 无序有序都用
    • 有序带来理性的方便
    • 无序带来混沌的快乐

图片描述

  • 洗牌、码牌、抓牌、看牌
    • 理牌 可以让手里的牌
    • 有适合出牌的次序

图片描述

  • 目前 列表 都是 一维的
    • 可以 升到 有更高维度 吗? 🤔
  • 下次再说 👋
  • 配套视频

  • 本文来自 oeasy Python 系统教程。
  • 想完整、扎实学 Python,
  • 搜索 oeasy 即可。