黄金点游戏v1.2

    2020年11月30日 字数:4907

继续“黄金点游戏”的版本迭代。

12周的“黄金点游戏”中,我们仅用一个提示窗口简要地描述本轮的游戏状态,以及各玩家在当前轮次结束后的总分。 现在,我们①添加了一个竖式的表格和一个树型的表格,用以描述各玩家目前的输入与得分情况(直接公布),以及历史的得分情况(如果展开树表)。同时,我们②添加了一个轮次-G值的折线图到计分板中,以便玩家分析G值变化的趋势。

avatar

在显示计分板之前,我们③开启了一个语音播报功能;在计分板显示之前,语音将播报本轮的G值,同时播报本轮的获胜玩家名。我们的语音播报段代码有足够的鲁棒性,它支持多个玩家同时获胜的播报,也支持中英文、数字玩家名同时出现时的播报。

综上所述,对比前后两个版本迭代,我们实现了至少三个新的功能。在后续的版本迭代后,我们会优化各功能的显示,并且加入一组更强大的AI与玩家共同游戏(正在实现中,暂未写入当前版本)。

代码如下:

import random
import os
import sys
import time
from tkinter import *
from tkinter import ttk
import tkinter
import tkinter.messagebox as messagebox
import copy
import win32com.client

import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

def on_quit_scoreboard():
    scoreboard = None

class Player:
    def __init__(self):
        self.is_human = False
        self.name = "Hawaii"
        self.score = 0
        self.choice = []
        self.gain = []
    def setPlayerName(self,st):
        self.is_human = True
        self.name = st
    def newChoice(self,mid,x = 0):
        temp = 0
        if not self.is_human:
            temp = mid*(random.randint(0,32767)+1)/(32769)
            if random.randint(0,32767) > 32000:
                temp = min(100-0.000001, temp+0.1*mid*(random.randint(0,32767)+1)/(32769))
        else:
        temp = x
        self.choice.append(temp)
    def win(self,n):
        self.gain.append(n)
        self.score+=n
    def draw(self):
        self.gain.append(0)
        self.score+=0
    def lose(self):
        self.gain.append(-2)
        self.score-=2
    def showName(self):
        return self.name
    def choice_i(self,i):
        i-=1
        if(0<=i and i<len(self.choice)):
            return self.choice[i]
        else:
            return -1
    def gain_i(self,i):
        i-=1
        if(0<=i and i<len(self.gain)):
            return self.gain[i]
        return -1
