当前位置: 首页 > news >正文

让电脑变得更聪明——用python实现五子棋游戏

作为经典的棋类游戏,五子棋深受大众喜爱,但如果仅实现人与人的博弈,那程序很简单,如果要实现人机对战,教会计算机如何战胜人类,那就不是十分容易的事了。本文我们先从简单入手,完成五子棋游戏的基本操作,然后再尝试引入一些实现人工智能的编程方法和技巧,从而实现人机博弈。

1.创建棋盘和棋子

对于棋类游戏来说,游戏的场景就是下棋的棋盘,而游戏的主要角色就是棋子。接下来我们开始创建棋盘和棋子。

1.1绘制棋盘

五子棋的棋盘可以看成是一个1818的网格,他由19条竖线和19条横线(包含边界)构成,直线的交叉处就下棋子的位置。这里,我们用1818个棕色格子来填满棋盘,每个格子的间距就是棋盘的纵横交错的线条,python可以实现该功能的库有pgzero、tkinter。这里我们用pygame

# 创建窗口,背景为棕色screen = pygame.display.set_mode((615, 615))pygame.display.set_caption('五子棋')screen.fill("#DD954F")
#创建外边框a = pygame.Surface((603, 603), flags=pygame.HWSURFACE)a.fill(color='#121010')b = pygame.Surface((585, 585), flags=pygame.HWSURFACE)b.fill(color="#DD954F")c = pygame.Surface((579, 579), flags=pygame.HWSURFACE)c.fill(color='#121010')## d = pygame.Surface((576, 576), flags=pygame.HWSURFACE)# d.fill(color="#DD954F")#棋盘格子e = pygame.Surface((31, 31), flags=pygame.HWSURFACE)e.fill(color="#DD954F")screen.blit(a, (6.5, 6.5))screen.blit(b, (15, 15))screen.blit(c, (18, 18))for j in range(18):for i in range(18):#起点是20,间隔是32,每个格子大小31,所以格子间距1screen.blit(e, (20 + 32 * i, 20 + 32 * j))#存储棋盘状态alist  = np.zeros((19, 19))#星位pygame.draw.circle(screen, '#121010', [307.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 115.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 115.5], 5)pygame.draw.circle(screen, '#121010', [307.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [307.5, 115.5], 5)
#刷新窗口pygame.display.flip()

1.2创建棋子

本来打算直接上图片,后来参考了别的博主的做法,其实可以通过多个半径颜色不同的同心圆叠加来绘制圆滑的棋子

    def black(x, y):a = 20b =20c =20d = 0.01#循环50次,每次绘制50个半径颜色不同的同心圆for i in range(50):pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16/(d-5)+16))a += 1b += 1c += 1d += 0.08pygame.display.update()def white(x, y):a = 170b = 170c = 170d = 0.02for i in range(50):pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y],(16/(d-5)+16))a += 1b += 1c += 1d += 0.08pygame.display.update()

在这里插入图片描述

2.完成走棋操作

棋盘和棋子都准备好了,下面来实现下棋的功能,看看如何把棋子摆放在棋盘上。

五子棋的规则如下

1.对局双方各执一色棋子。 空棋盘开局。 黑先、白后,交替下子,每次只能下一子。
2.棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
3.五颗连续的同色棋子先连城一条线的那方赢。

人可以通过眼睛来判断那个位置能下棋和何时输赢,那计算机怎么判断这些呢。计算不像人那样有聪明的大脑,想要让计算机能做出这些判断,就必须把这些操作转换成计算机能理解的数据。

怎么让计算机知道棋盘的情况呢?我们用一个二维数组来模拟棋盘,棋盘上每个位置都有三种状态(无子、黑子、白子)那我们就用(0、1、2)来表示这三种情况。用wb来表示当前棋子,如果该位置为0则,更新该位置的值和wb的值,然后调用对用绘画函数来更新窗口

    #存储棋盘状态alist  = np.zeros((19, 19))if event.type == pygame.MOUSEBUTTONDOWN:x, y = pygame.mouse.get_pos()# 棋盘边界线的中点是19.5, 通过计算得到当前坐标在棋盘的行号和列号(x,y)x = round((x - 19.5) / 32)y = round((y - 19.5) / 32)if x < 0:x = 0if x > 18:x = 18if y < 0:y = 0if y > 18:y = 18z = Falseif alist[x][y] == 0:#这步相当于black(x,y)或者是white(x,y)取决于wbeval(wb + "({},{})".format(x, y))

3.判断输赢

怎么判断赢了没?我们通过鼠标左机屏幕来下棋子,pygame也给我们提供了获取鼠标坐标的函数,每次鼠标点击后就进行check()操做
分别检查四个方向上是否有连子的情况,先找到该方向的第一个棋子然后向后统计同色数量,判断输赢。


