软工课设06_第24组_week 10

#文档名:软工课设06_第24组_week 8
#编写人:尹鸿伟
#校对:杨彦军
#编写时间:2020年11月2日 10:11:20



8-9周项目进度

  • 在第8周开始时我们完成了对本项目的总体设计,完成了需求分析等工作,整体项目已经确定方向并且心中已经有了雏形。
  • 在第9周刚开始时我们已经完成了程序的第一版开发,即控制台版本的黄金点游戏,玩家在控制台一次输入数据,并在控制台反馈最终得分,同样也能通过matplotlib生成的图片来直观的体会结果
  • 通过短暂几天的学习,我们最终在第9周末尾的时候完成了GUI程序的开发,用户输入和结果展示等都实现了图形化界面。

程序方法介绍

  • _ init_()方法:定义了GameBoard类和Player类的属性,GameBardr类中有playerNum储存玩家数量,players [ ] 储存实例化的玩家,g_nums [ ] 储存每轮的G值,player_scores [score, last_input] 存储玩家分数和最后一轮输入player_inputs [ [ ], [ ] ]储存玩家每轮输入。Player类中每个玩家有对应的id。
  • get_player_number:从键盘获得玩家数量。本函数中还包含一个**get_entry()**函数,此函数规定了玩家数量只能输入整形切不能小于0。
  • get_player_input:从键盘获得玩家每轮的输入,此函数中同样包含一个**get_entry()**函数,此函数规定了玩家输入只能为float型,切必须大于0小于100。
  • start_round():判断是否再来一局游戏。
  • get_player_input():将玩家的输入储存到player_scores,并且在此函数中完成G值的计算。
  • get_result:计算每位玩家的输入与G值的差值的绝对值,并且返回一个玩家差值绝对值升序排列的字典 temp_dic [ (id,abs),…],并为差值绝对值最小的加分,最大的减分。在本函数的最后,我们调用了matplotlib库来更加直观的展示游戏结果,每次游戏的G值用线性图来呈现,每轮每个玩家的输入则用散点图呈现,更加清晰直观的看到G值的走向。

程序源码

GameBoard.py:

"""
文件名:    GameBoard.py
功  能:    游戏主界面类定义。
修改人:    杨彦军,尹鸿伟
修改日期:  2020.11.1
修改内容:  添加游戏GUI界面。
"""
import matplotlib.pyplot as plt
from tkinter import *
from Player import Player


