最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python實現(xiàn)五子棋人機對戰(zhàn)游戲

 更新時間:2020年03月25日 15:49:24   作者:丹楓無跡  
這篇文章主要為大家詳細(xì)介紹了python實現(xiàn)五子棋之人機對戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文代碼基于 python3.6 和 pygame1.9.4。

五子棋比起我之前寫的幾款游戲來說,難度提高了不少。如果是人與人對戰(zhàn),那么,電腦只需要判斷是否贏了就可以。如果是人機對戰(zhàn),那你還得讓電腦知道怎么下。

我們先從簡單的問題來看。

開端

畫棋盤

首先肯定是要畫出棋盤來,用 pygame 畫出一個 19 × 19 或 15 × 15 的棋盤并不是什么難事,這在之前的文章中已經(jīng)多次用到,就不贅述了。

畫棋子

需要說一下的是畫棋子,因為沒找到什么合適的棋子圖片,所以只要自己來畫棋子。
我們用 pygame.draw.circle 畫出來的圓形是這樣的:

鋸齒狀十分明顯,pygame.draw 中有畫抗鋸齒直線的函數(shù) aaline,但是并沒有 aacircle 這樣的函數(shù)來畫一個抗鋸齒的圓。

這里就需要用到 pygame.gfxdraw 啦。pygame.gfxdraw 目前還僅是實驗版本,這意味著這個 API  可能會在以后的 pygame 版本中發(fā)生變化或消失。

要繪制抗鋸齒和填充形狀,請首先使用函數(shù)的aa *版本,然后使用填充版本。例如:

col = (255, 0, 0)
surf.fill((255, 255, 255))
pygame.gfxdraw.aacircle(surf, x, y, 30, col)
pygame.gfxdraw.filled_circle(surf, x, y, 30, col)

我們用這個方法在棋盤上畫一個棋子試試看。

可以看到效果已明顯改善。

落子

落子需要判斷鼠標(biāo)事件,當(dāng)鼠標(biāo)左鍵點擊,獲取鼠標(biāo)點擊的位置,然后根據(jù)棋盤的位置,計算出棋子落在棋盤的位置。

while True:
 for event in pygame.event.get():
 if event.type == QUIT:
 sys.exit()
 elif event.type == MOUSEBUTTONDOWN:
 pressed_array = pygame.mouse.get_pressed()
 if pressed_array[0]: # 鼠標(biāo)左鍵點擊
  mouse_pos = pygame.mouse.get_pos()
  click_point = _get_clickpoint(mouse_pos)

勝利判定

當(dāng)一子落下,如何判定是否勝利?

可以肯定的是,當(dāng)某一子落下的時候,如果出現(xiàn)了 5 連,那么落下的這顆子必定在這條 5 連線上。那么這個問題就可以簡化了,我們無需全盤掃描,只需要在落子位置上橫豎撇捺掃描一下,判斷是否出現(xiàn) 5 連即可。

我們定義一個棋盤類,類中實例化一個 19 × 19 的二維數(shù)組,初始值皆為 0,表示空,用 1 表示黑子,2 表示白子。這個類對外提供一個落子方法 drop,接收參數(shù)落子方和落子坐標(biāo),如果落子后勝利,則返回勝利者,否則返回 None。

Chessman = namedtuple('Chessman', 'Name Value Color')
Point = namedtuple('Point', 'X Y')
 
BLACK_CHESSMAN = Chessman('黑子', 1, (45, 45, 45))
WHITE_CHESSMAN = Chessman('白子', 2, (219, 219, 219))
 
offset = [(1, 0), (0, 1), (1, 1), (1, -1)]
 
 
class Checkerboard:
 def __init__(self, line_points):
 self._line_points = line_points
 self._checkerboard = [[0] * line_points for _ in range(line_points)]
 
 def _get_checkerboard(self):
 return self._checkerboard
 
 checkerboard = property(_get_checkerboard)
 
 # 判斷是否可落子
 def can_drop(self, point):
 return self._checkerboard[point.Y][point.X] == 0
 
 def drop(self, chessman, point):
 """
 落子
 :param chessman: 黑子/白子
 :param point:落子位置
 :return:若該子落下之后即可獲勝,則返回獲勝方,否則返回 None
 """
 print(f'{chessman.Name} ({point.X}, {point.Y})')
 self._checkerboard[point.Y][point.X] = chessman.Value
 
 if self._win(point):
 print(f'{chessman.Name}獲勝')
 return chessman
 
 # 判斷是否贏了
 def _win(self, point):
 cur_value = self._checkerboard[point.Y][point.X]
 for os in offset:
 if self._get_count_on_direction(point, cur_value, os[0], os[1]):
 return True
 
 def _get_count_on_direction(self, point, value, x_offset, y_offset):
 count = 1
 for step in range(1, 5):
 x = point.X + step * x_offset
 y = point.Y + step * y_offset
 if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:
 count += 1
 else:
 break
 for step in range(1, 5):
 x = point.X - step * x_offset
 y = point.Y - step * y_offset
 if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:
 count += 1
 else:
 break
 
 return count >= 5