class Game:
    def Start(self,st):
        self.n = eval(st)
        name_list = []
        label_list = []
        entry_list = []
        for i in range(self.n):
            tmp_label = Label(self.root,text = "玩家"+str(i+1)+"的姓名")
            tmp_label.grid (row = i+1,sticky = E)
            tmp_entry = Entry(self.root)
            tmp_entry.grid (row = i+1,column = 1,sticky = E)
            label_list.append(tmp_label)
            entry_list.append(tmp_entry)
        '''for i in entry_list:
            name_list.append(i.get())'''
        tmp_button = Button(self.root,text = "确定",command = lambda:self.addPlayer(entry_list))
        tmp_button.grid(row = self.n,column = 2,sticky = E)
        #self.root.update()

        #self.newTurn()
    def __init__(self):
        self.n = 0
        self.t = 0
        self.p = []
        self.mindis = 0
        self.maxdis = 0
        self.G_list = []
        self.mindis_list = []
        self.maxdis_list = []
        self.root = Tk()
        self.root.title = ('黄金点游戏')
        l_users = Label(self.root,text = "人数")
        l_users.grid (row=0,sticky = W)
        self.entry0 = Entry(self.root)
        self.entry0.grid(row = 0,column = 1,sticky = E)
        self.scoreboard = None
        
        Button(self.root,text = "开始",command = lambda :self.Start(self.entry0.get())).grid(row = 0,column = 2)
        
        self.root.mainloop()
        '''while self.n<1:
            print("请输入游戏人数:")
            self.n = eval(input())'''
        
        '''for i in range(self.n):
            st = input("请输入玩家"+str(i)+"的姓名(若姓名为AI,则为AI):")
            if(st != "AI"):
                self.p.append(Player())
                self.p[-1].setPlayerName(st)
            else:
                self.p.append(Player())'''
            
        
    def addPlayer(self,entry_list):
        for i in entry_list:
            self.p.append(Player())
            if i.get() != 'AI':
                self.p[-1].setPlayerName(i.get())
        self.newTurn()

    def cal(self):
        avg = 0.0
        for i in self.p:
            avg+=i.choice_i(self.t)
        avg/=self.n
        avg*=0.618
        #print("裁判公布G值:",avg)
        self.G_list.append(avg)
        self.mindis =100.0
        self.maxdis = 0.0
        
        dis = []
        for i in self.p:
            dis.append(abs(i.choice_i(self.t)-avg))
        self.mindis = min(dis)
        self.maxdis = max(dis)
        self.mindis_list.append(self.mindis)
        self.maxdis_list.append(self.maxdis)
        #print("maxdis:",self.maxdis," mindis:",self.mindis)
        for i in range(self.n):
            if dis[i] == self.mindis:
                self.p[i].win(self.n)
            elif dis[i] == self.maxdis:
                self.p[i].lose()
            else :
                self.p[i].draw()

        if self.scoreboard != None :
            self.scoreboard.destroy()

        self.scoreboard = tkinter.Tk()
        self.scoreboard.title("计分板")
        #scoreboard.geometry('800x600')
        self.scoreboard.resizable(False, False)

        self.scoreboard.protocol("WM_DELETE_WINDOW", on_quit_scoreboard)

        tree0 = ttk.Treeview(self.scoreboard)

        tree0["columns"] = ("输入","总分")
        #tree0.column("玩家", width=150)
        tree0.column("输入", width=150)
        tree0.column("总分", width=150)

        #tree0.heading("玩家", text="玩家")
        tree0.heading("输入", text="输入")
        tree0.heading("总分", text="总分")

        #tree0.pack(side='left')

        #vsb0 = ttk.Scrollbar(self.scoreboard, orient="vertical", command=tree0.yview)
        #vsb0.pack(side='right', fill='y')

        #tree0.configure(yscrollcommand=vsb0.set)

        j = 0

        for i in self.p:
            choice_string = str(i.choice_i(self.t))
            score_string = str(i.score) + "(" + str(i.gain_i(self.t)) + ")"
            #tree0.insert("", j, text="", values=(i.showName(), score_string))
            tree0.insert("", j, text=i.showName(), values=(choice_string, score_string))
            j = j + 1

        tree0.pack()

        tree = ttk.Treeview(self.scoreboard, selectmode = 'browse')
        tree.pack(side='left')

        vsb = ttk.Scrollbar(self.scoreboard, orient="vertical", command=tree.yview)
        vsb.pack(side='right', fill='y')

        tree.configure(yscrollcommand=vsb.set)

        for k in range(1, self.t+1):
            myid = tree.insert("", 0, "第" + str(k) + "轮", text = "第" + str(k) + "轮: G值" + str(self.G_list[k-1]), values=("1"))
            for i in self.p:
                tree.insert(myid, 0, "第" + str(k) + "轮" + str(i), text = "玩家 " + i.showName() + " 输入 " + str(i.choice_i(k)) + ",得 " + str(i.gain_i(k)) +" 分", values=("2"))

        tree.pack()

        turns = []
        Gs = []
        turns.append(0)
        Gs.append(0)

        for k in range(1, self.t + 1):
            turns.append(k)
            Gs.append(self.G_list[k-1])

        f = Figure(figsize=(5, 4), dpi=100)
        f_plot = f.add_subplot(111)
        canvs = FigureCanvasTkAgg(f, self.scoreboard)
        canvs.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
        f_plot.clear()
        f_plot.plot(turns, Gs)
        canvs.draw()

        #plt.plot(turns, Gs, linewidth=4)
        #plt.title("G",fontsize=20)
        #plt.xlabel("Turn", fontsize=12)
        #plt.ylabel("G", fontsize=12)
        # 设置坐标轴刻度标记的大小
        #plt.tick_params(axis='both',labelsize=10)
        #plt.show()

        speak_out = win32com.client.Dispatch('SAPI.SPVOICE')
        speak_out.Speak("第" + str(self.t) + "轮: G值" + str(self.G_list[self.t - 1]) + ",获胜玩家为")
        for i in self.p:
            if i.gain_i(self.t) == 2:
                speak_out.Speak(i.showName())

        #self.scoreBoard()

    def input_number(self,entry_list):
        mid = 50 * 0.618
        if len(self.G_list) > 0:
            mid = self.G_list[-1]
        for i in range(self.n):
            if self.p[i].is_human:
                if not entry_list[i].get():
                    return
                self.p[i].newChoice(mid,eval(entry_list[i].get()))
            else:
                self.p[i].newChoice(mid)
        self.cal()
        self.newTurn()
            
    def newTurn(self):
        self.t+=1
        #print("第 "+str(self.t)+" 轮")
        turn_label = Label(self.root,text = "第 "+str(self.t)+" 轮")
        turn_label.grid(row = 0,column = 0,sticky = W)
        self.turnLabel = Label(self.root)
        label_list = []
        entry_list = []
        for i in range(self.n):
            tmp_label = Label(self.root,text = "玩家"+str(i+1)+"的数字")
            tmp_label.grid (row = i+1,column = 0,sticky = W)
            if self.p[i].is_human:
                tmp_entry = Entry(self.root)
                tmp_entry.grid (row = i+1,column = 1,sticky = W)
                tmp_entry.show = "*"
                entry_list.append(tmp_entry)
            else:
                tmp_entry = Label(self.root,text = "AI 已经生成数字")
                tmp_label.grid(row = i+1,column = 1,sticky = W)
                entry_list.append(tmp_entry)
            label_list.append(tmp_label)
                
        tmp_button = Button(self.root,text = "确定",command = lambda:self.input_number(entry_list))
        tmp_button.grid(row = self.n,column = 2,sticky = E)

    
        
        
    def scoreBoard(self):

        st = '第'+str(self.t)+'轮游戏\n裁判公布G值:'+str(self.G_list[-1])+'\n'
        for i in self.p:
            
            st+=i.showName()+":\n"+"输入 "+str(i.choice_i(self.t))+"\t得 "+str(i.gain_i(self.t))+'\t当前得分:'+str(i.score)+'\n'           
        messagebox.showinfo(title="计分板", message=st)
        
print("欢迎进入黄金点游戏!")
#while True:
game = Game()

请我喝杯咖啡

取消

感谢您的支持,我会继续写出更优秀的文章!

扫码支持
扫码支持
请我喝杯咖啡

打开微信扫一扫,即可进行扫码打赏哦

comments powered by Disqus