机器学习实践:棋类游戏-5

机器学习实践:棋类游戏

1、实验描述

  • 本实验中,利用游戏Pygame库,结合Python基础编程编写棋类游戏脚本,使得玩家能够与AI电脑进行对抗博弈。AI下棋算法利用蒙特卡洛搜索树思想。通过设置AI的难度系数,从而决定AI在蒙特卡罗算法中的迭代次数,也就是定义好了AI能考虑到接下来对抗的几个回合落子情况,从而选择出最佳的方案和玩家对抗,本实验中AI难度设置较小,有兴趣的同学加入自己的思路进行实验。通过本实验的学习,我们能了解pygame在游戏开发中的应用以及蒙特卡罗搜索树思想。

  • 实验时长:90分钟

  • 主要步骤:

    • 数据准备

    • 全局变量代码定义

    • 棋盘设计代码编写

    • 棋子动态移动代码编写

    • 判断输赢代码编写

    • 用蒙特卡罗算法编写AI下棋

    • AI棋子操作代码编写

    • 玩家操作代码编写

    • 程序入口代码编写

    • 运行程序,与电脑博弈

2、实验环境

  • 虚拟机数量:1

  • 系统版本:CentOS 7.5

  • Python版本:Python 2.7

3、相关技能

  • linux命令
  • vim使用
  • Python编程
  • Pygame库使用
  • 蒙特卡洛搜索树算法原理

4、知识点

  • Pygame基础

  • 蒙特卡洛搜索树思想

5、效果图

  • 最终棋局
    在这里插入图片描述
图 1

6、实验步骤

6.1实验简介

6.1.1四子棋游戏是在5*5的格子中。轮流从格子最上方落下棋子。棋子会落在该列格子中最下面的空格子里。先将四个连续棋子连成一条线(水平直线,竖直直线,或倾斜直线)者获胜,游戏结束

6.2实验准备

6.2.1打开Linux终端进入experiment/pygame目录下,解压图片文件images.zip

[zkpk@master ~]$ cd experiment/pygame
[zkpk@master pygame]$ unzip images.zip
[zkpk@master pygame]$ cd
[zkpk@master ~]$ 

6.2.2安装依赖包

[zkpk@master ~]$ pip install --user -i https://pypi.doubanio.com/simple/ --trusted-host pypi.doubanio.com pygame

6.3准备编写代码

6.3.1在zkpk家目录下创建python文件pyChessgame.py文件

[zkpk@master ~]$ vim pyChessgame.py

6.3.2开始编写代码

6.3.3导入实验所需包和文件,并设置全局变量

6.3.3.1设置python脚本的编码格式为utf-8,使其支持中文字符

# -*- coding: utf-8 -*-

6.3.3.2导入实验所需要的包pygame和一些基础包

import random, copy, sys, pygame
from pygame.locals import *

6.3.3.3棋盘的宽度和高度,利用if-else语句判断棋盘是否符合游戏设置,不满足则程序报错

Chessboard_width = 5 # 棋子盘的宽度(5倍棋子大小)
Chessboard_height = 5 # 棋子盘的高度
if  Chessboard_width>=4 and Chessboard_height>=4:
   print("")
else:
   print("棋盘大小过小,不能满足四子棋的要求,请至少满足4*4格式")
   exit()

6.3.3.4设置AI的难度水平为2(与算法的递归有关);设置棋子大小为50;设置游戏窗口宽度和高度

AI_LEVEL=2 #AI难度
Chessman_size = 50 # 棋子的大小
Window_width = 640  # 游戏屏幕的像素宽度
Window_height = 480 # 游戏屏幕的像素高度

6.3.3.5设置棋盘在游戏框中的位置,水平方向取的是总宽度减去棋盘宽度,再均分为2,竖直方向是总高度减去棋盘高度,再均分为2,即水平居中、竖直居中显示棋盘

X_Left=int((Window_width - Chessboard_width * Chessman_size) / 2) 
Y_Height=int((Window_height - Chessboard_height * Chessman_size) / 2)