這里我定義了一個偏移量,我們一共要計算橫豎撇捺 4 條線,任意一條線出現(xiàn) 5 連就算獲勝。計算方法實際上是一樣的,只是方向不同,所以定義一個偏移量數(shù)組,不同的偏移量表示不同的方向,這樣就可以利用循環(huán)來實現(xiàn)了,節(jié)省了很多代碼。

電腦落子

這就是全篇的重頭戲了,要怎么教電腦下五子棋。
首先聲明,我用的是相對傳統(tǒng)的方式,不是深度學(xué)習(xí)。

五子棋就是要實現(xiàn) 5 連,所以,一開始,我的想法是:將所有連線保存在一個數(shù)組中,落子的時候選擇最長的連線落子。但這樣有個問題解決不掉,如何讓電腦識別“三三”呢?

后來網(wǎng)上看到篇文章,使用的方法是:遍歷棋盤上的空位,計算每一個位置其橫豎撇捺 8 個方向上是否有己方的子,有一個就加 10 分,最后選得分最高的位置落子。

這樣不太嚴(yán)謹(jǐn),寫出來的電腦估計水平很菜,但是這個思路卻是對的,落子就是要找到最值得的地方,那么我們干脆對每一個可落子的地方來做一個評估,選出最優(yōu)解。

這里我們需要了解一下五子棋的幾種基本棋形:連五,活四,沖四,活三,眠三,活二,眠二。

連五

顧名思義,五顆同色棋子連在一起,贏了。

活四

四顆同色棋子連在一起,并且左右兩邊都沒有對方棋子阻擋,有兩個連五點。

沖四

四顆同色棋子連在一起,并且一邊有對方棋子阻擋,或者四顆棋子不是連的,當(dāng)中有個空擋,這時只有一個連五點。

活三、跳活三

活三:三顆同色棋子連在一起。

跳活三:中間隔了一個空格的活三。

眠三

只能夠形成沖四的三,無外乎兩種情況,一是一邊被擋住了,一是當(dāng)中有 2 個空格。(其實我在代碼中僅考慮了第一種情況,即便形成沖四,也不是什么危險局面。)

活二和眠二

活二,能夠形成活三的二;眠二,能夠形成眠三的二。這里就不放圖了,參考活三眠三。

打分機制

理解了這些棋形,那么按我們之前的思路,就是如何打分了。

  • 首先,連五肯定是不存在的,出現(xiàn)連五勝負(fù)已分,所以只要棋局還在進(jìn)行中,就不會出現(xiàn)連五。那么,什么優(yōu)先級最高?自然就是活四了。
  • 其次是對方的“四”,對方活四,你防不防都一樣輸了,對方?jīng)_四,你就必須防守。
  • 再次是我方的活三或沖四,活三跟沖四其實是一個級別的,對方必須防守。
  • 再次是對方的活三或沖四。

以此類推下去。我們可以總結(jié)一點規(guī)律:

  • 相同的棋形,我方優(yōu)于對方。
  • 沖四跟活三一個級別,眠三跟活二一個級別。
  • 如果中間有空格的話,肯定是要比沒空格的略微低級一點,但不至于降級。

基本邏輯就是這樣,這一塊的代碼我寫得也不好,整個判斷寫了100多行,就不貼代碼了,大家可以直接下源碼看。

五子棋執(zhí)黑是必贏的,代碼中,玩家就是執(zhí)黑先手,電腦執(zhí)白后手,所以,下的好是完全可以贏電腦的,不過一個小小失誤也很可能被電腦翻盤。

更多關(guān)于python游戲的精彩文章請點擊查看以下專題:

python俄羅斯方塊游戲集合

python經(jīng)典小游戲匯總