class GameBoard:
    def __init__(self):
        self.playerNum = self.get_player_number()  # 玩家数量
        if 0 == self.playerNum:
            return
        self.players = []  # 存储实例化的玩家
        self.g_nums = []  # 存储每轮的G_num
        self.player_scores = {}  # int: [score, last_input] type, 存储玩家分数和最后一轮输入
        self.player_inputs = []  # [[], []] type, 存储玩家每轮输入
        for player_id in range(self.playerNum):  # 实例化玩家
            self.players.append(Player(player_id))
            self.player_scores[player_id] = [0, 0]
        self.start_round()

    def start_round(self):
        while True:
            self.get_player_input()
            keep_play = self.get_result()
            if 'n' == keep_play:
                break

    def get_player_input(self):
        inputs = []
        for player in self.players:
            player_input = player.get_player_input()
            self.player_scores[player.get_id()][1] = player_input  # 缓存玩家最后一轮输入
            inputs.append(player_input)
        # 计算G_num
        g = sum(inputs) / len(inputs) * 0.618
        self.g_nums.append(g)
        self.player_inputs.append(inputs)

    def get_result(self):
        temp_dic = {}
        # 计算绝对值阶段
        for player_id, player_input in self.player_scores.items():
            temp_dic[player_id] = abs(player_input[-1] - self.g_nums[-1])  # 用户输入与G值的绝对值
        temp_dic = sorted(temp_dic.items(), key=lambda x: x[1], reverse=False)  # 升序排序,返回的temp_dic [(id,abs),...] type
        # 计分阶段
        player_id, player_abs = temp_dic[0]
        for player in temp_dic:  # player (id,abs) type, 遍历查找是否有相同绝对值
            if player_abs != player[1]:
                break
            self.player_scores[player[0]][0] += self.playerNum  # 加N分

        player_id, player_abs = temp_dic[-1]
        for player in temp_dic[::-1]:  # 逆序列表来找绝对值最大的
            if player_abs != player[1]:
                break
            self.player_scores[player[0]][0] += -2  # 加-2分
        # matplotlib展示阶段
        result_window = Tk()
        result_window.title('本轮结束')
        Label(result_window, text='---Score Table---\n' +
                                  ''.join(f'玩家 {player_id} 当前分数 {self.player_scores[player_id][0]}\n'
                                          for player_id in self.player_scores)).grid(row=0, column=0)
        # todo: MATPLOTLIB FIGURE
        fig = plt.figure(figsize=(4, 4), tight_layout=True)
        plt.xlabel('Game Round')
        plt.ylabel('Number')
        plt.plot(self.g_nums, label='G-num', marker='o', ls=':')
        plt.plot(self.player_inputs, marker='x', ls='')
        plt.legend()
        plt.grid()
        from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
        canvas = FigureCanvasTkAgg(fig, master=result_window)
        canvas.draw()
        canvas.get_tk_widget().grid(row=0, column=1)
        plt.close()
        choice = StringVar()
        choice.set('n')

        def get_entry(c):
            choice.set(c)
            result_window.destroy()
            return

        Button(result_window, text='再玩一轮', command=lambda: get_entry('y')).grid(row=2, column=0, sticky=E)
        Button(result_window, text='结束游戏', command=lambda: get_entry('n')).grid(row=2, column=1, sticky=W)
        mainloop()
        return choice.get()

    def get_player_number(self):
        input_window = Tk()
        input_window.title('玩家数量')
        Label(input_window, text='本次游戏共有多少名玩家:').grid(row=0, column=0)
        num = StringVar()
        num.set('0')
        entry = Entry(input_window, width=8, textvariable=num)
        entry.grid(row=0, column=1)
        error_msg = StringVar('')
        Label(input_window, textvariable=error_msg).grid(row=1, column=0, columnspan=2)

        def get_entry():
            try:
                if 0 < int(num.get()):
                    input_window.destroy()
                    return
            except ValueError:
                pass
            error_msg.set('-非法输入,请重新输入-')

        Button(input_window, text='确认', command=get_entry).grid(row=2, column=0, columnspan=2)
        mainloop()
        return int(num.get())


game = GameBoard()

Player.py:

"""
文件名:    Player.py
功  能:    游戏的用户类定义。
修改人:    杨彦军
修改日期:  2020.11.1
修改内容:  添加玩家输入GUI界面。
"""
from tkinter import *


class Player:
    def __init__(self, id):
        self.id = id  # int type

    def get_player_input(self):
        input_window = Tk()
        input_window.title('输入数字')
        Label(input_window, text=f'玩家 {self.id} ,请输入你的数字:').grid(row=0, column=0)
        num = StringVar()
        num.set('0')
        entry = Entry(input_window, width=8, textvariable=num)
        entry.grid(row=0, column=1)
        error_msg = StringVar('')
        Label(input_window, textvariable=error_msg).grid(row=1, column=0, columnspan=2)

        def get_entry():
            try:
                if 0 < float(num.get()) < 100:
                    input_window.destroy()
                    return
            except ValueError:
                pass
            error_msg.set('-非法输入,请重新输入-')

        Button(input_window, text='确认', command= get_entry).grid(row=2, column=0, columnspan=2)
        mainloop()
        return float(num.get())

    def get_id(self):
        return self.id

运行展示

开始游戏,输入玩家数量
玩家分别输入数字
错误输入

玩家分别输入数字

一轮游戏后的结果图
多轮游戏后的结果图

后续展望

  • 把用户输入界面(原在Player类中)整合到Gameboard类中
  • 游戏结束时能讲matplotlib生成的图表保存到本地
  • 完成界面的美化
  • 完成更多代码的注释
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值