训练简单的ANN神经网络实现人棋对战(井字棋,Tic-tac-toe)

 

目录

 

摘要:

井字棋(Tic-tac-toe)介绍:

数据集:

模型构建及训练: 

应用实现,实现井字棋:

人机对下,结果分析:

摘要:

     井字棋是一种决策类下棋游戏,一般情况下先下棋者赢的可能性大一些。为了理解和观察人工智能算法在实际应用上的可行性。因此,我们训练了一个简单的全连接神经网络以阻止玩家获胜的空间。对于简单的3x3井字棋游戏,可以使用神经网络算法轻松学习到走棋方式。但是,更复杂的游戏(例如围棋)具有更复杂的走棋模式所以需要更复杂的方法来评估棋局间的下棋质量。

井字棋(Tic-tac-toe)介绍:

井字棋,又称为井字游戏、(英语:Tic-tac-toe)圈圈叉叉;另外也有打井游戏、○×棋的称呼,香港多称井字过三关、是种纸笔游戏,另有多种衍生变化玩法。 

玩法——

两个玩家,一个打圈,一个打叉,轮流在3乘3的格上打自己的符号,最先以横、直、斜连成一线则为胜。如果双方都下得正确无误,将得和局。

这种游戏实际上是由第一位玩家所控制,第一位玩家是攻,第二位玩家是守。第一位玩家在角位行第一子的话赢面最大(见图一),第二位玩家若是在边,角位下子,第一位玩家就可以以两粒连线牵制着第二位玩家,然后制造“两头蛇”,所以他必须下中央。

如第一位玩家下在中央,则第二位玩家必须下在角位才不会输。如第一位玩家下在边位,第二位玩家可以下在中央或角位,或是与第一位玩家下的位置相对的边位。

数据集:

这是一个多类分类任务,在该任务中设置棋盘以使其成为O玩家的举动,并且目标是预测对O玩家(即玩家-1)最佳的下一举动。

0 1 2
3 4 5
6 7 8

输入为x 0,...,x 8,即给定棋盘的Tic Tac Toe方块的状态,而输出y为O玩家(玩家-1)的最佳步法索引。

模型构建及训练: 

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(9,)), #input layer
    keras.layers.Dense(18, activation=tf.nn.tanh), #hidden layer
    keras.layers.Dense(9, activation=tf.nn.softmax) #output layer
])

#compiling neural network
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=["accuracy"])
# print(train_labels)
#training model
model.fit(train_images, train_labels, epochs=200)
#running tests (no learning occurs here)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('Test accuracy:', test_acc)

训练次数200的结果如下:

应用实现,实现井字棋:

棋盘实现核心代码:

#调用训练好的模型寻找最优步骤
predictions = model.predict(test_images)
for i in range(15):
    print(np.round(predictions[i]*1000)/1000, np.argmax(predictions[i]), test_labels[i])
import pygame, sys
from pygame.locals import *
#初始化pygame和显示屏
pygame.init()
surface = pygame.display.set_mode((480,480))
color = (0,0,0)
surface.fill((255,255,255))
pygame.draw.line(surface, color, (160,0), (160,480), 4)
pygame.draw.line(surface, color, (320,0), (320,480), 4)
pygame.draw.line(surface, color, (0,160), (480,160), 4)
pygame.draw.line(surface, color, (0,320), (480,320), 4)
#棋盘显示
zones = []
for i in range(3):
    for j in range(3):
        zones.append([j*160,i*160,j*160+160,i*160+160])
#board位置s
board = [0,0,0,0,0,0,0,0,0]
#在实际的井字游戏中检查是否有可能获胜
def checkForWin(x):
    if board[0] == x and board[1] == x and board[2] == x:
        return True
    if board[3] == x and board[4] == x and board[5] == x:
        return True
    if board[6] == x and board[7] == x and board[8] == x:
        return True
    if board[0] == x and board[3] == x and board[6] == x:
        return True
    if board[1] == x and board[4] == x and board[7] == x:
        return True
    if board[2] == x and board[5] == x and board[8] == x:
        return True
    if board[0] == x and board[4] == x and board[8] == x:
        return True
    if board[2] == x and board[4] == x and board[6] == x:
        return True
    else:
        return False
#循环
def mainloop():
    mainloop = True
    while mainloop== True:
        pygame.draw.line(surface, color, (160,0), (160,480), 4)
        pygame.draw.line(surface, color, (320,0), (320,480), 4)
        pygame.draw.line(surface, color, (0,160), (480,160), 4)
        pygame.draw.line(surface, color, (0,320), (480,320), 4)
        #getting click events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                mainloop = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mousex, mousey = pygame.mouse.get_pos()
                for i in range(9):
                    #玩游戏
                    if mousex >= zones[i][0] and mousex <= zones[i][2] and mousey >= zones[i][1] and mousey <= zones[i][3]: #figures out what zone the mouse clicked in
                        if board[i] == 0:
                            board[i] = 1 #filling board position
                            #drawing X
                            mid = (int((zones[i][0] + zones[i][2])/2), int((zones[i][1] + zones[i][3])/2))
                            pygame.draw.line(surface, color, (mid[0]-60, mid[1]-60), (mid[0]+60, mid[1]+60), 4)
                            pygame.draw.line(surface, color, (mid[0]+60, mid[1]-60), (mid[0]-60, mid[1]+60), 4)
                            print(np.array([board], dtype="float"))
                            #checks if either player won or draw
                            xwin = checkForWin(1)
                            ywin = checkForWin(-1)
                            if xwin:
                                print("You wins!")
                                mainloop = False
                                break
                            elif 0 not in board and not ywin and not xwin:
                                print("Draw!")
                                mainloop = False
                                break
                            #神经网络进行预测以获得最佳下一步
                            predictions = model.predict(np.array([board], dtype="float"))
                            print(predictions)
                            print(np.argmax(predictions))
                            space = np.argmax(predictions)
                            board[space] = -1 #populating board     
                            mid = (int((zones[space][0] + zones[space][2])/2), int((zones[space][1] + zones[space][3])/2))
                            pygame.draw.circle(surface, color, mid, 60, 4)
                            break
                ywin = checkForWin(-1)
                if ywin:
                    print("Y wins!")
                    mainloop = False
                    break
        pygame.display.flip()
        if not mainloop:
            break
while 1:
    mainloop();
    if input("Play again?: ") == "no":
        break;
    board = [0,0,0,0,0,0,0,0,0]
    surface.fill((255,255,255))
    pygame.draw.line(surface, color, (160,0), (160,480), 4)
    pygame.draw.line(surface, color, (320,0), (320,480), 4)
    pygame.draw.line(surface, color, (0,160), (480,160), 4)
    pygame.draw.line(surface, color, (0,320), (480,320), 4)
pygame.quit()

人机对下,结果分析:

训练200次,准确率不高的情况下:X为我走的第一步,O为机器预测要走的步骤。

当我走第一步时,机器预测走x2处可能赢的概率要大

最后,还是我赢了。

                                                                

但是又随便下了一次:

        模型到底是怎么预测的,为何两次下的步骤不一样,我不是非常清楚,目前还在研究中...相关细节,会在后续陆续补上代码详解。

原创文章 54 获赞 252 访问量 20万+

猜你喜欢

转载自blog.csdn.net/weixin_40651515/article/details/105756250