6.3.3.6设置游戏窗口的背景颜色为矢车菊蓝(100,149,237)

BackgroundColor=(100,149,237)

6.3.3.7定义人和电脑的字符串变量,方便后续调用

People = 'people'
Computer = 'computer'

6.3.3.8初始化pygame模块,初始化一个Clock模块

pygame.init()
FPSCLOCK = pygame.time.Clock()

6.3.3.9利用pygame的set_mode方法创建游戏窗口,并设置窗口标题

GameWindow=pygame.display.set_mode((Window_width,Window_height))
pygame.display.set_caption(u'Python Board Games')

6.3.3.10利用Rect方法定义红色、黑色棋盒的位置和宽高

RedBowls=pygame.Rect(int(Chessman_size / 2), Window_height - int(3 * Chessman_size / 2), Chessman_size, Chessman_size)#红色棋盒;left/top/width/height
BlackBowls=pygame.Rect(Window_width - int(3 * Chessman_size / 2), Window_height - int(3 * Chessman_size / 2), Chessman_size, Chessman_size)#黑色棋盒

在这里插入图片描述

6.3.3.11读取红色实验图片文件表示红色棋子,读取黑色实验图片文件表示黑色棋子,读取面板实验图片表示棋子面板

#红色棋子
RedChessman=pygame.image.load('/home/zkpk/experiment/pygame/images/red.png')
RedChessman=pygame.transform.smoothscale(RedChessman,(Chessman_size, Chessman_size))
#黑色棋子
BlackChessman=pygame.image.load('/home/zkpk/experiment/pygame/images/black.png')
BlackChessman=pygame.transform.smoothscale(BlackChessman,(Chessman_size, Chessman_size))
#棋子面板
BoardImg=pygame.image.load('/home/zkpk/experiment/pygame/images/board.png')
BoardImg=pygame.transform.smoothscale(BoardImg, (Chessman_size, Chessman_size))

6.3.3.12分别载入人和电脑获胜以及平局时的图片

PeopleWINNERIMG=pygame.image.load('/home/zkpk/experiment/pygame/images/peoplewinner.png')
ComputerWINNERIMG=pygame.image.load('/home/zkpk/experiment/pygame/images/computerwinner.png')
TIEWINNERIMG=pygame.image.load('/home/zkpk/experiment/pygame/images/tie.png')

6.3.3.13利用get_rect方法获得矩形对象,利用矩形对象调整图片的位置和大小等等,这里我们将图片的中心设置在游戏窗口的中间显示

#返回Rect实例
WINNERRECT = PeopleWINNERIMG.get_rect()
#游戏窗口中间位置坐标
WINNERRECT.center = (int(Window_width / 2), int(Window_height / 2))

6.3.3.14载入第一次下棋操作提示图片,获取其矩阵对象,设置其位置在红色棋盒右边距离10个像素点的位置,再利用centery属性使操作提示图片与红色棋盒纵向对齐

ARROWIMG=pygame.image.load('/home/zkpk/experiment/pygame/images/arrow.png')
ARROWRECT = ARROWIMG.get_rect()
ARROWRECT.left = RedBowls.right + 10
ARROWRECT.centery = RedBowls.centery

6.3.4棋盘设计

6.3.4.1定义构建棋盘方法drawBoard,该方法接受两个参数分别是棋盘board和棋格的属性extraToken,若调用时没有指定extraToken则默认为None;在方法中填充游戏窗口颜色,然后获取每一个棋格的位置和值,判断其颜色并绘图