def check(x,y):xx = xyy = ywhile True:#从最上边的棋子开始检查,记录颜色相同得棋子数量#先找到最同一条线上最上边的同色棋子if xx == 0:breakelif alist[xx][yy] != alist[x][y]:xx += 1breakelse:xx -= 1num = 0while True:if xx == 18:breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1num += 1if num >= 5:win(wb1)# 从最边的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上最左边的同色棋子xx = xyy = ywhile True:if yy == 0:breakelif alist[xx][yy] != alist[x][y]:yy += 1breakelse:yy -= 1num = 0while True:if yy == 18:breakelif alist[xx][yy] != alist[x][y]:breakelse:yy += 1num += 1if num >= 5:win(wb1)# 从左上方的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上左上方的同色棋子xx = xyy = ywhile True:if xx == 0:breakelif yy == 0:breakelif alist[xx][yy] != alist[x][y]:xx += 1yy += 1breakelse:xx -= 1yy -= 1num = 0while True:if xx == 18:breakelif yy == 18:breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1yy += 1num += 1if num >= 5:win(wb1)# 从右上方的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上右上方的同色棋子xx = xyy = ywhile True:if xx == 0:breakelif yy == 18:breakelif alist[xx][yy] != alist[x][y]:xx += 1yy -= 1breakelse:xx -= 1yy += 1num = 0while True:if xx == 18:breakelif yy == 0:breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1yy -= 1num += 1if num >= 5:pygame.font.init()win(wb1)def win(wb1):font = pygame.font.Font(None, 36)text = font.render("{}赢了".format(wb1), True, (255, 255, 255))screen.blit(text, ((665 - text.get_width()) / 2, (665 - text.get_height()) / 2))pygame.display.update()while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:do()

完成了这些步骤后,五子棋的基本规则已经实现,敲了几十行代码,终于能得到点反馈了。
下面是初级版的完整代码


import random
import sys
import pygameimport numpy as npdef init():pygame.init()# 创建窗口,背景为棕色global screenscreen = pygame.display.set_mode((615, 615))pygame.display.set_caption('五子棋')screen.fill("#DD954F")# 创建外边框a = pygame.Surface((603, 603), flags=pygame.HWSURFACE)a.fill(color='#121010')b = pygame.Surface((585, 585), flags=pygame.HWSURFACE)b.fill(color="#DD954F")c = pygame.Surface((579, 579), flags=pygame.HWSURFACE)c.fill(color='#121010')e = pygame.Surface((31, 31), flags=pygame.HWSURFACE)e.fill(color="#DD954F")screen.blit(a, (6.5, 6.5))screen.blit(b, (15, 15))screen.blit(c, (18, 18))# 棋盘格子for j in range(18):for i in range(18):# 起点是20,间隔是32,每个格子大小31,所以格子间距1screen.blit(e, (20 + 32 * i, 20 + 32 * j))# 存储棋盘状态global alistalist = np.zeros((19, 19))# 星位pygame.draw.circle(screen, '#121010', [307.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 115.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 115.5], 5)pygame.draw.circle(screen, '#121010', [307.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [307.5, 115.5], 5)# 刷新窗口pygame.display.flip()# 绘制棋子
def black(x, y):a = 20b = 20c = 20d = 0.01# 循环50次,每次绘制50个半径颜色不同的同心圆for i in range(50):pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))a += 1b += 1c += 1d += 0.08pygame.display.update()def white(x, y):a = 170b = 170c = 170d = 0.02for i in range(50):pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))a += 1b += 1c += 1d += 0.08pygame.display.update()pygame.font.init()
font1 = pygame.font.Font(None, 250)# 主要操作
def do(wb):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:x, y = pygame.mouse.get_pos()# 棋盘边界线的中点是19.5, 通过计算得到当前坐标在棋盘的行号和列号(x,y)x = round((x - 19.5) / 32)y = round((y - 19.5) / 32)if x < 0:x = 0if x > 18:x = 18if y < 0:y = 0if y > 18:y = 18if alist[x][y] == 0:eval(wb + "({},{})".format(x, y))if wb == "black":alist[x][y] = 1wb1 = "black"wb = "white"elif wb == "white":alist[x][y] = 2wb1 = "white"wb = "black"check(x, y, wb1)
def check(x, y, wb1):xx = xyy = ywhile True:# 从最上边的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上最上边的同色棋子if xx == 0:breakelif alist[xx][yy] != alist[x][y]:xx += 1breakelse:xx -= 1num = 0while True:if xx == 18:breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1num += 1if num >= 5:win(wb1)# 从最边的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上最左边的同色棋子xx = xyy = ywhile True:if yy == 0:breakelif alist[xx][yy] != alist[x][y]:yy += 1breakelse:yy -= 1num = 0while True:if yy == 18:breakelif alist[xx][yy] != alist[x][y]:breakelse:yy += 1num += 1if num >= 5:win(wb1)# 从左上方的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上左上方的同色棋子xx = xyy = ywhile True:if xx == 0:breakelif yy == 0:breakelif alist[xx][yy] != alist[x][y]:xx += 1yy += 1breakelse:xx -= 1yy -= 1num = 0while True:if xx == 18:breakelif yy == 18:breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1yy += 1num += 1if num >= 5:win(wb1)# 从右上方的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上右上方的同色棋子xx = xyy = ywhile True:if xx == 0:breakelif yy == 18:breakelif alist[xx][yy] != alist[x][y]:xx += 1yy -= 1breakelse:xx -= 1yy += 1num = 0while True:if xx == 18:breakelif yy == 0:breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1yy -= 1num += 1if num >= 5:pygame.font.init()win(wb1)def win(wb1):pygame.font.init()font = pygame.font.Font(None, 70)text = font.render(f"{wb1}  won", True, (255, 255, 255))screen.blit(text, ((655 - text.get_width()) / 2, (665 - text.get_height()) / 2))pygame.display.update()pygame.display.flip()while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:init()do("black")if __name__ == "__main__":init()do('black')

