美文网首页
Python实现黑白棋人机对弈

Python实现黑白棋人机对弈

作者: BroadLy | 来源:发表于2018-12-10 23:22 被阅读0次

    Python实现黑白棋人机对弈

    • 规则

    黑白棋的每颗棋子由黑白两色组成,一面白,一面黑。每次落子,把本方颜色的棋子放在棋盘的空格上,若在横、竖、斜八个方向的任一方向上有本方棋子,则被夹在中间的对手棋子全部翻转为本方棋子颜色;并且,仅在可以翻转棋子的地方才能落子。如果一方至少有一步合法棋步可下,他就必须落子,不得弃权。棋盘已满或双方都没有棋子可下时棋局结束,以棋子数目来计算胜负,棋子多的一方获胜。在棋盘还没有下满时,如果一方的棋子已经被对方吃光,则棋局也结束,将对手棋子吃光的一方获胜。

    两位玩家轮流下棋,直到一方没有符合规则的落子位置,在这种情况下,剩下的一方继续下棋,直到对手有了可以落子的位置。此时,恢复两者轮流下棋的顺序。如果一方落子在非法位置,则视为放弃本次对弈,对方获胜。游戏结束的条件:1)整个棋盘满了;2)一方的棋子已经被对方吃光;3)两名玩家都没有可以落子的棋盘格;4)一方落子在非法位置。前3 种情况以棋子数目来计算胜负,棋子多的一方获胜;第4 种情况判定对方获胜。

    • 计算机选择落子位置的策略

    选择落子位置的策略 选择落子位置的策略对每个可能 的落子 位置,计算 该位置的 该位置的 “分值 ”(可以翻转的对手棋子数量 可以翻转的对手棋子数量 可以翻转的对手棋子数量.同分数选择行数小的。

    • 实现思路

    黑白棋玩家的子的坐标放在集合中,改变集合元素实现下棋。根据集合中元素打印棋盘。

    • 亟待完善的地方

    • 机器下棋策略可以改善,设计递推方法
    • 不同的持棋方式写了重复的代码,可以进一步包装
    • 无效代码可以删除,如cont,
    • 命名
    
    import time
    
    import csv
    
    class HeiBaiPlayer(object):
    
        status = True  # 是否有位置可以下
    
        defeat = False  # 是否赢了
    
        R_LIST = [(i, j) for i in range(-1, 2) for j in range(-1, 2)]
    
        R_LIST.remove((0, 0))
    
        count = 0
    
        def __init__(self, dim, players, _color):  # _color只能是hei or bai ,players只能是com or peop
    
            self.hei = {(dim//2+1, dim//2), (dim//2, dim//2+1)}
    
            self.players = players
    
            self.bai = {(dim//2, dim//2), (dim//2+1, dim//2+1)}
    
            self.dim = dim
    
            self._color = _color  # dic
    
        def qp_print(self):
    
            '''
    
            根据场中的hei和bai打印棋盘
    
            :return:
    
            '''
    
            for i in range(self.dim + 1):
    
                if i == 0:
    
                    print(" ", end='')
    
                    print(''.join([str(chr(97 + x)) for x in range(self.dim)]))
    
                else:
    
                    for j in range(self.dim + 1):
    
                        if j == 0:
    
                            print(chr(96 + i), end='')
    
                        else:
    
                            if (i, j) in self.hei:
    
                                print('X', end='')
    
                            elif (i, j) in self.bai:
    
                                print('O', end='')
    
                            else:
    
                                # print((i,j))
    
                                print('.', end='')
    
                    print()
    
        def legal_position(self,players):
    
            '''
    
            :param players:bai或者hei的集合
    
            :return: 字典 {bai玩家或者hei玩家可以落子位置:反转对手子的位置}
    
            '''
    
            if players == self.hei:
    
                _players = self.bai
    
            else:
    
                _players = self.hei
    
            kong = [(i, j) for i in range(1, self.dim + 1) for j in range(1, self.dim + 1)]
    
            kong = set(kong) - self.hei - self.bai
    
            # print(kong)
    
            p_players_list_in = {}  # 如果落在p,会有的夹在中间的反色子集合
    
            for p in kong:
    
                all_r_players_list_in = []  # 所有方向的反色夹在中间子的集合
    
                for r in self.R_LIST:
    
                    _players_list_in = []  # 某一方向夹在中间反色子的集合
    
                    i = 1
    
                    lst = []
    
                    while 1:
    
                        if (p[0] + i * r[0], p[1] + i * r[1]) in _players:
    
                            lst.append(tuple([p[0] + i * r[0], p[1] + i * r[1]]))
    
                            i += 1
    
                            if (p[0] + i * r[0], p[1] + i * r[1]) in players:
    
                                _players_list_in += lst
    
                                break
    
                            if i > self.dim + 1:
    
                                break
    
                        else:
    
                            break
    
                    if _players_list_in:  # 如果这个方向有jiazai中间的反色子
    
                        all_r_players_list_in += _players_list_in
    
                if all_r_players_list_in:  # 如果落在p,会夹在中间的反色子集合【】
    
                    p_players_list_in[p] = all_r_players_list_in
    
            # print(p_players_list_in,'这是测试')
    
            return p_players_list_in
    
        def callback(self):
    
            '''
    
            根据对象不同选择不同的下棋方式
    
            :return: 机器下棋还是人工下棋
    
            '''
    
            if self.players == 'com':
    
                return self.computer_xia
    
            if self.players == 'peop':
    
                return self.players_xia
    
        def color(self):
    
            if self._color == 'hei':
    
                return self.hei
    
            return self.bai
    
        def hefa(self,players, p):
    
            '''
    
            测试某一位置是否合法,如果合法,返回相应反转的子的位置,不合法返回False
    
            :param p: 位置元组
    
            :return:列表
    
            '''
    
            if p in self.legal_position(players).keys():
    
                return self.legal_position(players)[p]
    
            return False
    
        def defen(self, players, p):
    
            '''
    
            某一位置的得分
    
            :param players:set
    
            :param p:(,)
    
            :return:
    
            '''
    
            return len(self.hefa(players, p))
    
        def computer_xia(self,players):  # 要么是黑,要么是白,players类型是集合
    
            if not self.legal_position(players).keys():
    
                print('com no Invalid move\n========')
    
                self.status = False
    
            else:
    
                self.status = True
    
                p_score = {}
    
                for p in self.legal_position(players).keys():
    
                    p_score[p] = self.defen(players, p)
    
                score = max(p_score.values())
    
                for p in [(i, j) for i in range(1, self.dim + 1) for j in range(1, self.dim + 1)]:
    
                    if self.hefa(players, p):
    
                        if p_score[p] == score:
    
                            return {p: self.legal_position(players)[p]}
    
        def players_xia(self, players):  # 要么是黑,要么是白,players类型是集合
    
            '''
    
            人工下棋,先判断有无位置可以下,在让用户选择落子位置,如果位置出错 self.defeat = True
    
            :param players: 人player拥有子位置的集合
    
            :return: {落子位置:反转对面位置}
    
            '''
    
            if not self.legal_position(players).keys():
    
                print('poeple no Invalid move\n========')
    
                self.status = False
    
            else:
    
                self.status = True
    
                try:
    
                    s = input("你的落子位置(例如ab:a行b列):?")
    
                    posintion = tuple([ord(s[0]) - 96, ord(s[1]) - 96])
    
                    if posintion in self.legal_position(players).keys():
    
                        return {posintion:self.legal_position(players=players)[posintion]}
    
                    else:
    
                        self.defeat = True
    
                except Exception as e:
    
                    print('Sth Wrong, Try again',e)
    
                    s = input("你的落子位置:?")
    
                    posintion = tuple([ord(s[0]) - 96, ord(s[1]) - 96])
    
                    if posintion in self.legal_position(players).keys():
    
                        return {posintion: self.legal_position(players=players)[posintion]}
    
                    else:
    
                        self.defeat = True
    
        def change(self, dic):
    
            '''
    
            下棋之后改变hei和bai中的元素
    
            :param dic: {落子位置:反转对面位置}
    
            :return: 新的hei和bai集合
    
            '''
    
            if self._color == 'hei':
    
                self.hei = self.hei | set(list(dic.keys())) | set(list(dic.values())[0])
    
                self.bai = self.bai - set(list(dic.values())[0])
    
            else:
    
                self.bai = self.bai | set(list(dic.keys())) | set(list(dic.values())[0])
    
                self.hei = self.hei - set(list(dic.values())[0])
    
    def com_turn():
    
        '''
    
        电脑下棋
    
        :return:
    
        '''
    
        com.bai = peop.bai
    
        com.hei = peop.hei
    
        color_set = com.color()  # 颜色集合
    
        HeiBaiPlayer_function = com.callback()  # 下棋方法传入集合
    
        dic = HeiBaiPlayer_function(color_set)  # 得到下棋位置和反转位置
    
        if not com.status:
    
            peop.qp_print()
    
        else:
    
            if peop.status == False:
    
                peop.status = True
    
            com.count = 0
    
            print('==' * 5)
    
            print('机器下棋位置:反转对方位置', dic)
    
            com.change(dic)
    
            # print(com.hei, com.bai)
    
            com.qp_print()
    
            if not peop.status:
    
                peop.status = True
    
    def peop_turn():
    
        '''
    
        人下棋
    
        :return:
    
        '''
    
        peop.bai = com.bai
    
        peop.hei = com.hei
    
        color_set = peop.color()
    
        HeiBaiPlayer_function = peop.callback()  # 下棋的函数
    
        dic = HeiBaiPlayer_function(color_set)
    
        if not peop.status:
    
            peop.qp_print()
    
        elif not peop.defeat:
    
            if com.status == False:
    
                com.status = True
    
            peop.count = 0
    
            print('=='*5)
    
            # print('人的下棋位置:反转对方位置', dic)
    
            peop.change(dic)
    
            # print('黑,白', peop.hei, peop.bai)
    
            peop.qp_print()
    
        else:
    
            peop.qp_print()
    
            peop.defeat = True
    
            # print("人输了")
    
    t1 = time.time()
    
    begin_time = time.strftime('%Y%m%d %H:%M:%S')
    
    Dimension = eval(input('Dimension:'))  # 用户输入开始
    
    OX = input('Computer plays (X/O):')
    
    if OX == 'O':
    
        com = HeiBaiPlayer(dim=Dimension, players='com', _color='bai')
    
        peop = HeiBaiPlayer(dim=Dimension, players='peop', _color='hei')
    
        hei_player = 'computer'
    
    if OX == 'X':
    
        com = HeiBaiPlayer(dim=Dimension, players='com', _color='hei')
    
        peop = HeiBaiPlayer(dim=Dimension, players='peop', _color='bai')
    
        hei_player = 'players'
    
    if com._color == 'hei':
    
        count = 0
    
        peop.qp_print()
    
        while 1:
    
            com_turn()
    
            if peop.status == False and com.status == False:
    
                print("Both players have no valid move.")
    
                print("Game Over")
    
                print('com:{}**peop:{}'.format(com.color(), peop.color()))
    
                if len(com.color()) > len(peop.color()):
    
                    print('com win!!')
    
                elif len(com.color()) < len(peop.color()):
    
                    print('players win!!')
    
                else:
    
                    print('0比0')
    
                score = str(len(com.color())) +':'+ str(len(peop.color()))
    
                break
    
            peop_turn()
    
            if peop.defeat:
    
                print('Invalid move.\nGame over.')
    
                print('com win')
    
                score = 'Human give up'
    
                break
    
            if peop.status == False and com.status == False:
    
                print("Both players have no valid move.")
    
                print("Game Over")
    
                print('com:{}**peop:{}'.format(com.color(), peop.color()))
    
                if len(com.color()) > len(peop.color()):
    
                    print('com win!!')
    
                elif len(com.color()) < len(peop.color()):
    
                    print('players win!!')
    
                else:
    
                    print('0比0')
    
                score = str(len(com.color())) +':'+ str(len(peop.color()))
    
                break
    
        peop.qp_print()
    
    if peop._color == 'hei':
    
        count = 0
    
        peop.qp_print()
    
        while 1:
    
            peop_turn()
    
            if peop.defeat:
    
                print('Invalid move.\nGame over.')
    
                print('com win')
    
                score = 'Human give up'
    
                break
    
            if peop.status == False and com.status == False:
    
                print("Both players have no valid move.")
    
                print("Game Over")
    
                print('com:{}**peop:{}'.format(com.color(), peop.color()))
    
                if len(com.color()) > len(peop.color()):
    
                    print('com win!!')
    
                elif len(com.color()) < len(peop.color()):
    
                    print('players win!!')
    
                else:
    
                    print('0比0')
    
                score = str(len(peop.color())) +':'+ str(len(com.color()))
    
                break
    
            com_turn()
    
            if peop.status == False and com.status == False:
    
                print("Both players have no valid move.")
    
                print("Game Over")
    
                print('com:{}**peop:{}'.format(com.color(), peop.color()))
    
                if len(com.color()) > len(peop.color()):
    
                    print('com win!!')
    
                elif len(com.color()) < len(peop.color()):
    
                    print('players win!!')
    
                else:
    
                    print('0比0')
    
                score = str(len(peop.color())) +':'+ str(len(com.color()))
    
                break
    
        peop.qp_print()
    
    t2 = time.time()
    
    time_sep = int(t2 - t1)
    
    if hei_player == 'computer':
    
    bai_player = 'players'
    
    else:
    
    bai_player = 'computer'
    
    def save_info(begin_time, time_sep, dim, hei_player, bai_player, score):
    
    with open('reversi.csv', 'a', newline='') as f:
    
    writer = csv.writer(f)
    
    writer.writerow([begin_time, time_sep, str(dim)+'*'+str(dim), hei_player, bai_player, score])
    
    save_info(begin_time, time_sep, Dimension, hei_player, bai_player, score)
    
    
    1544455193(1).jpg 1544455180(1).jpg

    相关文章

      网友评论

          本文标题:Python实现黑白棋人机对弈

          本文链接:https://www.haomeiwen.com/subject/orsjhqtx.html