您的位置:首页 > 大数据 > 人工智能

【机器学习实战】制作五子棋AI之三:基本规则的建立【1】

2017-08-16 11:43 447 查看
我们已经完成了UI的界面的组合和棋子的放置问题,接下来要为这个五子棋AI设定一些基本规则,让他能够按照真实的五子棋规则运行。

上一次,我们使用一个二维数组(i,j),i,j∈{1,2,3,…,15}来表示每个格点的标号,其中i 代表从上到下的行号,j 代表从左到右的列号,但是有些时候使用起来略微不方便,这里定义两个函数让一维索引值和二维格点坐标可以相互转化。

def array2index(array):
return (array[0]-1)*15+array[1]

def index2array(index):
i,j = int((index-index%15)/15+1),int(index%15)
if j == 0 :
i -= 1
j = 15
return i,j


另外,还需要一个函数将二维数组转化为在窗口中的坐标,其实上次就写好了,只要把它封装起来就好。

def array2pixel(array):
# 计算棋子在棋盘中的位置
piece_chessboard_x,piece_chessboard_y = 22+(array[1]-1)*d,22+(array[0]-1)*d
# 计算棋子的实际位置
piece_x,piece_y = piece_chessboard_x+chessboard_start_x,piece_chessboard_y+chessboard_start_y
return piece_x,piece_y


下面,我们要为游戏设置一些基本规则。想象一下,我们下棋的时候,按先后手顺序依次落子,每次落子后棋盘上的状态就会改变,那么我们需要定义一个类,来存放和读取棋盘每次变化后的状态。

class GameStatus(object):
def __init__(self):
# 黑棋落子的索引值列表
self.__black = list()
# 白棋落子的索引值列表
self.__white = list()

# 初始化一些硬件设备
pygame.init()
# 创建一个窗口
self.__screen = pygame.display.set_mode((1024,768),0,32)
# 设置窗口标题
pygame.display.set_caption('五子棋AI')

# 背景和棋盘图片
self.__background_surface = pygame.image.load(imagePath+'background.jpg').convert()
self.__chessboard_surface = pygame.image.load(imagePath+'chessboard.jpg').convert()
#  黑白白色棋子图片
self.__black_surface = pygame.image.load(imagePath+'blackpiece.png').convert_alpha()
self.__white_surface = pygame.image.load(imagePath+'whitepiece.png').convert_alpha()

# 设置黑白棋落子索引值列表
def set_list(self,black,white):
self.__black = black
self.__white = white

# 添加黑棋落子索引值
def black_append(self,index):
self.__black.append(index)

#得到黑棋历史所引致
def black_list(self):
return self.__black

# 黑棋个数
def black_count(self):
return len(self.__black)

# 添加黑棋落子索引值
def white_append(self,index):
self.__white.append(index)

#得到白棋历史所引致
def white_list(self):
return self.__white

# 白棋个数
def white_count(self):
return len(self.__black)

# 棋盘剩余空格索引值列表
def empty_list(self):
empty = list(range(1,226))
for i,j in zip(self.__black,self.__white):
empty.remove(i)
empty.remove(j)
return empty


这样通过
GameStatus
类就能知道棋盘上黑白棋和空客的情况了,当已知棋盘棋盘状态后,我们就要把棋子画到棋盘上去,为了方便起见,把绘制的过程也包含到
GameStatus
类下

class GameStatus(object):
def __init__(self):
# 黑棋落子的索引值列表
self.__black = list()
# 白棋落子的索引值列表
self.__white = list()

# 初始化一些硬件设备
pygame.init()
# 创建一个窗口
self.__screen = pygame.display.set_mode((1024,768),0,32)
# 设置窗口标题
pygame.display.set_caption('五子棋AI')

# 背景和棋盘图片
self.__background_surface = pygame.image.load(imagePath+'background.jpg').convert()
self.__chessboard_surface = pygame.image.load(imagePath+'chessboard.jpg').convert()
#  黑白白色棋子图片
self.__black_surface = pygame.image.load(imagePath+'blackpiece.png').convert_alpha()
self.__white_surface = pygame.image.load(imagePath+'whitepiece.png').convert_alpha()

# 设置黑白棋落子索引值列表
def set_list(self,black,white):
self.__black = black
self.__white = white

# 添加黑棋落子索引值
def black_append(self,index):
self.__black.append(index)

#得到黑棋历史所引致
def black_list(self):
return self.__black

# 黑棋个数
def black_count(self):
return len(self.__black)

# 添加黑棋落子索引值
def white_append(self,index):
self.__white.append(index)

#得到白棋历史所引致
def white_list(self):
return self.__white

# 白棋个数
def white_count(self):
return len(self.__black)

# 棋盘剩余空格索引值列表
def empty_list(self):
empty = list(range(1,226))
for i,j in zip(self.__black,self.__white):
empty.remove(i)
empty.remove(j)
return empty

def draw_background(self):
# 将背景图画上去
self.__screen.blit(self.__background_surface,(0,0))
# 将棋盘画在背景图片的正中间
self.__screen.blit(self.__chessboard_surface,(chessboard_start_x,chessboard_start_y))

def draw_pieces(self):
for i,j in zip(self.__black,self.__white):
x,y = array2pixel(index2array(i))
x -= self.__black_surface.get_width()/2
y -= self.__black_surface.get_height()/2
self.__screen.blit(self.__black_surface,(x,y))
x,y = array2pixel(index2array(j))
x -= self.__white_surface.get_width()/2
y -= self.__white_surface.get_height()/2
self.__screen.blit(self.__white_surface,(x,y))


在绘制函数里面,用到了一些上次用过的pygame的函数、一些计算坐标常量以及上面写的转换函数,把它们添加在类定义前面

import pygame
from pygame.locals import *

imagePath = 'XXX'

# 间距
d = (518-22)/14
# 棋盘左上角初始位置
chessboard_start_x = (1024-540)/2-1
chessboard_start_y = (768-540)/2-1

def array2index(array):
return (array[0]-1)*15+array[1]
def index2array(index):
return (index-index%15)/15+1,index%15
def array2pixel(array): # 计算棋子在棋盘中的位置 piece_chessboard_x,piece_chessboard_y = 22+(array[1]-1)*d,22+(array[0]-1)*d # 计算棋子的实际位置 piece_x,piece_y = piece_chessboard_x+chessboard_start_x,piece_chessboard_y+chessboard_start_y return piece_x,piece_y


最后,将它保存成
gamerule.py
文件,方便我们在主程序里面调用。将上次写的主程序拿出来稍作修改,去掉原来的绘图部分使用新写好的类的方法代替。

import pygame
from pygame.locals import *
from sys import exit
from gamerule import GameStatus

status = GameStatus()
while True:
# pygame中有鼠标 键盘 手柄 用户定义等各种事件
for event in pygame.event.get():
#接收到退出事件后退出程序
if event.type == QUIT:
pygame,quit()
exit()

# 黑白棋落子的索引值列表
black = [1,2,3,4,5]
white = [6,7,8,9,10]
# 将两个列表给到棋盘状态
status.set_list(black,white)
# 绘制背景和棋子
status.draw_background()
status.draw_pieces()

#刷新一下画面
pygame.display.update()


如果不出意外的话,那么就能够得到如下的测试画面



好了,那么这次我们存取并显示棋盘状态的功能就完成了。

由于本人水平有限,难免出现错漏之处,欢迎批评指正
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息