Python實(shí)現(xiàn)黑白棋人機(jī)對(duì)弈

Python實(shí)現(xiàn)黑白棋人機(jī)對(duì)弈

  • 規(guī)則

黑白棋的每顆棋子由黑白兩色組成待错,一面白褐澎,一面黑会钝。每次落子,把本方顏色的棋子放在棋盤(pán)的空格上工三,若在橫迁酸、豎、斜八個(gè)方向的任一方向上有本方棋子俭正,則被夾在中間的對(duì)手棋子全部翻轉(zhuǎn)為本方棋子顏色奸鬓;并且,僅在可以翻轉(zhuǎn)棋子的地方才能落子掸读。如果一方至少有一步合法棋步可下全蝶,他就必須落子,不得棄權(quán)寺枉。棋盤(pán)已滿(mǎn)或雙方都沒(méi)有棋子可下時(shí)棋局結(jié)束抑淫,以棋子數(shù)目來(lái)計(jì)算勝負(fù),棋子多的一方獲勝姥闪。在棋盤(pán)還沒(méi)有下滿(mǎn)時(shí)始苇,如果一方的棋子已經(jīng)被對(duì)方吃光,則棋局也結(jié)束筐喳,將對(duì)手棋子吃光的一方獲勝催式。

兩位玩家輪流下棋,直到一方?jīng)]有符合規(guī)則的落子位置避归,在這種情況下荣月,剩下的一方繼續(xù)下棋,直到對(duì)手有了可以落子的位置梳毙。此時(shí)哺窄,恢復(fù)兩者輪流下棋的順序。如果一方落子在非法位置,則視為放棄本次對(duì)弈萌业,對(duì)方獲勝坷襟。游戲結(jié)束的條件:1)整個(gè)棋盤(pán)滿(mǎn)了;2)一方的棋子已經(jīng)被對(duì)方吃光生年;3)兩名玩家都沒(méi)有可以落子的棋盤(pán)格婴程;4)一方落子在非法位置。前3 種情況以棋子數(shù)目來(lái)計(jì)算勝負(fù)抱婉,棋子多的一方獲勝档叔;第4 種情況判定對(duì)方獲勝。

  • 計(jì)算機(jī)選擇落子位置的策略

選擇落子位置的策略 選擇落子位置的策略對(duì)每個(gè)可能 的落子 位置,計(jì)算 該位置的 該位置的 “分值 ”(可以翻轉(zhuǎn)的對(duì)手棋子數(shù)量 可以翻轉(zhuǎn)的對(duì)手棋子數(shù)量 可以翻轉(zhuǎn)的對(duì)手棋子數(shù)量.同分?jǐn)?shù)選擇行數(shù)小的蒸绩。

  • 實(shí)現(xiàn)思路