python微信跳一跳游戲集合

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • python安裝包出現(xiàn)Retrying?(Retry(total=4,?connect=None,?read=None,?redirect=None,?status=None))問題解決

    python安裝包出現(xiàn)Retrying?(Retry(total=4,?connect=None,?read=No

    這篇文章主要給大家介紹了關(guān)于python安裝包出現(xiàn)Retrying?(Retry(total=4,?connect=None,?read=None,?redirect=None,?status=None))問題的解決方法,需要的朋友可以參考下
    2022-09-09
  • Python的Flask框架中使用Flask-Migrate擴展遷移數(shù)據(jù)庫的教程

    Python的Flask框架中使用Flask-Migrate擴展遷移數(shù)據(jù)庫的教程

    Flask-Migrate可以幫助Flask應(yīng)用程序通過預(yù)設(shè)的Python腳本完成數(shù)據(jù)庫遷移操作,這里我們就來看一下Python的Flask框架中使用Flask-Migrate擴展遷移數(shù)據(jù)庫的教程,需要的朋友可以參考下
    2016-06-06
  • Python 爬取網(wǎng)頁圖片詳解流程

    Python 爬取網(wǎng)頁圖片詳解流程

    沒想到python是如此強大,令人著迷,以前看見圖片總是一張一張復(fù)制粘貼,現(xiàn)在好了,學(xué)會python就可以用程序?qū)⒁粡垙垐D片,保存下來。今天網(wǎng)上沖浪看到很多美圖,可是圖片有點多,不想一張一張地復(fù)制粘貼,怎么辦呢?辦法總是有的,即便沒有我們也可以創(chuàng)造一個辦法
    2021-11-11
  • Python3內(nèi)置模塊之base64編解碼方法詳解

    Python3內(nèi)置模塊之base64編解碼方法詳解

    這篇文章主要介紹了Python3內(nèi)置模塊之base64編解碼方法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • win與linux系統(tǒng)中python requests 安裝

    win與linux系統(tǒng)中python requests 安裝

    requests是Python的一個HTTP客戶端庫,跟urllib,urllib2類似,今天我們主要來談?wù)剋in與linux系統(tǒng)中python requests的安裝方法以及使用指南
    2016-12-12
  • python GUI庫圖形界面開發(fā)之PyQt5信號與槽的高級使用技巧(自定義信號與槽)詳解與實例

    python GUI庫圖形界面開發(fā)之PyQt5信號與槽的高級使用技巧(自定義信號與槽)詳解與實例

    這篇文章主要介紹了python GUI庫圖形界面開發(fā)之PyQt5信號與槽的高級知識(自定義信號與槽)詳解與實例,需要的朋友可以參考下
    2020-03-03
  • PyTorch安裝與基本使用詳解

    PyTorch安裝與基本使用詳解

    這篇文章主要介紹了PyTorch安裝與基本使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Python中g(shù)etservbyport和getservbyname函數(shù)的用法大全

    Python中g(shù)etservbyport和getservbyname函數(shù)的用法大全

    在Python的網(wǎng)絡(luò)編程中,getservbyport()函數(shù)和getservbyname()函數(shù)是socket模塊中的兩個函數(shù),因此在使用這兩個函數(shù)時,需要導(dǎo)入socket模塊,這篇文章主要介紹了Python中g(shù)etservbyport和getservbyname函數(shù)的用法,需要的朋友可以參考下
    2023-01-01
  • python argparse模塊通過后臺傳遞參數(shù)實例

    python argparse模塊通過后臺傳遞參數(shù)實例

    這篇文章主要介紹了python argparse模塊通過后臺傳遞參數(shù)實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Python中time.sleep(0.001)是否真的只等待1毫秒

    Python中time.sleep(0.001)是否真的只等待1毫秒

    這篇文章主要介紹了Python中time.sleep(0.001)是否真的只等待1毫秒,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06

最新評論

繁昌县| 霍山县| 辛集市| 高要市| 普安县| 监利县| 丹东市| 微博| 曲周县| 讷河市| 定边县| 哈密市| 福清市| 射洪县| 习水县| 舞钢市| 寻乌县| 习水县| 福清市| 定西市| 萨迦县| 吴旗县| 始兴县| 灵山县| 金堂县| 沧州市| 宽城| 广州市| 通州市| 德令哈市| 巴马| 顺昌县| 界首市| 鲁甸县| 丁青县| 旌德县| 定远县| 无极县| 宁城县| 分宜县| 万荣县|