def drawBoard(board, extraToken=None):
    #GameWindow 是我们的界面,在初始化变量模块中有定义
    GameWindow.fill(BackgroundColor)#将游戏窗口背景色填充为蓝色
    spaceRect = pygame.Rect(0, 0, Chessman_size, Chessman_size)#创建Rect实例
    for x in range(Chessboard_width):
        #确定每一列中每一行中的格子的左上角的位置坐标
        for y in range(Chessboard_height):
            spaceRect.topleft = (X_Left + (x * Chessman_size), Y_Height + (y * Chessman_size))
            if board[x][y] == 'red':#如果棋格的值为红色
                #则在在游戏窗口的spaceRect中画红色棋子
                GameWindow.blit(RedChessman, spaceRect)
            elif board[x][y] == 'black': #否则画黑色棋子
                GameWindow.blit(BlackChessman, spaceRect)

    # extraToken 是包含了位置信息和颜色信息的变量
    # 用来显示指定的棋子的
    if extraToken != None:
        if extraToken['color'] == 'red':
            GameWindow.blit(RedChessman,(extraToken['x'],
			extraToken['y'], Chessman_size, Chessman_size))
        elif extraToken['color'] == 'black':
            GameWindow.blit(BlackChessman, (extraToken['x'], 
			extraToken['y'], Chessman_size, Chessman_size))

    # 画棋子面板
    for x in range(Chessboard_width):
        for y in range(Chessboard_height):
            spaceRect.topleft = (X_Left + (x * Chessman_size), Y_Height + (y * Chessman_size))
            GameWindow.blit(BoardImg, spaceRect)

    # 画游戏窗口中左下角和右下角的棋盒
    GameWindow.blit(RedChessman, RedBowls) # 左边的红色棋盒
    GameWindow.blit(BlackChessman, BlackBowls) # 右边的黑色棋盒

6.3.4.2定义getNewBoard方法用来获取新的棋盘,其中返回的是Chessboard_width*Chessboard_height个None的列表

def getNewBoard():
    board = []
    for x in range(Chessboard_width):
        board.append(['None'] * Chessboard_height)
    return board

6.3.5棋子移动方法的定义

6.3.5.1定义getlowestEmptySpace方法,接受棋盘和某一列,获得该列最下方的值为None的棋格,若没有则返回-1表示无空余棋格

def getLowestEmptySpace(board, column):
    for y in range(Chessboard_height-1, -1, -1):
        if board[column][y] == 'None':
            return y
    return -1

6.3.5.2定义在确定棋子移动后绘制颜色方法makeMove,接受棋盘、操作者颜色、某一列三个参数,该方法先获取该列的最下方一个空闲棋格,如果有空闲棋格,则将其值赋予操作者颜色

def makeMove(board, playercolor, column):
    lowest = getLowestEmptySpace(board, column)
    if lowest != -1:  #判断是否存在最下方空闲棋格
        board[column][lowest] = playercolor

6.3.5.3定义棋子实现棋子动态降落算法Dynamic_landing,该方法接受棋盘、某一列、棋子颜色三个参数,方法中先找到棋子下降所在的列的位置(x,y),利用getLowestEmptySpace方法获得最下方的空闲棋格,利用循环使棋子以一定的速度和加速度下落至最下面的空闲棋格

def Dynamic_landing(board, column, color):
    x = X_Left + column * Chessman_size
    y = Y_Height - Chessman_size
    dropSpeed = 1.0#棋子降落的速度
    lowestEmptySpace = getLowestEmptySpace(board, column)
    while True:
        y += int(dropSpeed)#y的坐标以dropSpeed叠加
        dropSpeed += 0.5#棋子下落的加速度为0.5
        #判断是否到达最下面的空格
        if int((y - Y_Height) / Chessman_size) >= lowestEmptySpace:
            return
        #y不断变化,不断绘制红色棋子,形成降落效果
        drawBoard(board, {'x':x, 'y':y, 'color':color})
        pygame.display.update()
        FPSCLOCK.tick()

6.3.6定义判断胜利、平局和移动是否成功等方法

6.3.6.1定义方法:判断是否胜利isWinner,该方法接受棋盘和棋子颜色两个参数,然后考虑4种可能获胜的情况,只要有一种满足则返回True表示该颜色棋子获胜,若否不满足则返回Flase表示该颜色棋子没有获胜;4种情况分别是:水平方向4子相连;竖直方向4子相连;左斜方向4子相连;右斜方向4子相连