4.实现人机对弈

现在五子棋的基本公能已经实现了,但这种充满策略与博弈的棋类游戏,猜测并应对对手可能的布局,相互之间进行激烈的智力对决才是游戏最好玩的部分,一个人玩也太无聊了,要是电脑能像人一样可以思考该多好呀,就像近几年的特别火的“阿尔法狗”一样,我很期待被自己的程序打败。那么怎样实现人机对弈呢?

随着人工智能的快速发展,其在许多领域都得到了广泛应用,其中就包括游戏人工智能。游戏人工智能分为两大类,
一类叫做确定性人工智能,另一类叫做非确定性人工智能。
确定性人工智能,是指电脑按照确定的规则进行判断和抉择。非确定性人工智能是指电脑根据已有的规则来学习新的规则,例如神经网络、遗传算法、决策树和概率方法等。
因为五子棋的规则是确定的,所以我们只用让电脑记住规则,并按照规则来决策和判断。在棋类游戏中,如果把棋子的每一种布局都当作是一种状态,那对局中所有的可能局面的集合被称为状态空间,状态空间搜素就是根据某种规则,在所有的局面中找到最有利的局面,并以此来决定下一步走法。由于五子棋的规则简单,不同状态的最优解比较少,不必采用耗费空间的状态空间搜素法,只用让电脑记住所有的最优解即可。

4.1列举最优解

回想一下自己下棋的思考过程,决策和判断的依据无非就那几种,进过权衡后选择最有利的走法。模仿人的思考过程,我们可以告诉电脑所有的走法,然后将这些走法按等级排序,电脑每次决策的时候就在这些走法集合中按照等级由高到低的顺序依次搜素,没有找到最优解则随机下子。

为了让电脑能识别走法,首先要对棋局的各种走法进行描述和储存,这里我们用一个cdata列表实现,0表示空棋、1表示黑棋、 2表示白棋、3表示将要下棋的位置。


# 0表示空棋
# 1表示黑棋
# 2表示白棋
# 3表示下棋的位置cdata = [# 一颗棋子的情况[1, 3, 0, 0, 0], [0, 1, 3, 0, 0], [0, 0, 1, 3, 0], [0, 0, 0, 1, 3], [0, 0, 0, 3, 1],[2, 3, 0, 0, 0], [0, 2, 3, 0, 0], [0, 0, 2, 3, 0], [0, 0, 0, 2, 3], [0, 0, 0, 3, 2],# 二颗棋子的情况[0, 1, 3, 1, 0], [1, 1, 3, 0, 0], [0, 0, 3, 1, 1],[2, 2, 3, 0, 0], [0, 0, 3, 2, 2], [0, 2, 3, 2, 0],# 三颗棋子的情况[1, 1, 1, 3, 0], [0, 3, 1, 1, 1], [1, 1, 3, 1, 0], [1, 3, 1, 1, 0],[2, 2, 0, 3, 2], [2, 3, 0, 2, 2], [0, 3, 2, 2, 2], [2, 2, 3, 2, 0],[2, 3, 2, 2, 0], [0, 2, 3, 2, 2], [0, 2, 2, 3, 2], [2, 2, 2, 3, 0], [3, 2, 2, 2, 0],# 四颗棋子情况[1, 1, 1, 1, 3], [3, 1, 1, 1, 1], [1, 1, 1, 3, 1], [1, 3, 1, 1, 1], [1, 1, 3, 1, 1],[2, 2, 2, 2, 3], [3, 2, 2, 2, 2], [2, 2, 3, 2, 2], [2, 3, 2, 2, 2], [2, 2, 2, 3, 2]
]

4.2匹配最优解

现在电脑已经掌握各种走法了,决胜秘籍在手,电脑改怎么用呢?接下来我们定义三个全局变量,用来辅助匹配算法的执行。 用ai_col 下棋位置列号, ai_row下棋位置行号,max_level走法等级

  global ai_col, ai_row, max_levelai_col = -1ai_row = -1max_level = -1

接着我们来定义auto_match()函数