黑白棋玩家的子的坐標(biāo)放在集合中衙四,改變集合元素實(shí)現(xiàn)下棋。根據(jù)集合中元素打印棋盤(pán)侵贵。

  • 亟待完善的地方

  • 機(jī)器下棋策略可以改善届搁,設(shè)計(jì)遞推方法
  • 不同的持棋方式寫(xiě)了重復(fù)的代碼缘薛,可以進(jìn)一步包裝
  • 無(wú)效代碼可以刪除窍育,如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):

        '''

        根據(jù)場(chǎng)中的hei和bai打印棋盤(pán)

        :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或者h(yuǎn)ei的集合

        :return: 字典 {bai玩家或者h(yuǎn)ei玩家可以落子位置:反轉(zhuǎn)對(duì)手子的位置}

        '''

        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漱抓,會(huì)有的夾在中間的反色子集合

        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:  # 如果這個(gè)方向有jiazai中間的反色子

                    all_r_players_list_in += _players_list_in

            if all_r_players_list_in:  # 如果落在p,會(huì)夾在中間的反色子集合【】

                p_players_list_in[p] = all_r_players_list_in

        # print(p_players_list_in,'這是測(cè)試')

        return p_players_list_in

    def callback(self):

        '''

        根據(jù)對(duì)象不同選擇不同的下棋方式

        :return: 機(jī)器下棋還是人工下棋

        '''

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

        '''

        測(cè)試某一位置是否合法恕齐,如果合法乞娄,返回相應(yīng)反轉(zhuǎn)的子的位置,不合法返回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類(lèi)型是集合

        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類(lèi)型是集合

        '''

        人工下棋范删,先判斷有無(wú)位置可以下,在讓用戶(hù)選擇落子位置拷肌,如果位置出錯(cuò) self.defeat = True

        :param players: 人player擁有子位置的集合

        :return: {落子位置:反轉(zhuǎn)對(duì)面位置}

        '''

        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: {落子位置:反轉(zhuǎn)對(duì)面位置}

        :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)  # 得到下棋位置和反轉(zhuǎn)位置

    if not com.status:

        peop.qp_print()

    else:

        if peop.status == False:

            peop.status = True

        com.count = 0

        print('==' * 5)

        print('機(jī)器下棋位置:反轉(zhuǎn)對(duì)方位置', 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()  # 下棋的函數(shù)

    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('人的下棋位置:反轉(zhuǎn)對(duì)方位置', 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:'))  # 用戶(hù)輸入開(kāi)始

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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末到旦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子巨缘,更是在濱河造成了極大的恐慌添忘,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件若锁,死亡現(xiàn)場(chǎng)離奇詭異搁骑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)靶病,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)会通,“玉大人,你說(shuō)我怎么就攤上這事娄周√槌蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵煤辨,是天一觀的道長(zhǎng)裳涛。 經(jīng)常有香客問(wèn)我,道長(zhǎng)众辨,這世上最難降的妖魔是什么端三? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮鹃彻,結(jié)果婚禮上郊闯,老公的妹妹穿的比我還像新娘。我一直安慰自己蛛株,他們只是感情好团赁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著谨履,像睡著了一般欢摄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笋粟,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天怀挠,我揣著相機(jī)與錄音,去河邊找鬼害捕。 笑死绿淋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的尝盼。 我是一名探鬼主播吞滞,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼东涡!你這毒婦竟也來(lái)了冯吓?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疮跑,失蹤者是張志新(化名)和其女友劉穎组贺,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體祖娘,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡失尖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年啊奄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掀潮。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡菇夸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仪吧,到底是詐尸還是另有隱情庄新,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布薯鼠,位于F島的核電站择诈,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏出皇。R本人自食惡果不足惜羞芍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望郊艘。 院中可真熱鬧荷科,春花似錦、人聲如沸纱注。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)奈附。三九已至全度,卻和暖如春煮剧,著一層夾襖步出監(jiān)牢的瞬間斥滤,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工勉盅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留佑颇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓草娜,卻偏偏與公主長(zhǎng)得像挑胸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宰闰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 磨劍記(8) 8茬贵,飄海 裊裊要真武在她生日正日去她家。真武對(duì)她有一種說(shuō)不出的喜愛(ài)移袍,高高纖細(xì)的身段解藻,如花的面容,天真...
    火若一筆閱讀 213評(píng)論 0 0
  • 轉(zhuǎn)眼間葡盗,牛雪莉的年齡已進(jìn)入了而立之年螟左,皮氣、個(gè)性、思想都有了質(zhì)的變化胶背。確切的說(shuō)巷嚣,處事為人,看問(wèn)題比以前大有長(zhǎng)...
    閆忠錄閱讀 558評(píng)論 0 1
  • 在我們成長(zhǎng)的過(guò)程中评雌,一直被教育,不能辜負(fù)別人的期望直焙。 不辜負(fù)父母景东、不辜負(fù)朋友、不辜負(fù)老師奔誓、不辜負(fù)另一半斤吐。甚至不去在...
    耳邊漫時(shí)光閱讀 1,282評(píng)論 0 0
  • 1. “小蘇老師。 還是習(xí)慣這樣稱(chēng)呼你厨喂,當(dāng)年大家都這樣叫你和措,用以區(qū)分你和另一個(gè)蘇老師。 你還好嗎蜕煌? 我回了學(xué)校派阱,即...
    許清和閱讀 1,574評(píng)論 10 20
  • 一、string字符串 1.常用功能 1.1獲取長(zhǎng)度和次數(shù) 代碼演示:#1.計(jì)算字符串長(zhǎng)度 len#類(lèi)似于lis...
    hollow_02f9閱讀 570評(píng)論 0 1