def isWinner(board, tile):
    for x in range(Chessboard_width - 3): #x的取值可以是0,1
        for y in range(Chessboard_height):
            if board[x][y] == tile and board[x+1][y] == tile and board[x+2][y] == tile and board[x+3][y] == tile: #水平方向是否获胜
                return True
    for x in range(Chessboard_width):
        for y in range(Chessboard_height - 3):
            if board[x][y] == tile and board[x][y+1] == tile and board[x][y+2] == tile and board[x][y+3] == tile: #竖直方向是否获胜
                return True
    for x in range(Chessboard_width - 3):
        for y in range(3, Chessboard_height):
            if board[x][y] == tile and board[x+1][y-1] == tile and board[x+2][y-2] == tile and board[x+3][y-3] == tile: #左斜方向是否获胜
                return True
    for x in range(Chessboard_width - 3):
        for y in range(Chessboard_height - 3):
            if board[x][y]==tile and board[x+1][y+1]==tile and board[x+2][y+2]==tile and board[x+3][y+3] == tile: #右斜方向是否获胜
                return True
    return False

6.3.6.2判断移动是否有效方法isValidMove,该方法接受棋盘和某列两个参数,如果拖动棋子到所在列column松开鼠标,则判断该列是否小于0或者大于棋盘宽度或者该列中第一个棋格都是非空的,则判断为无效移动,否则为有效移动

def isValidMove(board, column):
    if column < 0 or column >= (Chessboard_width) or board[column][0] != 'None': #如果列小于0或者列大于棋盘宽度或者该列无空闲棋格,则为无效移动False,否则为有效移动True
        return False
    return True

6.3.6.3定义判断棋盘是否还有空闲棋格的方法isBoardFull,该方法接受一个棋盘参数,遍历棋盘中所有的棋格,如果有一个空闲的棋格则返回False表示棋盘还有空格,否则返回棋盘没有空格了,没有空格而还未决出胜负的话就表示平局了

def isBoardFull(board):
    for x in range(Chessboard_width):
        for y in range(Chessboard_height):
            if board[x][y] == 'None': #遍历所有棋格
                return False
    return True

6.3.7定义AI获取最佳移动算法

6.3.7.1蒙特卡洛搜索树的思想:利用一维中的掷点法完成对围棋盘面的评估。当我们给定某一个棋盘局面时,程序在当前局面的所有可下点中随机选择一个点摆上棋子,并不断重复这个随机选择可下点(掷点)的过程,直到双方都没有可下点(即对弈结束),再把这个最终状态的胜负结果反馈回去,作为评估当前局面的依据。在本实验当中AI通过不断选择不同的栏,然后考虑双方的获胜结果进行评估,AI最终会选择评估较高的策略

6.3.7.2蒙特卡罗最佳移动算法最终返回的是一个移动列表,列表中存储的AI移动棋子到任意一个棋格时获胜的可能性大小,其数值为-1~1的随机数,趋近于1表示AI获胜的可能性越大,趋近于-1是表示人的获胜可能性越大,为0时表示都不会获胜

6.3.7.3AI在每一次移动时,会预测接下来两个回合(因为AI难度设置)的对抗中谁会胜出