def auto_mach(row, col, level, dx, dy):global ai_col, ai_row, max_levelcol_sel = -1  # 暂存棋子列号row_sel = -1  # 暂存棋子行号isfind = True  # 匹配成功的标记for j in range(5):cs = alist[row + j * dx][col + j * dy]if cs == 0:if cdata[level][j] == 3:row_sel = row + j * dxcol_sel = col + j * dyelif cdata[level][j] == 1:isfind = Falsebreakelif cdata[level][j] == 2:isfind = Falsebreakelif cs != cdata[level][j]:isfind = Falsebreakif isfind:ai_row = row_selai_col = col_selmax_level = levelreturn Truereturn False

函数需要4个参数row和col是棋子的位置,level是走法等级,dx,dy是下一步方向,用row_sel,col_sel来存储匹配过程中棋子的位值,棋子按照dx,dy的方向一次往后匹配,
如果棋盘布局和走法列表匹配成功则发挥True,反正返回False。

4.3自主操作

完成了匹配操作后,电脑就有了判断的能力了,接下来我们来实现电脑的自主操作。下面定义ai_play()


def ai_play():global ai_col, ai_row, max_levelai_col = -1ai_row = -1max_level = -1# 搜素棋盘每个位置for i in range(19):for j in range(19):# 从高到低搜索for level in range(len(cdata) - 1, -1, -1):if level > max_level:if i + 4 < 19:if auto_mach(i, j, level, 1, 0):breakif j + 4 < 19:if auto_mach(i, j, level, 0, 1):breakif i + 4 < 19 and j + 4 < 19:if auto_mach(i, j, level, 1, 1):breakif i + 4 < 19 and j - 4 > 0:if auto_mach(i, j, level, 1, -1):breakif ai_row!=-1 and ai_row!=-1:alist[ai_row][ai_col]=2return Truewhile True:col = random.randint(0,18)row = random.randint(0, 18)if alist[row][col]==0:alist[row][col]=2ai_row=rowai_col=colreturn Truereturn False

该函数首先将全局变量max_level,ai_row,ai_col重置为-1,清除上次结果的影响,然后从棋盘第一个位置开始匹配,max_level记录最高等级,凡是等级比其低的走法直接不考虑,这样能减少不必要的操作,加快程序运行速率,匹配结束后,若找到最优解了就更新ai_row,ai_col,没找到就随机选一个符合要求的位置。

完整代码

至此程序全部编写完成,现在运行游戏玩一下,看看你和计算机谁更厉害,如果被打败了这就是你肝了半天的代码最好的反馈。


