python项目阅读记录——四子棋

python项目阅读记录——四子棋,第1张

概述项目代码阅读记录这个栏目将会总结我在学习过程中阅读过的项目代码的总结和记录。文章目录项目代码阅读记录一、全局变量二、主函数main二、runGame()三、余下函数1.getNewBoard()2.defisBoardFull(board)3.defgetHumanMove(board,isFirstMove):4.defisValidMove( 项目代码阅读记录

这个栏目将会总结我在学习过程中阅读过的项目代码的总结和记录。


文章目录项目代码阅读记录一、全局变量二、主函数main二、runGame()三、余下函数1. getNewBoard()2.def isBoardFull(board)3.def getHumanMove(board, isFirstMove):4.def isValidMove(board, column)5.def animateDroppingToken(board, column, color)6.def getLowestEmptySpace(board, column)7.def isWinner(board, tile)8、def getComputerMove(board)9.def getPotentialMoves(board, tile, depth)10.def animateComputerMoving(board, column)11.def drawBoard(board, extraToken=None)12.def makeMove(board, player, column)


一、全局变量
BOARDWIDTH = 7  # 棋子盘的宽度栏数BOARDHEIGHT = 6 # 棋子盘的高度栏数assert BOARDWIDTH >= 4 and BOARDHEIGHT >= 4, 'Board must be at least 4x4.'#if not Expression:#   raise AssertionError(arguments)#assert语句可以等价为此#python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。#可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。DIFFICulTY = 2 # 难度系数,计算机能够考虑的移动级别               #这里2表示,考虑对手走棋的7种可能性及如何应对对手的7种走法SPACESIZE = 50 # 棋子的大小FPS = 30 # 屏幕的更新频率,即30/s#所谓的FPS其实就是指游戏画面刷新帧频(游戏画面刷新频率),也就是说游戏中每秒钟能够绘制多少次图像。# 我们看到的动画其实就是一系列的图片快速的刷新产生的,每秒钟帧数越多,所显示的动作就会越流畅WINDOWWIDTH = 640  # 游戏屏幕的宽度像素WINDOWHEIGHT = 480 # 游戏屏幕的高度像素Xmargin = int((WINDOWWIDTH - BOARDWIDTH * SPACESIZE) / 2)#X边缘坐标量,即格子栏的最左边Ymargin = int((WINDOWHEIGHT - BOARDHEIGHT * SPACESIZE) / 2)#Y边缘坐标量,即格子栏的最上边BRIGHTBLUE = (0, 50, 255)#蓝色WHITE = (255, 255, 255)#白色BGcolor = BRIGHTBLUETEXTcolor = WHITERED = 'red'BLACK = 'black'EMPTY = NoneHUMAN = 'human'COmpuTER = 'computer'

在这里定义了一些游戏框架的基本变量,如棋子盘的参数,棋子的参数,边缘坐标参数,颜色,游戏的难度等等…

二、主函数main
def main():    global FPSCLOCK, disPLAYSURF, REDPILERECT, BLACKPILERECT, REDTOKENimg    global BLACKTOKENimg, BOARDimg, ARROWimg, ARROWRECT, HUMANWINNERimg    global COmpuTERWINNERimg, WINNERRECT, TIEWINNERimg    pygame.init()    FPSCLOCK = pygame.time.Clock()    #初始化游戏窗口,创建一个对象来帮助跟踪时间    disPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))    #游戏窗口标题, 初始化一个准备显示的窗口或屏幕    pygame.display.set_caption('Four in a Row')    #设置窗口说明文字    REDPILERECT = pygame.Rect(int(SPACESIZE / 2), WINDOWHEIGHT - int(3 * SPACESIZE / 2), SPACESIZE, SPACESIZE)    #创建窗口左下和右下角的棋子     #Rect 是用于存储矩形坐标的 Pygame 对象。    BLACKPILERECT = pygame.Rect(WINDOWWIDTH - int(3 * SPACESIZE / 2), WINDOWHEIGHT - int(3 * SPACESIZE / 2), SPACESIZE, SPACESIZE)    #载入红色棋子图片    REDTOKENimg = pygame.image.load('images/4rowred.png')        #将红色棋子图片缩放为SPACESIZE    #pygame.transform.smoothscale - 平滑地将曲面缩放到任意大小    REDTOKENimg = pygame.transform.smoothscale(REDTOKENimg, (SPACESIZE, SPACESIZE))    #黑色棋子    BLACKTOKENimg = pygame.image.load('images/4rowblack.png')    #将黑色棋子图片缩放为SPACESIZE    BLACKTOKENimg = pygame.transform.smoothscale(BLACKTOKENimg, (SPACESIZE, SPACESIZE))    #载入棋子面板图片    BOARDimg = pygame.image.load('images/4rowboard.png')    #将棋子面板图片缩放为SPACESIZE    BOARDimg = pygame.transform.smoothscale(BOARDimg, (SPACESIZE, SPACESIZE))    #载入人胜利时图片    HUMANWINNERimg = pygame.image.load('images/4rowhumanwinner.png')    #载入AI胜利时图片    COmpuTERWINNERimg = pygame.image.load('images/4rowcomputerwinner.png')    #载入平局图片    TIEWINNERimg = pygame.image.load('images/4rowtIE.png')    #返回Rect实例    WINNERRECT = HUMANWINNERimg.get_rect()    #游戏窗口中间位置坐标    WINNERRECT.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2))    #载入 *** 作提示图片    ARROWimg = pygame.image.load('images/4rowarrow.png')    #返回Rect实例    ARROWRECT = ARROWimg.get_rect()    # *** 作提示的左位置    ARROWRECT.left = REDPILERECT.right + 10     #将 *** 作提示与下方红色棋子实例在纵向对齐    ARROWRECT.centery = REDPILERECT.centery     isFirstGame = True     while True:        runGame(isFirstGame)        isFirstGame = False

在主函数中,大部分的代码都是在描述设置一些实体信息,例如载入图片,设置Rect对象等等。在最后设置了一个isFirstGame,根据是否是第一局游戏的判断对接下来的游戏步骤产生影响,运行rungame(),由此可见,rungame()函数才是游戏得以运行的实体程序。

二、runGame()
def runGame(isFirstGame):    if isFirstGame:        turn = COmpuTER #先手        showHelp = True #提示图片    else:        if random.randint(0, 1) == 0:        #在零和一之间随机选取一个数字            turn = COmpuTER        #若随机数是零则电脑是先手        else:            turn = HUMAN        showHelp = False        #第二局不展示帮助    mainBoard = getNewBoard()    while True:        if isBoardFull(mainBoard):            winnerimg = TIEWINNERimg            break         if turn == HUMAN:            getHumanMove(mainBoard, showHelp)            if showHelp:                showHelp = False            if isWinner(mainBoard, RED):                winnerimg = HUMANWINNERimg                break            turn = COmpuTER         else:            column = getComputerMove(mainBoard)            animateComputerMoving(mainBoard, column)            makeMove(mainBoard, BLACK, column)            if isWinner(mainBoard, BLACK):                winnerimg = COmpuTERWINNERimg                break            turn = HUMAN     while True:        drawBoard(mainBoard)        disPLAYSURF.blit(winnerimg, WINNERRECT)        pygame.display.update()        FPSCLOCK.tick()        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

三、余下函数1. getNewBoard()

产生值为空的BOARDHEIGHT*BOARDWIDTH的矩阵

def getNewBoard():    board = []    for x in range(BOARDWIDTH):        board.append([EMPTY] * BOARDHEIGHT)    return board #返回board列表,其值为BOARDHEIGHT数量的None    #产生值为空的BOARDHEIGHT*BOARDWIDTH的矩阵
2.def isBoardFull(board)

逐个检查矩阵的每一个以便于判断矩阵有没有放满

def isBoardFull(board):    for x in range(BOARDWIDTH):        for y in range(BOARDHEIGHT):            if board[x][y] == EMPTY:                return False    return True    #逐个检查矩阵的每一个以便于判断矩阵有没有放满
3.def getHumanMove(board, isFirstMove):

判断人对棋子所做的事件并作出一系列反应。

def getHumanMove(board, isFirstMove):    draggingToken = False #拖动    tokenx, tokeny = None, None    while True:        # pygame.event.get()来处理所有的事件        for event in pygame.event.get():             #停止,退出            if event.type == QUIT:                pygame.quit()                sys.exit()            #如果事件类型为鼠标按下,notdraggingToken为True,鼠标点击的位置在REDPILERECT里面            elif event.type == MOUSEbuttonDOWN and not draggingToken and REDPILERECT.collIDepoint(event.pos):            #evebt.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 < Ymargin and tokenx > Xmargin and tokenx < WINDOWWIDTH - Xmargin:                    #根据棋子的x坐标确定棋子会落的列(0,1...6)                    column = int((tokenx - Xmargin) / SPACESIZE)                    if isValIDMove(board, column):                        #棋子掉落,显示掉落效果                        animateDropPingToken(board, column, RED)                        #将空格中最下面的格子设为红色                        board[column][getLowestemptySpace(board, column)] = RED                        #落入的格子中划红色棋子                        drawBoard(board)                        #窗口更新                        pygame.display.update()                        return                tokenx, tokeny = None, None                draggingToken = False        if tokenx != None and tokeny != None:            #如果拖动了棋子,则显示拖动的棋子,并且通过调整x,y的坐标使拖动时,鼠标始终位于棋子的中心位置。            drawBoard(board, {'x':tokenx - int(SPACESIZE / 2), 'y':tokeny - int(SPACESIZE / 2), 'color':RED})        else:            #当为无效移动时,鼠标松开后,因为此时board中所有格子的值均为none            #调用drawBoard时,进行的 *** 作是显示下面的两个棋子,相当于棋子回到到开始拖动的地方            drawBoard(board)        if isFirstMove:            #AI先走,显示提示 *** 作图片            disPLAYSURF.blit(ARROWimg, ARROWRECT)        pygame.display.update()        FPSCLOCK.tick()
4.def isValIDMove(board, column)

判断此步的移动是否是有效的。

def isValIDMove(board, column):    if column < 0 or column >= (BOARDWIDTH) or board[column][0] != EMPTY:        return False    return True
5.def animateDropPingToken(board, column, color)

显示掉落的动画。

def animateDropPingToken(board, column, color):    x = Xmargin + column * SPACESIZE #定位掉落位置的坐标,此时默认为第n列最下面    y = Ymargin - SPACESIZE    dropSpeed = 1.0#棋子降落的速度    lowestemptySpace = getLowestemptySpace(board, column)#获得此时最低的空位置    while True:        y += int(dropSpeed)#y的坐标以dropSpeed叠加        dropSpeed += 0.5#dropSpeed也在加速,即棋子下落的加速度为0.5        #判断到达最下面的空格        if int((y - Ymargin) / SPACESIZE) >= lowestemptySpace:            return        #y不断变化,不断绘制红色棋子,形成不断降落的效果        drawBoard(board, {'x':x, 'y':y, 'color':color})        pygame.display.update()        FPSCLOCK.tick()
6.def getLowestemptySpace(board, column)

循环查找最低的空格子。

def getLowestemptySpace(board, column):    for y in range(BOARDHEIGHT-1, -1, -1):        if board[column][y] == EMPTY:            return y    return -1
7.def isWinner(board, tile)

暴力扫描棋盘中的棋子判断是否是四种获胜方法的其中一种。

def isWinner(board, tile):    for x in range(BOARDWIDTH - 3):        for y in range(BOARDHEIGHT):            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(BOARDWIDTH):        for y in range(BOARDHEIGHT - 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(BOARDWIDTH - 3):        for y in range(3, BOARDHEIGHT):            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(BOARDWIDTH - 3):        for y in range(BOARDHEIGHT - 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
8、def getComputerMove(board)

获取电脑的移动。

def getComputerMove(board):    potentialMoves = getpotentialMoves(board, BLACK, DIFFICulTY)                                   bestMoves = []    bestMovefitness = -BOARDWIDTH    for i in range(len(potentialMoves)):        if potentialMoves[i]>bestMovefitness and isValIDMove(board,i):            bestMovefitness = potentialMoves[i]                                                         for i in range(len(potentialMoves)):                if potentialMoves[i] == bestMovefitness and isValIDMove(board, i):            bestMoves.append(i)       return random.choice(bestMoves)
9.def getpotentialMoves(board, tile, depth)

分析对手潜在的移动轨迹。

def getpotentialMoves(board, tile, depth):    if depth == 0 or isBoardFull(board):        return [0] * BOARDWIDTH    #确定对手棋子颜色    if tile == RED:        enemyTile = BLACK    else:        enemyTile = RED    #初始一个潜在的移动列表,其数值全部为0    potentialMoves = [0] * BOARDWIDTH    for firstMove in range(BOARDWIDTH):        #对每一栏进行遍历,将双方中的任一方的移动称为firstMove        #则另外一方的移动就称为对手,counterMove。        #这里我们的firstMove为AI,对手为玩家。        dupeBoard = copy.deepcopy(board)#可换成回溯的方式,那样就不用每次都深拷贝了        #这里用深复制是为了让board和dupeBoard不互相影响        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(BOARDWIDTH):                    #考虑对手移动                    dupeBoard2 = copy.deepcopy(dupeBoard)                    if not isValIDMove(dupeBoard2, counterMove):                        continue                    makeMove(dupeBoard2, enemyTile, counterMove)                    #玩家获胜                    if isWinner(dupeBoard2, enemyTile):                        potentialMoves[firstMove] = -1                        break                    else:                        #递归调用                        results = getpotentialMoves(dupeBoard2, tile, depth - 1)                        potentialMoves[firstMove] += (sum(results)*1.0 / BOARDWIDTH) / BOARDWIDTH #求适应度fitness    return potentialMoves
10.def animateComputerMoving(board, column)
def animateComputerMoving(board, column):    x = BLACKPILERECT.left    y = BLACKPILERECT.top    speed = 1.0    while y > (Ymargin - SPACESIZE):        y -= int(speed)        speed += 0.5        drawBoard(board, {'x':x, 'y':y, 'color':BLACK})        pygame.display.update()        FPSCLOCK.tick()    y = Ymargin - SPACESIZE    speed = 1.0    while x > (Xmargin + column * SPACESIZE):        x -= int(speed)        speed += 0.5        drawBoard(board, {'x':x, 'y':y, 'color':BLACK})        pygame.display.update()        FPSCLOCK.tick()    animateDropPingToken(board, column, BLACK)
11.def drawBoard(board, extraToken=None)
def drawBoard(board, extraToken=None):    #disPLAYSURF 是我们的界面,在初始化变量模块中有定义    disPLAYSURF.fill(BGcolor)#将游戏窗口背景色填充为蓝色    spaceRect = pygame.Rect(0, 0, SPACESIZE, SPACESIZE)#创建Rect实例    for x in range(BOARDWIDTH):        #确定每一列中每一行中的格子的左上角的位置坐标        for y in range(BOARDHEIGHT):            spaceRect.topleft = (Xmargin + (x * SPACESIZE), Ymargin + (y * SPACESIZE))            #x =0,y =0时,即第一列第一行的格子。            if board[x][y] == RED:#如果格子值为红色                #则在在游戏窗口的spaceRect中画红色棋子                disPLAYSURF.blit(REDTOKENimg, spaceRect)            elif board[x][y] == BLACK: #否则画黑色棋子                disPLAYSURF.blit(BLACKTOKENimg, spaceRect)    # extraToken 是包含了位置信息和颜色信息的变量    # 用来显示指定的棋子    if extraToken != None:        if extraToken['color'] == RED:            disPLAYSURF.blit(REDTOKENimg,(extraToken['x'],            extraToken['y'], SPACESIZE, SPACESIZE))        elif extraToken['color'] == BLACK:            disPLAYSURF.blit(BLACKTOKENimg, (extraToken['x'], extraToken['y'], SPACESIZE, SPACESIZE))    # 画棋子面板    for x in range(BOARDWIDTH):        for y in range(BOARDHEIGHT):            spaceRect.topleft = (Xmargin + (x * SPACESIZE), Ymargin + (y * SPACESIZE))            disPLAYSURF.blit(BOARDimg, spaceRect)    # 画游戏窗口中左下角和右下角的棋子    disPLAYSURF.blit(REDTOKENimg, REDPILERECT) # 左边的红色棋子    disPLAYSURF.blit(BLACKTOKENimg, BLACKPILERECT) # 右边的黑色棋子
12.def makeMove(board, player, column)

移动。

def makeMove(board, player, column):    lowest = getLowestemptySpace(board, column)    if lowest != -1:        board[column][lowest] = player

望给予建议并指正。 总结

以上是内存溢出为你收集整理的python项目阅读记录——四子棋全部内容,希望文章能够帮你解决python项目阅读记录——四子棋所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1188726.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存