def Monte_Carlo(board, tile, AI_LEVEL):
    #如果AI的难度为0或者,棋盘已满,则返回一个全为0的列表,此时AI失去智能
    if AI_LEVEL == 0 or isBoardFull(board):
        return [0] * Chessboard_width
    #确定对手棋子颜色enemyTile
    if tile == 'red':
        enemyTile = 'black'
    else:
        enemyTile = 'red'
    #初始一个移动列表,其数值全部为0
    potentialMoves = [0] * Chessboard_width
    for firstMove in range(Chessboard_width):
        #对每一栏进行遍历,将双方中的任一方的移动称为firstMove
        #则另外一方的移动就称为对手,counterMove。
        #这里我们的firstMove为AI,对手为玩家。
        dupeBoard = copy.deepcopy(board)#深复制棋盘 
        #若不是有效移动,则跳出本次循环
        if not isValidMove(dupeBoard, firstMove):
            continue
        #如果是有效移动,则设置相应的格子颜色
        makeMove(dupeBoard, tile, firstMove)
        if isWinner(dupeBoard, tile):
            potentialMoves[firstMove] = 1
            #获胜的棋子自动获得一个很高的数值来表示其获胜的概率
            #数值越大,获胜可能性越大,对手获胜可能性越小。
            break
        else:
            if isBoardFull(dupeBoard):
                #如果dupeBoard中没有空格,无法移动
                potentialMoves[firstMove] = 0
            else:
                #预测对手移动
                for counterMove in range(Chessboard_width):
                    #为了不影响AI的预测棋盘,这里再复制一份
                    dupeBoard2 = copy.deepcopy(dupeBoard)
                    if not isValidMove(dupeBoard2, counterMove):
                        continue
                    makeMove(dupeBoard2,enemyTile,counterMove)
                    #玩家获胜
                    if isWinner(dupeBoard2, enemyTile):
                        potentialMoves[firstMove] = -1
                        break
                    else:
                        #递归调用
                        results = Monte_Carlo(dupeBoard2, tile, AI_LEVEL - 1)
                        potentialMoves[firstMove]+= (sum(results)*1.0 / Chessboard_width) / Chessboard_width
    return potentialMoves

6.3.8AI移动方法的定义

6.3.8.1定义AI棋子自动移动函数AIAutoMoving,该函数接收棋盘和某一列两个参数,方法中首先找到黑色棋盒的位置,利用while循环判断棋子是否在棋盘上方,如果不是则向上移动,直到到达棋盘上方,再根据参数column确定棋子移动到哪一列,移动到指定位置后,调用我们之前定义的棋子动态降落函数Dynamic_landing实现棋子下落

def AIAutoMoving(board, column):
    x = BlackBowls.left #黑色棋盒的左坐标
    y = BlackBowls.top #黑色棋盒的上坐标
    speed = 1.0 #棋子移动速度,可以自定义
    while y > (Y_Height - Chessman_size): #判断从棋子是否在棋盘上方,如果不在则y减小,相当于棋子向上移动
        y -= int(speed)
        speed += 0.5 #棋子的加速度,可以自定义
        drawBoard(board, {'x':x, 'y':y, 'color':'black'})#调用我们之前的绘制棋盘方法,根据y的不断变化不断绘制棋子,形成动态效果
        pygame.display.update()
        FPSCLOCK.tick()
   #当棋子移动到棋盘上方时,则跳出循环
    y = Y_Height - Chessman_size 
    speed = 1.0 #再次设置棋子的移动速度
    while x > (X_Left + column * Chessman_size): #这次我们根据参数column来确定x轴的移动
        x -= int(speed)
        speed += 0.5
        drawBoard(board, {'x':x, 'y':y, 'color':'black'}) #不断绘制,形成动态效果
        pygame.display.update()
        FPSCLOCK.tick()
    #棋子达到棋盘上方且指定列上方时,调用动态降落方法,棋子下落
    Dynamic_landing(board, column, 'black')

6.3.8.2定义获得AI计算后确定落子位置的函数ComputerMove,该函数接收一个棋盘参数,在方法中我们根据传入的棋盘调用前面定义的蒙特卡罗算法来获得一个AI落子到各个棋格时对应的概率值,从概率值中取出最大值,并获得所有最大值所在的列,从这些列中随机选择一个(如果只有一个列那就只能选择它了)作为落子的目标列