import random
import sys
import pygameimport numpy as np# 0表示空棋
# 1表示黑棋
# 2表示白棋
# 3表示下棋的位置cdata = [# 一颗棋子的情况[1, 3, 0, 0, 0], [0, 1, 3, 0, 0], [0, 0, 1, 3, 0], [0, 0, 0, 1, 3], [0, 0, 0, 3, 1],[2, 3, 0, 0, 0], [0, 2, 3, 0, 0], [0, 0, 2, 3, 0], [0, 0, 0, 2, 3], [0, 0, 0, 3, 2],# 二颗棋子的情况[0, 1, 3, 1, 0], [1, 1, 3, 0, 0], [0, 0, 3, 1, 1],[2, 2, 3, 0, 0], [0, 0, 3, 2, 2], [0, 2, 3, 2, 0],# 三颗棋子的情况[1, 1, 1, 3, 0], [0, 3, 1, 1, 1], [1, 1, 3, 1, 0], [1, 3, 1, 1, 0],[2, 2, 0, 3, 2], [2, 3, 0, 2, 2], [0, 3, 2, 2, 2], [2, 2, 3, 2, 0],[2, 3, 2, 2, 0], [0, 2, 3, 2, 2], [0, 2, 2, 3, 2], [2, 2, 2, 3, 0], [3, 2, 2, 2, 0],# 四颗棋子情况[1, 1, 1, 1, 3], [3, 1, 1, 1, 1], [1, 1, 1, 3, 1], [1, 3, 1, 1, 1], [1, 1, 3, 1, 1],[2, 2, 2, 2, 3], [3, 2, 2, 2, 2], [2, 2, 3, 2, 2], [2, 3, 2, 2, 2], [2, 2, 2, 3, 2]
]def auto_mach(row, col, level, dx, dy):global ai_col, ai_row, max_levelcol_sel = -1  # 暂存棋子列号row_sel = -1  # 暂存棋子行号isfind = True  # 匹配成功的标记for j in range(5):cs = alist[row + j * dx][col + j * dy]if cs == 0:if cdata[level][j] == 3:row_sel = row + j * dxcol_sel = col + j * dyelif cdata[level][j] == 1:isfind = Falsebreakelif cdata[level][j] == 2:isfind = Falsebreakelif cs != cdata[level][j]:isfind = Falsebreakif isfind:ai_row = row_selai_col = col_selmax_level = levelreturn Truereturn Falsedef ai_play():global ai_col, ai_row, max_levelai_col = -1ai_row = -1max_level = -1# 搜素棋盘每个位置for i in range(19):for j in range(19):# 从高到低搜索for level in range(len(cdata) - 1, -1, -1):if level > max_level:if i + 4 < 19:if auto_mach(i, j, level, 1, 0):breakif j + 4 < 19:if auto_mach(i, j, level, 0, 1):breakif i + 4 < 19 and j + 4 < 19:if auto_mach(i, j, level, 1, 1):breakif j + 4 < 19 and i - 4 > 0:if auto_mach(i, j, level, -1, 1):breakif ai_row!=-1 and ai_row!=-1:alist[ai_row][ai_col]=2return Truewhile True:col = random.randint(0,18)row = random.randint(0, 18)if alist[row][col]==0:alist[row][col]=2ai_row=rowai_col=colreturn Truereturn Falsedef init():pygame.init()# 创建窗口,背景为棕色global screenscreen = pygame.display.set_mode((615, 615))pygame.display.set_caption('五子棋')screen.fill("#DD954F")# 创建外边框a = pygame.Surface((603, 603), flags=pygame.HWSURFACE)a.fill(color='#121010')b = pygame.Surface((585, 585), flags=pygame.HWSURFACE)b.fill(color="#DD954F")c = pygame.Surface((579, 579), flags=pygame.HWSURFACE)c.fill(color='#121010')e = pygame.Surface((31, 31), flags=pygame.HWSURFACE)e.fill(color="#DD954F")screen.blit(a, (6.5, 6.5))screen.blit(b, (15, 15))screen.blit(c, (18, 18))# 棋盘格子for j in range(18):for i in range(18):# 起点是20,间隔是32,每个格子大小31,所以格子间距1screen.blit(e, (20 + 32 * i, 20 + 32 * j))# 存储棋盘状态global alistalist = np.zeros((19, 19))# 星位pygame.draw.circle(screen, '#121010', [307.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 307.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [115.5, 115.5], 5)pygame.draw.circle(screen, '#121010', [499.5, 115.5], 5)pygame.draw.circle(screen, '#121010', [307.5, 499.5], 5)pygame.draw.circle(screen, '#121010', [307.5, 115.5], 5)# 刷新窗口pygame.display.flip()# 绘制棋子
def black(x, y):a = 20b = 20c = 20d = 0.01# 循环50次,每次绘制50个半径颜色不同的同心圆for i in range(50):pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))a += 1b += 1c += 1d += 0.08pygame.display.update()def white(x, y):a = 170b = 170c = 170d = 0.02for i in range(50):pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))a += 1b += 1c += 1d += 0.08pygame.display.update()pygame.font.init()
font1 = pygame.font.Font(None, 250)# 主要操作
def do(wb):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:x, y = pygame.mouse.get_pos()# 棋盘边界线的中点是19.5, 通过计算得到当前坐标在棋盘的行号和列号(x,y)x = round((x - 19.5) / 32)y = round((y - 19.5) / 32)if x < 0:x = 0if x > 18:x = 18if y < 0:y = 0if y > 18:y = 18if alist[x][y] == 0:black(x, y)alist[x][y] = 1wb1 = "You"wb = "white"check(x, y, wb1)pygame.time.wait(100)if ai_play():white(ai_row, ai_col)wb1 = "AI"wb = "black"check(ai_row, ai_col, wb1)def check(x, y, wb1):xx = xyy = ywhile True:# 从最上边的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上最上边的同色棋子if xx == 0:if alist[xx][yy] != alist[x][y]:xx += 1breakelif alist[xx][yy] != alist[x][y]:xx += 1breakelse:xx -= 1num = 0while True:if xx == 18:if alist[xx][yy] == alist[x][y]:num += 1breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1num += 1if num >= 5:win(wb1)# 从最边的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上最左边的同色棋子xx = xyy = ywhile True:if yy == 0:if alist[xx][yy] != alist[x][y]:yy += 1breakelif alist[xx][yy] != alist[x][y]:yy += 1breakelse:yy -= 1num = 0while True:if yy == 18:if alist[xx][yy] == alist[x][y]:num += 1breakelif alist[xx][yy] != alist[x][y]:breakelse:yy += 1num += 1if num >= 5:win(wb1)# 从左上方的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上左上方的同色棋子xx = xyy = ywhile True:if xx == 0:if alist[xx][yy] != alist[x][y]:xx += 1yy += 1breakelif yy == 0:if alist[xx][yy] != alist[x][y]:xx += 1yy += 1breakelif alist[xx][yy] != alist[x][y]:xx += 1yy += 1breakelse:xx -= 1yy -= 1num = 0while True:if xx == 18:if alist[xx][yy] == alist[x][y]:num += 1breakelif yy == 18:if alist[xx][yy] == alist[x][y]:num += 1breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1yy += 1num += 1if num >= 5:win(wb1)# 从右上方的棋子开始检查,记录颜色相同得棋子数量# 先找到最同一条线上右上方的同色棋子xx = xyy = ywhile True:if xx == 0:if alist[xx][yy] != alist[x][y]:xx += 1yy -= 1breakelif yy == 18:if alist[xx][yy] != alist[x][y]:xx += 1yy -= 1breakelif alist[xx][yy] != alist[x][y]:xx += 1yy -= 1breakelse:xx -= 1yy += 1num = 0while True:if xx == 18:if alist[xx][yy] == alist[x][y]:num += 1breakelif yy == 0:if alist[xx][yy] == alist[x][y]:num += 1breakelif alist[xx][yy] != alist[x][y]:breakelse:xx += 1yy -= 1num += 1if num >= 5:win(wb1)def win(wb1):pygame.font.init()font = pygame.font.Font(None, 70)text = font.render(f"{wb1}  won", True, (255, 255, 255))screen.blit(text, ((655 - text.get_width()) / 2, (665 - text.get_height()) / 2))pygame.display.update()while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:init()text = font.render("Start the game", True, (255, 255, 255))screen.blit(text, ((655 - text.get_width()) / 2, (665 - text.get_height()) / 2))pygame.display.update()pygame.time.wait(500)init()do("black")if __name__ == "__main__":init()do('black')

