黄金点游戏v1.1

    2020年11月16日 字数:3636

黄金点游戏 在上次课程设计作业的基础上(C++完成),我们发现C++较难实现可视化,并且不利于后续迭代,因此我们利用python重构了整份代码。

当设定的玩家名为“AI”时,我们实现了一个简单的AI;上次课程设计作业中,我们令AI随机生成0~100中的一个浮点数,但这样AI的决策和之前各玩家的报数和G值(各玩家报数的平均值*0.618)完全无关。

在参考了MSRA的获奖算法后,我们让AI先在0~上轮的G值(如果是第一轮游戏,则为(100+0)/2 * 0.618)中随机一个浮点数,然后AI有较小的概率将自己的报数再增加一次,增量为0~上轮的G值(如果是第一轮游戏,则为(100+0)/2 * 0.618)中随机的浮点数乘以一个系数(暂时为0.1),通过函数mIn()保证不大于等于100。这参考MSRA的获奖算法中,逐渐降低平均值(随着游戏轮数增加的一般情况)+随机化(以应对某个玩家突然报大数的突发状况)的思路。

现在与AI的游戏已经有一定的决策深度,但我们发现了新的问题:玩家数n>2时,玩家可以通过故意报出大数提高上轮的G值(大概率-2分),然后再报小数并取得当轮的胜利(大概率+n分),这样每两轮玩家的分数有很大概率会提升至少一次。在算法方面仍然有进一步提升的空间,后续可能会以模仿棋的思路,令AI去学习玩家的报数策略,让AI更有竞争力。

功能描述

Player类:维护与单一玩家相关的信息。

init():初始化。

SetPlayerName():设置该玩家为拥有指定姓名的人类玩家。

newChoice():设置该玩家当前轮的报数。

win():设置该玩家当前轮赢(+n分,n为玩家数)。

draw():设置该玩家当前轮平(计0分)。

lose():设置该玩家当前轮负(-2分)。

showName():返回该玩家的姓名。

choice_i():返回该玩家第i轮的报数。

gain_i():返回该玩家第i轮的得分。

Game类:维护与当前对局相关的信息。

Start():开始一局全新的游戏。

init():初始化。

addPlayer():增加一个新玩家。

cal():计算当前轮的G值,并维护每个对局中玩家在当前轮的胜平负。

input_number():如果非AI玩家当前轮均已报数,则维护当前轮的对局。

newTurn():显示得分表与当前轮结果,并开始新的一轮。

scoreBoard():显示计分板。

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)
        
        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()
        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