def ComputerMove(board):
    #获得每一种落子情况的概率列表
    potentialMoves = Monte_Carlo(board, 'black', AI_LEVEL)
    bestMoves = []
    bestMoveFitness = -1
    #找出概率列表中最大的值,也就是AI越能赢的可能性
    for i in range(len(potentialMoves)):
        if potentialMoves[i]>bestMoveFitness and isValidMove(board,i):
            bestMoveFitness = potentialMoves[i]
    #获得概率为最大值的所有列,存入bestMoves列表中
    for i in range(len(potentialMoves)):
        if potentialMoves[i] == bestMoveFitness and isValidMove(board, i):
            bestMoves.append(i)
    #随机返回一个列作为落子的目标列
    return random.choice(bestMoves)

6.3.9定义玩家操作方法

6.3.9.1定义玩家下棋的方法了

6.3.9.2定义方法PeopleMove,该方法接受棋盘和是否是第一次移动两个参数,pygame提供了event方法用来获得游戏框中的所有事件,在方法中我们在while循环中定义了玩家可能出现的所有操作:点击棋盒、拖动棋子、释放棋子、关闭游戏框。针对每一种情况来绘制棋子,达到动态效果

def PeopleMove(board, isFirstMove):
    draggingToken = False #定义一个Boolean值用于判断棋子是否拖拽
    tokenx, tokeny = None, None
    while True:
        # pygame.event.get()来处理所有的事件
        for event in pygame.event.get():
            if event.type == QUIT: #如果事件是退出游戏
                pygame.quit()#退出pygame
                sys.exit()
            #如果事件类型为鼠标按下,notdraggingToken为True,鼠标点击的位置在RedBowls里面
            elif event.type == MOUSEBUTTONDOWN and not draggingToken and RedBowls.collidepoint(event.pos):
                draggingToken = True #点击事件发生后接下来就可以拖拽了
                tokenx, tokeny = event.pos
            #如果开始拖动了红色棋子
            elif event.type == MOUSEMOTION and draggingToken:
                #更新被拖拽的棋子的位置
                tokenx, tokeny = event.pos
            elif event.type == MOUSEBUTTONUP and draggingToken:
                #如果棋子被拖拽在board的正上方
                if tokeny < Y_Height and tokenx > X_Left and tokenx < Window_width - X_Left:
                    #根据棋子的x坐标确定棋子会落的列(0,1...6)
                    column = int((tokenx - X_Left) / Chessman_size)
                    if isValidMove(board, column):
                        #棋子掉落,显示掉落效果
                        Dynamic_landing(board, column, 'red')
                        #将空格中最下面的格子设为红色
                        board[column][getLowestEmptySpace(board, column)] = 'red'
                        #落入的格子中划红色棋子
                        drawBoard(board)
                        #窗口更新
                        pygame.display.update()
                        return #不带参数的return默认返回None,后面的函数不再执行
                tokenx, tokeny = None, None
                draggingToken = False
        if tokenx != None and tokeny != None:
            #如果拖动了棋子,则显示拖动的棋子,并且通过调整x,y的坐标使拖动时,鼠标始终位于棋子的中心位置。
            drawBoard(board, {'x':tokenx - int(Chessman_size / 2), 'y':tokeny - int(Chessman_size / 2), 'color':'red'})
        else:
            #当为无效移动时,鼠标松开后调用drawBoard,只显示下面的两个棋子,相当于棋子回到到开始拖动的地方
            drawBoard(board)

        if isFirstMove:
            #AI先走,如果玩家是第一次操作则显示提示操作图片
            GameWindow.blit(ARROWIMG, ARROWRECT)
        #刷新页面
        pygame.display.update()
        FPSCLOCK.tick()

6.3.10至此我们整个代码已经基本构建完成,从棋盘构建,棋子移动,动态展示到AI移动,玩家移动,判断输赢等函数的定义,现在我们只差一个main方法去调用程序了

6.3.11创建main方法,调用上面定义的函数开始游戏

6.3.11.1在此之前,我们先定义一个GameStart方法,用来开始游戏,然后再去创建一个main方法,main方法循环调用GameStrat方法,让游戏能够持续运行