在这里插入图片描述

参考资料《趣学python游戏编程》

相关文章:

让电脑变得更聪明——用python实现五子棋游戏

作为经典的棋类游戏&#xff0c;五子棋深受大众喜爱&#xff0c;但如果仅实现人与人的博弈&#xff0c;那程序很简单&#xff0c;如果要实现人机对战&#xff0c;教会计算机如何战胜人类&#xff0c;那就不是十分容易的事了。本文我们先从简单入手&#xff0c;完成五子棋游戏的…...

C#-接口

接口 (interface) 定义了一个可由类和结构实现的协定。接口可以包含方法、属性、事件和索引器。接口不提供它所定义的成员的实现 — 它仅指定实现该接口的类或结构必须提供的成员。 接口可支持多重继承。在下面的示例中,接口 IComboBox 同时从 ITextBox 和 IListBox 继承。 i…...

ASP.NET可视化流程设计器源码

源码介绍: ASP.NET可视化流程设计器源码已应用于众多大型企事业单位。拥有全浏览器兼容的可视化流程设计器、表单设计器、基于角色的权限管理等系统开发必须功能&#xff0c;大大为您节省开发时间&#xff0c;是您开发OA.CRM、HR等企事业各种应用管理系统和工作流系统的最佳基…...

景联文科技GPT教育题库:AI教育大模型的强大数据引擎

GPT-4发布后&#xff0c;美国奥数队总教练、卡耐基梅隆大学数学系教授罗博认为&#xff0c;这个几乎是用“刷题”方式喂大的AI教育大模型的到来&#xff0c;意味着人类的刷题时代即将退出历史舞台。 未来教育将更加注重学生的个性化需求和多元化发展&#xff0c;借助GPT和AI教育…...

PHP进阶-实现网站的QQ授权登录

授权登录是站点开发常见的应用场景&#xff0c;通过社交媒体一键授权可以跳过注册站点账户的繁琐操作。本文将讲解如何用PHP实现QQ授权登录。首先&#xff0c;我们需要申请QQ互联开发者账号获得APPID和密钥&#xff1b;接着&#xff0c;我们下载QQ官方SDK&#xff1a;PHP SDK v…...

字节跳动基础架构SRE-Copilot获得2023 CCF国际AIOps挑战赛冠军

近日&#xff0c;2023 CCF国际AIOps挑战赛决赛暨“大模型时代的AIOps”研讨会在北京成功举办&#xff0c;活动吸引了来自互联网、运营商、科研院所、高校、软硬件厂商等领域多名专家学者参与&#xff0c;为智能运维的前沿学术研究、落地生产实践打开了新思路。决赛中&#xff0…...

python moviepy 图文批量合成带字幕口播视频

最近在研究将图片和文本批量合成为带字幕口播视频 主要是基于python的moviepy库 from generator import audio, pics, subs, videodef main():texts_input examplepics_input example# 图片分辨率预处理pics.adjust(pics_input)# 文字转语音audio.text_to_audio(texts_inpu…...

【代码片段】Linux C++打印当前函数调用堆栈

在开发大型项目时&#xff0c;尤其是多线程情况下&#xff0c;一般无法使用断点调试&#xff0c;这时候将当前函数的调用堆栈打印出来是非常有必要和有效的问题排查手段。 这里记录一段Linux环境下&#xff0c;打印函数堆栈的代码。 void get_native_callstack(std::string &a…...

Linux程序、进程以及计划任务(第一部分)

目录 一、程序和进程 1、什么是程序&#xff1f; 2、什么是进程&#xff1f; 3、线程是什么&#xff1f; 4、如何查看是多线程还是单线程 5、进程结束的两种情况&#xff1a; 6、进程的状态 二、查看进程信息的相关命令 1、ps&#xff1a;查看静态的进程统计信息 2、…...

Oracle database 12cRAC异地恢复至单机

环境 rac 环境 byoradbrac Oracle12.1.0.2 系统版本&#xff1a;Red Hat Enterprise Linux Server release 6.5 软件版本&#xff1a;Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit byoradb1&#xff1a;172.17.38.44 byoradb2&#xff1a;172.17.38.4…...

