面向对象编程—掷骰子游戏
最近编了一个面向编程的经典游戏案例,根据游戏的规则,设计编程的流程和类,方法,属性。这是一个比较经典和流行的面向对象编程的玩骰子的小游戏。
整个游戏分为四个模块:
◆ 主菜单模块(main_menu.py)
◊ 功能:导入主程序模块,定义一个AllThatDice类, 定义一个run函数
◆ 主程序模块(main.py)
◊ 功能:程序运行主界面,游戏玩家名单注册、显示游戏的总成绩、进入游戏、退出游戏。
playGame函数,参数为游戏名, getTable函数
◆ 游戏玩家模块(Person.py)
◊ 功能:定义人员类,属性包括玩家游戏初始币值、获胜场数、玩的总场数
won函数、res函数、play函数
◆ 游戏模块(Games.py)
◊ 功能:定义游戏类Game:
§ 属性–骰子点数元组、参与游戏的最少玩家人数、最多玩家人数
§ find函数,参数为玩家姓名,playIt函数,makeBid函数、sifter函数
定义奇偶游戏子类Odd_or_Even(Game):
§ 属性–游戏玩家账号account,参数为默认最少玩家数1,最多玩家数1,游戏名称“Odd-or-Even”
§ play函数
定义Maxi(Game)游戏子类:
§ 属性–游戏玩家账号,参数为默认最少玩家数3,最多玩家数5,游戏名称“Maxi”
§ play函数
定义Bunco(Game)游戏子类:
§ 属性–游戏玩家账号,参数为默认最少玩家数2,最多玩家数4,游戏名称“Bunco”
§ play函数
游 戏 简 介
这款游戏的玩法分三种,第一种Odd-or_Even(猜奇偶数),只有一个玩家玩骰子。就是猜测骰子出现的数字是奇数还是偶数。如果猜对了,就算赢了。第二种游戏是Maxi,需要最少3个玩家,最多5个玩家掷一对骰子。每个玩家按顺序投掷一对骰子,正面朝上的数值总和最高的玩家获胜,如果一个玩家抛出香哦太难的最高金额,那么这些玩家将继续与其他玩家一起玩游戏。第三种游戏Bunco,需要最少2个玩家,最多4个玩家玩3个骰子。一共六轮游戏,每轮游戏,按顺序玩家投掷骰子,如果骰子的正面的数值与当前的游戏的轮数都不相等,那么不得分,轮到下一个游戏玩家,如果下一个游戏玩家投掷3个骰子,有一个正面朝上的骰子的数值与当前的轮数相等,那么加1point,该玩家继续投掷骰子,如果出现2个正面朝上的骰子的数值与当前轮数相等,那么该玩家加2points,那么如果出现3个骰子的正面朝上的数值与当前轮数不相等,但是三个骰子的数值相等,该玩家加5个points,继续投掷骰子,直到3个骰子中没有出现与该轮游戏轮数相等的数值,换下一个游戏玩家,每个游戏玩家的points累计相加,如果超过21,那么本轮游戏结束,达到或者超过21points的玩家就是本轮游戏的获胜者,如果出现3个骰子的正面数值都与该轮游戏轮数相等,那么就是“Bunco!”,并且加21points,该轮游戏结束,进入下一轮,而且下一轮首先出现的游戏玩家是当前结束的游戏玩家的下一个。
游 戏 运 行 环境
开发环境: PyCharm 2020
开发语言:Python3.9
游 戏 界 面
1. 主界面
包括四个选项,① 注册新游戏玩家 ② 显示游戏排行榜 ③ 玩游戏。④ 退 出,如下图红框所示:
2. 玩游戏之前,必须先注册游戏玩家
根据上图所示,选择输入r,进入游戏玩家注册界面,如下图所示:
3. 开始玩游戏
输入p,进入游戏界面,如下图所示:
4. 游戏界面出现三款游戏,进行选择
4.1选择o, 进行奇偶游戏
如下图所示:
4.2选择m, 进入Maxi游戏
如下图所示:
4.3 选择b, 进入Bunco游戏
如下图所示:
附上源码:
Games.py
import random
import Person
# 游戏类
class Game:
s = ("x", "⚀", "⚁", "⚂", "⚃", "⚄", "⚅")
g_name = ""
g_max = 0
g_min = 0
# 参与游戏的玩家人数
num_people = 0
bid = {
} # 筹码字典
n = 0 # 玩家数
Pond = 0 # 奖池
account = [] # 账户
def __init__(self, a, b, s):
self.g_min = a
self.g_max = b
self.g_name = s
def find(self, name):
for i in range(len(self.account)):
if self.account[i].name == name:
return i
return -1
# 进行游戏
def playIt(self):
if len(self.account) >= self.g_min:
print("Let’s play the game of " + self.g_name + "!")
print("How many players (" + str(self.g_min) + "-" + str(self.g_max) + ")?")
return 1
else:
print("Not enough players to play " + self.g_name + ".")
# 下注
def makeBid(self):
# 玩家数检查
while True:
self.num_people = input(">")
self.num_people = int(self.num_people)
if self.g_min <= self.num_people <= self.g_max:
break
else:
print("Invalid choice.\n")
try:
# 参与玩家
for i in range(1, self.num_people + 1):
id1 = 0
# 姓名录入
while True:
print("What is the name of player #" + str(i) + "?")
name = input(">")
if self.find(name) != -1:
if not (name in self.bid):
id1 = self.find(name)
self.account[id1].play()
break
else:
print(name + " is already in the game.\n")
else:
print("There is no player named " + name + ".")
# 赌注录入
while True:
print("How many chips would you bid " + name + " (1-" + str(self.account[id1].coin) + ")?")
bid_i = input(">")
bid_i = int(bid_i)
if 1 <= bid_i <= self.account[id1].coin:
self.bid[name] = bid_i
self.account[id1].coin -= bid_i
self.Pond += bid_i
break
else:
print("Invalid number of chips.")
except:
print('请核实输入的信息!!')
# 获取筛子
def sifter(self, i):
n = i + random.randint(1, 6)
n %= 6
if n == 0: return 6
return n
# 赔率设置,输则扣掉bid,赢则获得bid
class Odd_or_Even(Game):
def __init__(self, account):
Game.__init__(self, 1, 1, "Odd-or-Even")
self.account = account
def play(self):
if not self.playIt():
return
self.makeBid()
arr = []
i = 0
for key in self.bid.keys():
per = self.account[self.find(key)]
o = 'e'
odd = 0
while True:
print("Hey " + key + ", Odd (o) or Even (e)?")
o = input(">")
if o == 'o' or o == 'e':
if o == 'o':
odd = 1
else:
odd = 0
break
else:
print("Invalid choice.\n")
s = 0
while True:
print("How strong will you throw (0-5)?")
s = int(input(">"))
if 0 <= s <= 5:
break
else:
print("Invalid choice.")
s = self.sifter(s)
print(self.s[s])
if s % 2 == odd:
per.coin += self.Pond * 2
per.won()
print("Congratulations, " + key + "! You win!")
else:
print("Sorry, " + key + "! You lose!")
# 赔率设置,赢家获得全部pond
class Maxi(Game):
def __init__(self, account):
Game.__init__(self, 3, 5, "Maxi")
self.account = account
def play(self):
if not self.playIt():
return
self.makeBid()
print("Let the game begin!")
while True:
num = {
}
nums = []
for name in self.bid.keys():
print("It’s " + name + "’s turn.")
a = 0
b = 0
c = 0
while True:
print("How strong will you throw (0-5)?")
c = int(input(">"))
if 0 <= c <= 5:
break
else:
print("Invalid choice.\n")
a = self.sifter(c)
b = self.sifter(c)
print(self.s[a] + " " + self.s[b])
# print(str(a) + "个点" + " " + str(b) + "个点") # 防止看不清骰子
nums.append(a + b)
num[name] = a + b
n = 0
maxn = max(nums)
for i in nums:
if maxn == i:
n += 1
if n == 1:
for name in num.keys():
if num[name] == maxn:
e = self.account[self.find(name)]
e.coin += self.Pond
e.won()
print("Congratulations, " + name + "! You win!")
return
else:
print("Players remaining:")
for name in num.keys():
if num[name] == maxn:
print(name + ',')
else:
del self.bid[name]
class Bunco(Game):
def __init__(self, account):
Game.__init__(self, 2, 4, "Bunco")
self.account = account
self.rnd_stop_flag = False
def play(self):
if not self.playIt():
return
self.makeBid()
# 轮数
rnd = 1
# 总成绩列表
total_score = []
# 定义一个Bunco字典,键为玩家姓名,值为Bunco
bunco = {
}
# 定义赢家赢的轮数字典, 键为玩家姓名,值为赢的轮数
win_round = {
}
# 参与游戏的玩家列表
player_lst = list(self.bid.keys())
# 为每个玩家的bunco初始化为0
for name in self.bid.keys():
bunco[name] = 0
win_round[name] = 0
turn_i = 0
while rnd <= 6:
self.rnd_stop_flag = False
# 把筹码字典键转成列表
name_lst = list(self.bid.keys())
# 遍历玩家名字列表,首轮玩家名字列表索引默认为0
for i in range(turn_i, len(name_lst)):
# 判断本轮游戏是否结束,如果结束退出本轮循环
if self.rnd_stop_flag:
break
# 这样才能做到每轮的结果不变,否则都是最后一轮的游戏结果
score = str(rnd)
score = {
}
print("<Round " + str(rnd) + ">")
for name in self.bid.keys():
# 每一轮开始之前,得分字典清零
score['Round'] = rnd
score[name] = 0
while True:
print("It’s " + name_lst[i] + "’s turn.")
a = 0
b = 0
c = 0
d = 0
while True:
print("How strong will you throw (0-5)?")
# 异常处理,否则输入非数字程序会崩溃退出
try:
d = int(input(">"))
if 0 <= d <= 5:
break
else:
print("Invalid choice.\n")
except:
print('Please input the number(0-5)!!')
pass
a = self.sifter(d)
b = self.sifter(d)
c = self.sifter(d)
print(self.s[a] + " " + self.s[b] + " " + self.s[c])
print(str(a) + "个点" + " " + str(b) + "个点" + " " + str(c) + "个点")
# 如果一个骰子的点数与游戏的轮数相等
if (a == rnd and a != b and a != c) or (b == rnd and a != b and b != c) or (
c == rnd and c != a and c != b):
score[name_lst[i]] += 1
print("You earned 1 point," + str(score[name_lst[i]]) + " points in total.")
if score[name_lst[i]] >= 21:
# 输出本轮游戏赢家名字
print(f"{name_lst[i]} is the winner in round {rnd}!")
# 把本轮的分值添加到列表
total_score.append(score)
win_round[name_lst[i]] += 1
#print(total_score)
#print(bunco)
# 跳到下一个人
turn_i = i + 1
# 判断是否超过玩家名字列表的索引范围
if turn_i == len(name_lst):
turn_i = 0
rnd += 1
self.rnd_stop_flag = True
print(f'===== 第{rnd-1}轮游戏结束!=====')
if rnd<=6:
print(f'===== 开启第{rnd}轮游戏!=====')
break
else:
print(f"Keep playing {name_lst[i]}")
# 如果 两个骰子的点数相同,而且两个点子数等于游戏的轮数,加2points
elif (a == b == rnd and a != c) or (a == c == rnd and a != b) or (b == c == rnd and b != a):
score[name_lst[i]] += 2
print("You earned 2 point," + str(score[name_lst[i]]) + " points in total.")
# 判断该游戏玩家总points是否超过21points
if score[name_lst[i]] >= 21:
# 输出本轮游戏赢家名字
print(f"{name_lst[i]} is the winner in round {rnd}!")
# 把本轮的分值添加到列表
total_score.append(score)
win_round[name_lst[i]] += 1
#print(total_score)
#print(bunco)
# 跳到下一个人
turn_i = i + 1
# 判断是否超过玩家名字列表的索引范围
if turn_i == len(name_lst):
turn_i = 0
rnd += 1
self.rnd_stop_flag = True
print(f'===== 第{rnd-1}轮游戏结束!=====')
if rnd<=6:
print(f'===== 开启第{rnd}轮游戏!=====')
break
else:
print(f"Keep playing {name_lst[i]}")
# 如果三个骰子的点数一样,但是不等于游戏的轮数,加5points
elif a == b == c and a != rnd:
score[name_lst[i]] += 5
print("You earned 5 point," + str(score[name_lst[i]]) + " points in total.")
# print(score)
# 判断该游戏玩家的总points是否超过21points
if score[name_lst[i]] >= 21:
# 输出本轮游戏赢家名字
print(f"{name_lst[i]} is the winner in round {rnd}!")
# 把本轮的分值添加到列表
total_score.append(score)
win_round[name_lst[i]] += 1
#print(total_score)
#print(bunco)
# 跳到下一个人
turn_i = i + 1
# 判断是否超过玩家名字列表的索引范围
if turn_i == len(name_lst):
turn_i = 0
rnd += 1
self.rnd_stop_flag = True
print(f'===== 第{rnd-1}轮游戏结束!=====')
if rnd <= 6:
print(f'===== 开启第{rnd}轮游戏!=====')
break
else:
print(f"Keep playing {name_lst[i]}")
# 如果没有一个骰子的点数跟游戏轮数一样,没有point,换人
elif a != rnd and b != rnd and c != rnd:
print("You earned no points, " + str(score[name_lst[i]]) + " points in total.")
# print(score)
i += 1
# 判断是否超过玩家名字列表的索引范围
if i == len(name_lst):
i = 0
# 如果骰子点数都等于轮数,结束本轮游戏,进入下一轮
elif a == b == c == rnd:
print("Bunco!")
print("You earned 21 points, " + str(score[name_lst[i]] + 21) + " points in total.")
print(f"{name_lst[i]} is the winner in round {rnd}!\n\n")
score[name_lst[i]] += 21
# 为每个人玩家赢得的bunco记录
bunco[name_lst[i]] += 1
# 把本轮的分值添加到列表
total_score.append(score)
win_round[name_lst[i]] += 1
# print(total_score)
# print(bunco)
# 跳到下一个人
turn_i = i + 1
# 判断是否超过玩家名字列表的索引范围
if turn_i == len(name_lst):
turn_i = 0
rnd += 1
self.rnd_stop_flag = True
print(f'===== 第{rnd-1}轮游戏结束!=====')
if rnd <=6:
print(f'===== 开启第{rnd}轮游戏!=====')
break
# 把Bunco值转成列表
bunco_lst = list(bunco.values())
# 输出六轮游戏的总数据
print('=' * 40)
for key in total_score[0].keys():
print(key, end='\t\t')
print('\n' + '=' * 40)
# 把总列表中第一个字典的所有键转成列表
name_lst = list(total_score[0].keys())
# 玩家人数等于列表中去掉第一个元素(round),其余就是游戏玩家的数
num_people1 = len(name_lst) - 1
# 玩家的六轮总points汇总作为sum列表的元素
sum = []
# 玩家的人数最少2位最多4位
if num_people1 == 2:
sum = [0, 0]
# 0-5 代表 游戏1-6轮
for new_i in range(6):
# 遍历六轮的游戏的points值
for value in total_score[new_i].values():
print(value, end='\t\t\t')
sum[0] += list(total_score[new_i].values())[1]
sum[1] += list(total_score[new_i].values())[2]
print()
print('=' * 40)
print('Total' + '\t\t' + str(sum[0]) + '\t\t\t' + str(sum[1]))
print('=' * 40)
print('Bunco' + '\t\t' + str(bunco_lst[0]) + '\t\t\t' + str(bunco_lst[1]))
print('=' * 40)
# 取bunco最大值
result = max(list(bunco.values()))
#print(result)
# 取sum最大值
max_sum = max(sum)
# 取赢的轮数最大值
max_round = max(list(win_round.values()))
for player in player_lst:
# 玩家赢的轮数和bunco都是最高的,输出
if win_round[player] == max_round:
print(player + ' won ' + str(win_round[player]) + ' rounds,' + ' scoring ' + str(
max_sum) + ' points,' + ' with ' + str(result) + ' Buncos.')
print(f'Congratulations, {player}!, You win! ')
else:
pass
# 游戏玩家3个人
elif num_people1 == 3:
sum = [0, 0, 0]
for new_i in range(6):
for value in total_score[new_i].values():
print(value, end='\t\t\t')
sum[0] += list(total_score[new_i].values())[1]
sum[1] += list(total_score[new_i].values())[2]
sum[2] += list(total_score[new_i].values())[3]
print()
print('=' * 40)
print('Total' + '\t\t' + str(sum[0]) + '\t\t\t' + str(sum[1]) + '\t\t\t' + str(sum[2]))
print('=' * 40)
print('Bunco' + '\t\t' + str(bunco_lst[0]) + '\t\t\t' + str(bunco_lst[1]) + '\t\t\t' + str(bunco_lst[2]))
print('=' * 40)
# 取bunco最大值
result = max(list(bunco.values()))
# 取sum最大值
max_sum = max(sum)
# 取赢的轮数最大值
max_round = max(list(win_round.values()))
for player in player_lst:
# 玩家赢的轮数和bunco都是最高的,输出
if win_round[player] == max_round:
print(player + ' won ' + str(win_round[player]) + ' rounds,' + ' scoring ' + str(
max_sum) + ' points,' + ' with ' + str(result) + ' Buncos.')
print(f'Congratulations, {player}!, You win! ')
else:
pass
elif num_people1 == 4:
sum = [0, 0, 0, 0]
for new_i in range(6):
for value in total_score[new_i].values():
print(value, end='\t\t\t')
sum[0] += list(total_score[new_i].values())[1]
sum[1] += list(total_score[new_i].values())[2]
sum[2] += list(total_score[new_i].values())[3]
sum[3] += list(total_score[new_i].values())[4]
print()
print('=' * 40)
print('Total' + '\t\t' + str(sum[0]) + '\t\t\t' + str(sum[1]) + '\t\t\t' + str(sum[2]) + '\t\t\t' + str(sum[3]))
print('=' * 40)
print('Bunco' + '\t\t' + str(bunco_lst[0]) + '\t\t\t' + str(bunco_lst[1]) + '\t\t\t' + str(bunco_lst[2]) +'\t\t\t' +str(bunco_lst[3]))
print('=' * 40)
# 取bunco最大值
result = max(list(bunco.values()))
# 取sum最大值
max_sum = max(sum)
# 取赢的轮数最大值
max_round = max(list(win_round.values()))
for player in player_lst:
# 玩家赢的轮数和bunco都是最高的,输出
if win_round[player] == max_round:
print(player + ' won ' + str(win_round[player]) + ' rounds,' + ' scoring ' + str(
max_sum) + ' points,' + ' with ' + str(result) + ' Buncos.')
print(f'Congratulations, {player}!, You win! ')
else:
pass
Person.py
class Per:
coin = 100
name = ""
# 胜场
won_num = 0
# 总场
play_num = 0
def __init__(self, name):
self.name = name
def res(self, n):
self.coin = n
def won(self):
self.won_num += 1
def play(self):
self.play_num += 1
Main.py
import Games
import Person
account = []
def find(name):
for i in range(len(account)):
if account[i].name == name:
return True
else:
return False
# 增加玩家
def add(name):
if find(name):
print("Sorry, the name is already taken.")
else:
# 账户初始额度100
account.append(Person.Per(name))
print("Welcome, " + name + "!")
# 进行游戏
def playGame(game):
if game == 'o':
e = Games.Odd_or_Even(account)
e.play()
elif game == 'm':
e = Games.Maxi(account)
e.play()
elif game == 'b':
e = Games.Bunco(account)
e.play()
else:
print("Invalid choice.")
def getTable():
print("=============================\n")
print("Name Played Won Chips\n")
print("=============================\n")
account.sort(key=lambda x: x.coin, reverse=True)
for a in account:
print(a.name, str(a.play_num).rjust(16-len(a.name)), str(a.won_num).rjust(4), str(a.coin).rjust(6), "\n")
print("=============================")
# 主函数
print("\n> Welcome to All-That-Dice!" +
"\n> Developed by Bruce_Liuxiaowei" +
"\n> Object-Oriented Programming\n> Date:2022-06-02")
while True:
print("\nWhat would you like to do?" +
"\n(r) register a new player" +
"\n(s) show the leader board" +
"\n(p) play a game" +
"\n(q) quit")
flag = input(">")
if flag == 'r':
print("What is the name of the new player?")
add(input(">"))
elif flag == 's':
getTable()
elif flag == 'p':
print("Which game would you like to play?\n" +
"(o) Odd-or-Even\n" + "(m) Maxi\n" + "(b) Bunco")
playGame(input(">"))
elif flag == 'q':
print("\nThank you for playing All-That-Dice!")
break
else:
print("Invalid choice.")
input()
Main_menu.py
import main
# 定义一个所有骰子游戏的类
class AllThatDice:
def run(self):
main.py
if __name__ == "__main__":
my_all_that_dice = AllThatDice()
my_all_that_dice.run()