6.3.11.2在GameStart方法中我们首先要获得是否是第一次游戏的变量isFirstGame,如果是第一次则AI先手下棋,并且将用户移动中的第一次移动时帮助提示变量showHelp设置为True,然后AI开始下棋,若没有决出胜负则循环值玩家操作,再次判断有无决出胜负,直到有一方赢得胜利,跳出循环打印胜利者图片,如果用户点击退出或者按ESC则关闭pygame,否则返回None回到函数开始重新开始游戏

def GameStart(isFirstGame):
    if isFirstGame: #如果是第一次游戏,AI先手,输出操作提示
        turn = Computer
        showHelp = True
    else:
        if random.randint(0, 1) == 0: #如果不是第一次游戏,随机先手
            turn = Computer
        else:
            turn = People
        showHelp = False #不输出操作提示
    mainBoard = getNewBoard() #获取棋盘
    while True:
        if isBoardFull(mainBoard): #如果棋盘满了则判断平局
            winnerImg = TIEWINNERIMG
            break
        if turn == People: #如果轮到玩家操作
            PeopleMove(mainBoard, showHelp) #玩家移动
            if showHelp:
                showHelp = False
            if isWinner(mainBoard, 'red'): #判断玩家是否获胜
                winnerImg = PeopleWINNERIMG
                break
            turn = Computer #轮到AI操作
        else: #如果轮到AI操作
            column = ComputerMove(mainBoard) #获得移动最优解
            AIAutoMoving(mainBoard, column) #AI自动移动
            makeMove(mainBoard, 'black', column) #确认移动
            if isWinner(mainBoard, 'black'):#判断AI是否胜利
                winnerImg = ComputerWINNERIMG
                break
            turn = People
    #决出胜负后,在棋盘上显示对应的胜利者图片
    while True:
        drawBoard(mainBoard)
        GameWindow.blit(winnerImg, WINNERRECT)
        pygame.display.update()
        FPSCLOCK.tick()
        #判断决出胜负后的事件:1退出2鼠标点击
        for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
                pygame.quit() #退出程序
                sys.exit()
            elif event.type == MOUSEBUTTONUP:
                return #重新回到函数开始,即重新开始游戏

6.3.11.3创建main方法作为程序的入口,第一次进入main方法时,isFirstGame变量设置成True表示显示操作提示图片,main方法进入循环后,也就是非第一次游戏之后,isFirstGame变为False

def main():
    isFirstGame = True #初始化isFirstGame

    while True: #在非退出情况下,保证程序一直运行
        GameStart(isFirstGame) #开始游戏
        isFirstGame = False

6.3.11.4定义程序入口,如果直接运行此脚本,则模块名为main,那么就执行main方法

if __name__ == '__main__':
    main()

6.3.12至此,脚本文件代码编写完毕,现在我们可以利用:wq保存代码文件退出vim编辑器

6.3.13运行程序

6.3.13.1利用python2.7运行脚本文件,等待游戏开始

[zkpk@master ~]$ python2.7 pyChessgame.py 

在这里插入图片描述

图 2

6.3.13.2可以看到游戏框出现,黑子先走,然后出现操作提示

在这里插入图片描述

图 3

6.3.9.13.3玩家可以点击红子拖拽到棋盒上方某一列,松开鼠标按键,棋子自动下落到棋盘中

在这里插入图片描述

图 4

6.3.9.13.4与电脑对弈知道一方分出胜负

在这里插入图片描述

图 5

7、总结

利用游戏实验Pygame库,结合Python基础编程编写棋类游戏脚本,使得玩家能够与AI电脑进行对抗博弈。在本实验中我们运用蒙特卡罗树思想让AI能获得每一步操作结果的概率值,从而选出最优解进行对抗,通过本实验的学习,我们能了解pygame在游戏开发中的应用以及蒙特卡罗搜索树思想。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JTZ001

你的鼓励是我创作的最大动力?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值