【docker】linux部署docker

简介 首先我需要声明的是&#xff0c;我的系统是centos7&#xff0c;下载工具使用的是yum&#xff1b;在linux上部署docker&#xff0c;之前一直看的是这篇文章Linux之Docker部署&#xff0c;基本上功能方面也都可以使用&#xff0c;部署起来也是比较的简单。首先我先讲述这篇…...

【K8S 云原生】Pod资源限制、Pod容器健康检查(探针)

目录 一、docker的重启方式和K8S重启方式 1、Pod的重启方式&#xff1a; 2、docker的重启策略&#xff1a; 二、yaml文件快速生成&#xff1a; 三、pod的状态&#xff1a; 四、Pod的资源限制 1、限制的方式和种类 2、CPU的限制的格式&#xff1a; 五、K8S拉取镜像的策…...

Python从入门到网络爬虫(模块详解)

模块 我们知道&#xff0c;函数和类都是可以重复调用的代码块。在程序中使用位于不同文件的代码块的方法是&#xff1a;导入 (import) 该对象所在的模块 (mudule)。当程序变得越来越大时&#xff0c;将程序的不同部分根据不同分类方法保存在不同文件中通常会更加方便。 导入模…...

[大厂实践] 无停机迁移大规模关键流量(下)

在系统升级、迁移的过程中&#xff0c;如何验证系统逻辑、性能正确无误&#xff0c;是一个很大的挑战。这一系列介绍了Netflix通过重放流量测试解决这一挑战的实践。原文: Migrating Critical Traffic At Scale with No Downtime — Part 2 想象一下&#xff0c;你被心爱的Netf…...

VMware Workstation虚拟机CentOS 7.9 配置固定ip的步骤

VMware Workstation虚拟机CentOS7.9配置固定ip的步骤 编辑虚拟机 打开VMware Workstation。 选择要配置的虚拟机&#xff0c;但不要启动它。 点击“编辑虚拟机设置”&#xff08;Edit virtual machine settings&#xff09;。 选择“网络适配器”&#xff08;Network Adapter&…...

构建自己的私人GPT

创作不易&#xff0c;请大家多鼓励支持。 在现实生活中&#xff0c;很多人的资料是不愿意公布在互联网上的&#xff0c;但是我们又要使用人工智能的能力帮我们处理文件、做决策、执行命令那怎么办呢&#xff1f;于是我们构建自己或公司的私人GPT变得非常重要。 一、本地部署…...

EtherCAT主站SOEM -- 14 --Qt-Soem通过界面采集从站IO进行显示

