总项目目标:用面向过程思想设计一个简单的纸牌游戏程序,称为"Higher or Lower"(高还是低)。游戏中,玩家需要猜测接下来的一张牌是比当前牌高还是低。根据猜测的准确性,玩家可以得到或失去相应的积分。为后续对比面向对象编程思想做准备。
项目1.6 完整的猜大小纸牌游戏
import random
SUIT_TUPLE = ('黑桃', '红心', '梅花', '方块')
RANK_TUPLE = ('A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K')
# 洗牌函数
def shuffle(deckListIn):
deckListOut = deckListIn.copy() # 生成一副牌的副本
random.shuffle(deckListOut) # 洗牌
return deckListOut
# 抽牌函数
def getCard(deckListIn):
thisCard = deckListIn.pop() # 从牌组中取第一张牌
return thisCard
# 欢迎界面
print("欢迎来到猜大小纸牌游戏,游戏规则如下:")
print("游戏开始时,玩家有50分。")
print("从一副牌中随机抽取一张牌作为当前牌。")
print("玩家需要猜测下一张牌的大小是高还是低。")
print("如果玩家猜对了,得20分;如果猜错了,扣15分。")
print("游戏进行8轮,每轮玩家需要猜测下一张牌的大小。")
print("猜完8轮后,玩家可以选择再次玩游戏或退出游戏。")
# 存储生成的初始牌组
startingDeckList = []
# 两个嵌套的循环创建一个包含牌的字典cardDict,其中包括点数、花色和用于比较大小的值
# 并将各张牌的字典添加到startingDeckList列表中。
for suit in SUIT_TUPLE:
for thisValue, rank in enumerate(RANK_TUPLE):
cardDict = {'rank': rank, 'suit': suit, 'value': thisValue + 1}
startingDeckList.append(cardDict)
# 游戏开始时,玩家有50分
score = 50
while True: # 游戏一直重复,除非退出
# 游戏正式开始,第一件事是洗牌,将返回的洗牌后的牌组赋值给gameDeckList
gameDeckList = shuffle(startingDeckList)
# 抽取第一张牌,将该牌的信息以字典形式保存在currentCardDict中
currentCardDict = getCard(gameDeckList)
# 将抽到的这张牌的各个信息通过字典索引拿出,包括花色,点数,和比较用的值
currentCardRank = currentCardDict['rank']
currentCardValue = currentCardDict['value']
currentCardSuit = currentCardDict['suit']
print('该副牌第一张是: ', currentCardSuit+currentCardRank)
print()
# 游戏抽8次牌进行比较
for cardNumber in range(0,8):
# 在进行牌的比较前,用户通过输入'h'或'l'来猜测下一张牌的大小。
answer = input("猜猜下一张牌是大于还是小于当前的牌: " +
currentCardSuit + currentCardRank +
"(输入 h 或 l)")
answer = answer.casefold() # 为了只判断小写字母
# 抽取下一张牌,将牌的信息以字典形式保存在nextCardDict中
nextCardDict = getCard(gameDeckList)
# 将下一张牌的各个信息通过字典索引拿出,包括花色,点数,和比较用的值
nextCardRank = nextCardDict['rank']
nextCardValue = nextCardDict['value']
nextCardSuit = nextCardDict['suit']
if answer == 'h':
# 在条件判断语句中,比较下一张牌的值与当前牌的值。
if nextCardValue > currentCardValue:
print("你猜对了, ")
score = score + 20 # 如果玩家猜对了,得20分
else:
print("你猜错了")
score = score - 15 # 如果猜错了,扣15分。
elif answer == 'l':
if nextCardValue < currentCardValue:
print("你猜对了")
score = score + 20
else:
print("你猜错了")
score = score - 15
print("下张牌是: " + nextCardSuit + nextCardRank)
print()
print("你当前得分:", score)
# 更新当前牌的信息为下一张牌的信息,为下一轮比较做准备。
# 在下一轮的比较中,当前牌会变成上一轮比较中抽取到的下一张牌,以便玩家可以继续猜测下一张牌的大小。
currentCardRank = nextCardRank
currentCardValue = nextCardValue
currentCardSuit = nextCardSuit
goAgain = input('如果想在玩一次,按回车,或按q退出')
if goAgain == 'q':
break
print("再见")
效果如下:
程序分析:
这个程序实现了一个简单的猜大小纸牌游戏。以下是程序的解释:
-
输出游戏的欢迎界面,介绍游戏规则,创建一个空的牌组列表。
-
使用两个嵌套的循环创建一副牌的字典,并将每张牌的字典添加到
startingDeckList
列表中。初始化玩家的初始得分为 50。 -
进入游戏循环,循环开始时进行洗牌操作,使用
getCard()
函数抽取第一张牌,并将该牌的信息存储在currentCardDict
中。从currentCardDict
字典中获取当前牌的花色、点数和比较用的值。打印当前抽到的第一张牌。 -
进入循环进行8次牌的比较。
-
在循环中,玩家通过输入 'h' 或 'l' 来猜测下一张牌是大于还是小于当前牌。
-
使用
getCard()
函数抽取下一张牌,并将该牌的信息存储在nextCardDict
中。 -
从
nextCardDict
字典中获取下一张牌的花色、点数和比较用的值。 -
根据玩家的猜测和下一张牌的值进行判断,更新玩家的得分。
-
打印下一张牌的信息和当前得分。
-
更新当前牌的信息为下一张牌的信息,为下一轮比较做准备。
-
在循环结束后,询问玩家是否想再次玩游戏,如果输入 'q' 则退出游戏,否则继续下一轮游戏。
-
打印 "再见",游戏结束。
这个程序的面向对象方面存在一些不足之处:
-
缺乏类的抽象和封装:整个程序都被写在了一个主函数中,并没有使用类来进行适当的抽象和封装。这导致程序的结构相对松散,代码的可重用性和可扩展性较差。
-
数据和功能耦合:程序中的数据(如牌的点数、花色等)和功能(如洗牌、抽牌等)没有被适当地封装在类的属性和方法中,而是通过全局变量和函数进行处理。这种耦合性使得代码难以维护和扩展。
-
缺乏面向对象设计原则:程序中没有明确地应用面向对象设计原则,如单一职责原则、开闭原则等。这使得代码结构和逻辑流程相对混乱,难以进行模块化和重用。
-
缺乏对象的交互和组合:程序中没有明确定义和管理对象之间的交互关系,而是通过函数和全局变量来进行数据传递和状态更新。这样的设计使得代码的可读性和可维护性较差。