EtherCAT主站SOEM -- 14 --Qt-Soem通过界面采集从站IO进行显示 一 mainwindow.c 文件函数:1.1 自定义PDO配置1.2 主站初始化二 motrorcontrol.c 文件三 allvalue.h 文件该文档修改记录:总结一 mainwindow.c 文件函数: 1.1 自定义PDO配置 int IO_setup(uint16 slave) {int...

线程安全、共享变量的可见性

Java中的线程安全问题 谈到线程安全问题&#xff0c;我们先说说什么是共享资源。所谓共享资源&#xff0c;就是说该资源被多个线程所持有或者说多个线程都可以去访问该资源。 线程安全问题是指当多个线程同时读写一个共享资源并且没有任何同步措施时&#xff0c;导致出现脏数…...

电动汽车BMS PCB制板的技术分析与可制造性设计

随着电动汽车行业的迅猛发展&#xff0c;各大厂商纷纷投入巨资进行技术研发和创新。电动汽车的核心之一在于其电池管理系统&#xff08;Battery Management System, BMS&#xff09;&#xff0c;而BMS的心脏则是其印刷电路板&#xff08;PCB&#xff09;。通过这篇文章探讨电动…...

Android 车联网——多屏多用户(十五)

前面几篇文章介绍了多用户和多屏相关的 Manager 和 Service。上一篇文章最后虽然车内乘员都根据配置有自己的对应屏幕,但默认情况下,所有车内乘员依然使用的是当前主用户(司机用户),这一篇我们继续放下看一下用户的创建与分配。 一、用户创建分配 1、创建用户 对于创建用…...

uwsgitop 使用

背景&#xff1a;Django项目 uwsgi&#xff0c;uwsgi.ini 在工程下。 使用&#xff1a; 下载安装uwsgitop [roothost ~]# tar -zxvf uwsgitop-0.11.tar.gz [rootuwsgitop-0.11 ~]# cd uwsgitop-0.11/ [rootuwsgitop-0.11 ~]# python setup.py install [rootuwsgitop-0.11 …...

深信服技术认证“SCSA-S”划重点:文件包含漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…...

Color Control

设计一个优秀的用户界面是一项艰巨的任务。特别是如果你想改变UI的颜色,调整所有元素可能需要花费大量时间。Color Control可以帮助你!在检查器中以可视化的方式将你的项目颜色定义为资源。Color Control为你提供了组件,当你编辑它们时,它们会自动更新你的UI元素。 颜色控制…...

端口开放问题

端口开放问题 所遇问题 在宿主主机上可以ping通虚拟机ip192.168.27.129&#xff0c;但无法在宿主主机上访问http://192.168.27.129:8080navavcat 16连接mysql时&#xff0c;2002 - Can’t connect to server on ‘192.168.27.129’(100601&#xff09; 原因 以上两个问题&a…...

KNN 回归

K 近邻回归&#xff08;K-Nearest Neighbors Regression&#xff09;是一种基于实例的回归算法&#xff0c;用于预测连续数值型的输出变量。它的基本思想是通过找到与给定测试样本最近的 K 个训练样本&#xff0c;并使用它们的输出值来预测测试样本的输出。它与 K 最近邻分类类…...

Kali Linux——获取root权限

目录 一、设置root密码 【操作命令】 【操作实例】 二、临时获取root权限 【操作命令】 【操作实例】 三、提升用户到root 1、获取root权限 2、进入/etc/passwd 3、查看root账号ID 4、找到需要修改的用户 5、输入i&#xff0c;进入编辑模式 6、把用户的ID改成跟r…...

听GPT 讲Rust源代码--compiler(28)

File: rust/compiler/rustc_codegen_llvm/src/llvm/mod.rs 文件rust/compiler/rustc_codegen_llvm/src/llvm/mod.rs是Rust编译器的LLVM代码生成模块的一个文件。该文件定义了一些用于与LLVM交互的结构体、枚举和常量。 此文件的主要作用是&#xff1a; 定义编译器和LLVM之间的接…...

Debezium日常分享系列之:Debezium2.5版本之connector for JDBC

Debezium日常分享系列之&#xff1a;Debezium2.5版本之connector for JDBC 一、概述二、JDBC 连接器的工作原理三、使用复杂的 Debezium 变更事件四、至少一次交付五、多项任务六、数据和列类型映射七、主键处理八、删除模式九、幂等写入十、Schema evolution十一、引用和区分大…...

爬虫网易易盾滑块案例:某乎

声明&#xff1a; 该文章为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;违者后果自负&#xff0c;由此产生的一切后果均与作者无关 一、滑块初步分析 js运行 atob(‘aHR0cHM6Ly93d3cuemhpaHUuY29tL3NpZ25pbg’) 拿到网址&#xff0c;浏览器打开网站&#xff0…...

机器学习笔记 - 偏最小二乘回归 (PLSR)

一、偏最小二乘回归:简介 PLS 方法构成了一个非常大的方法族。虽然回归方法可能是最流行的 PLS 技术,但它绝不是唯一的一种。即使在 PLSR 中,也有多种不同的算法可以获得解决方案。PLS 回归主要由斯堪的纳维亚化学计量学家 Svante Wold 和 Harald Martens 在 20 世纪 80 年代…...

如何给网站流量来源做标记通过在网址后边加问号?/百度竞价推广属于什么广告

框架专利的重要性 ---法国汤姆森公司有损扩展无损专利分析 在国内专利申请中&#xff0c;汤姆森许可贸易公司&#xff08;就是那个和fraunfor IIS 等公司共同持有MP3专利的那个法国企业&#xff09;在中国申请了4个与在现在的有损编码器方法&#xff08;标准&#xff0c;系统&a…...

青岛模版网站建设哪家好/湖南关键词排名推广

为什么80%的码农都做不了架构师&#xff1f;>>> - (UIStatusBarStyle)preferredStatusBarStyle {return UIStatusBarStyleLightContent; } 转载于:https://my.oschina.net/cgphp/blog/389962...

上海网站建设与设计公司/淘宝关键词指数查询

转自&#xff1a;指尖流淌 http://www.cnblogs.com/zhijianliutang/p/4100103.html SQL Server数据库启动过程&#xff08;用户数据库加载过程的疑难杂症&#xff09; 前言 本篇主要是上一篇文章的补充篇&#xff0c;上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和…...

做网站推广代理/东莞网站推广方案

根据需求&#xff0c;在一台服务器上部署了多个tomcat&#xff0c;每个Tomcat设置不同端口&#xff0c;将遇到的一些坑记录一下&#xff1a;说明&#xff1a;每个Tomcat需要修改设置不同的端口&#xff0c;这种基础问题就不说了。由于这是我排完错之后才写的&#xff0c;有些已…...

佛山做外贸网站推广/网站维护费一年多少钱

bouncy castle转载于:https://www.cnblogs.com/webundle/p/5864664.html...

ui设计的发展趋势/网站优化排名软件

写于2019年1月10日天添书香阁开更前的历史记录1今年开始的读书笔记&#xff0c;准备从构建多元思维模型的角度&#xff0c;分析每本书在各自思维模型领域赋予的价值&#xff0c;探索每个思维模型在现实生活中的用法以及与其他思维模型的结合。目标通过5-10年时间&#xff0c;架…...