python+pyGame 黑白棋游戏

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/guzhou_diaoke/article/details/8201542

注:以下程序为根据相应的字符界面程序改编而来,写的不好,若有好的建议,望留言告知。而若能帮助一二访客,幸甚!


继续学习python。

为了学习起来更有趣,继续以游戏的方式来学习。

注:前几天学习了Invent Your Own Computer Games with Python 一书中的一些游戏例子程序,有一个字符界面的黑白棋程序,为了更便于操作和美观,我决定把它改为图形界面的程序,但多数代码修改或借用的原始程序。

1.绘制棋盘

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

BACKGROUNDCOLOR = (255, 255, 255)
FPS = 40


# 退出
def terminate():
    pygame.quit()
    sys.exit()


# 初始化
pygame.init()
mainClock = pygame.time.Clock()

# 加载图片
boardImage = pygame.image.load('board.png')
boardRect = boardImage.get_rect()
blackImage = pygame.image.load('black.png')
blackRect = blackImage.get_rect()
whiteImage = pygame.image.load('white.png')
whiteRect = whiteImage.get_rect()


# 设置窗口
windowSurface = pygame.display.set_mode((boardRect.width, boardRect.height))
pygame.display.set_caption('黑白棋')


# 游戏主循环
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            terminate()

    windowSurface.fill(BACKGROUNDCOLOR)
    windowSurface.blit(boardImage, boardRect, boardRect)
    
    pygame.display.update()
    mainClock.tick(FPS)



2.绘制棋子

1)黑白棋的规则,开局时先放置上黑白各两个棋子在中间

2)用一个8x8列表保存棋子

CELLWIDTH = 50
CELLHEIGHT = 50
PIECEWIDTH = 47
PIECEHEIGHT = 47
BOARDX = 35
BOARDY = 35

# 重置棋盘
def resetBoard(board):
    for x in range(8):
        for y in range(8):
            board[x][y] = 'none'

    # Starting pieces:
    board[3][3] = 'black'
    board[3][4] = 'white'
    board[4][3] = 'white'
    board[4][4] = 'black'


# 开局时建立新棋盘
def getNewBoard():
    board = []
    for i in range(8):
        board.append(['none'] * 8)

    return board

mainBoard = getNewBoard()
resetBoard(mainBoard)

for x in range(8):
        for y in range(8):
            rectDst = pygame.Rect(BOARDX+x*CELLWIDTH+2, BOARDY+y*CELLHEIGHT+2, PIECEWIDTH, PIECEHEIGHT)
            if mainBoard[x][y] == 'black':
                windowSurface.blit(blackImage, rectDst, blackRect)
            elif mainBoard[x][y] == 'white':
                windowSurface.blit(whiteImage, rectDst, whiteRect)



3.鼠标事件

1)鼠标操纵

2)轮流走棋

# 谁先走
def whoGoesFirst():
    if random.randint(0, 1) == 0:
        return 'computer'
    else:
        return 'player'

turn = whoGoesFirst()
if turn == 'player':
    playerTile = 'black'
    computerTile = 'white'
else:
    playerTile = 'white'
    computerTile = 'black'

for event in pygame.event.get():
        if event.type == QUIT:
            terminate()
        if turn == 'player' and event.type == MOUSEBUTTONDOWN and event.button == 1:
            x, y = pygame.mouse.get_pos()
            col = int((x-BOARDX)/CELLWIDTH)
            row = int((y-BOARDY)/CELLHEIGHT)
            if makeMove(mainBoard, playerTile, col, row) == True:
                if getValidMoves(mainBoard, computerTile) != []:
                    turn = 'computer'

    windowSurface.fill(BACKGROUNDCOLOR)
    windowSurface.blit(boardImage, boardRect, boardRect)

    if (turn == 'computer'):
        x, y = getComputerMove(mainBoard, computerTile)
        makeMove(mainBoard, computerTile, x, y)
        savex, savey = x, y

        # 玩家没有可行的走法了
        if getValidMoves(mainBoard, playerTile) != []:
            turn = 'player'

    windowSurface.fill(BACKGROUNDCOLOR)
    windowSurface.blit(boardImage, boardRect, boardRect)


4.游戏规则

1)是否允许落子

2)落子后的翻转

3)电脑AI走法


前几天不会玩时总被电脑虐,如今略微会玩了,图为我执黑,大胜电脑AI,看来这个AI算法并不咋地啊……


完整程序:

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

BACKGROUNDCOLOR = (255, 255, 255)
BLACK = (255, 255, 255)
BLUE = (0, 0, 255)
CELLWIDTH = 50
CELLHEIGHT = 50
PIECEWIDTH = 47
PIECEHEIGHT = 47
BOARDX = 35
BOARDY = 35
FPS = 40

# 退出
def terminate():
    pygame.quit()
    sys.exit()


# 重置棋盘
def resetBoard(board):
    for x in range(8):
        for y in range(8):
            board[x][y] = 'none'

    # Starting pieces:
    board[3][3] = 'black'
    board[3][4] = 'white'
    board[4][3] = 'white'
    board[4][4] = 'black'


# 开局时建立新棋盘
def getNewBoard():
    board = []
    for i in range(8):
        board.append(['none'] * 8)

    return board


# 是否是合法走法
def isValidMove(board, tile, xstart, ystart):
    # 如果该位置已经有棋子或者出界了,返回False
    if not isOnBoard(xstart, ystart) or board[xstart][ystart] != 'none':
        return False

    # 临时将tile 放到指定的位置
    board[xstart][ystart] = tile

    if tile == 'black':
        otherTile = 'white'
    else:
        otherTile = 'black'

    # 要被翻转的棋子
    tilesToFlip = []
    for xdirection, ydirection in [ [0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1] ]:
        x, y = xstart, ystart
        x += xdirection
        y += ydirection
        if isOnBoard(x, y) and board[x][y] == otherTile:
            x += xdirection
            y += ydirection
            if not isOnBoard(x, y):
                continue
            # 一直走到出界或不是对方棋子的位置
            while board[x][y] == otherTile:
                x += xdirection
                y += ydirection
                if not isOnBoard(x, y):
                    break
            # 出界了,则没有棋子要翻转OXXXXX
            if not isOnBoard(x, y):
                continue
            # 是自己的棋子OXXXXXXO
            if board[x][y] == tile:
                while True:
                    x -= xdirection
                    y -= ydirection
                    # 回到了起点则结束
                    if x == xstart and y == ystart:
                        break
                    # 需要翻转的棋子
                    tilesToFlip.append([x, y])

    # 将前面临时放上的棋子去掉,即还原棋盘
    board[xstart][ystart] = 'none' # restore the empty space

    # 没有要被翻转的棋子,则走法非法。翻转棋的规则。
    if len(tilesToFlip) == 0:   # If no tiles were flipped, this is not a valid move.
        return False
    return tilesToFlip


# 是否出界
def isOnBoard(x, y):
    return x >= 0 and x <= 7 and y >= 0 and y <=7


# 获取可落子的位置
def getValidMoves(board, tile):
    validMoves = []

    for x in range(8):
        for y in range(8):
            if isValidMove(board, tile, x, y) != False:
                validMoves.append([x, y])
    return validMoves


# 获取棋盘上黑白双方的棋子数
def getScoreOfBoard(board):
    xscore = 0
    oscore = 0
    for x in range(8):
        for y in range(8):
            if board[x][y] == 'black':
                xscore += 1
            if board[x][y] == 'white':
                oscore += 1
    return {'black':xscore, 'white':oscore}


# 谁先走
def whoGoesFirst():
    if random.randint(0, 1) == 0:
        return 'computer'
    else:
        return 'player'


# 将一个tile棋子放到(xstart, ystart)
def makeMove(board, tile, xstart, ystart):
    tilesToFlip = isValidMove(board, tile, xstart, ystart)

    if tilesToFlip == False:
        return False

    board[xstart][ystart] = tile
    for x, y in tilesToFlip:
        board[x][y] = tile
    return True

# 复制棋盘
def getBoardCopy(board):
    dupeBoard = getNewBoard()

    for x in range(8):
        for y in range(8):
            dupeBoard[x][y] = board[x][y]

    return dupeBoard

# 是否在角上
def isOnCorner(x, y):
    return (x == 0 and y == 0) or (x == 7 and y == 0) or (x == 0 and y == 7) or (x == 7 and y == 7)


# 电脑走法,AI
def getComputerMove(board, computerTile):
    # 获取所以合法走法
    possibleMoves = getValidMoves(board, computerTile)

    # 打乱所有合法走法
    random.shuffle(possibleMoves)

    # [x, y]在角上,则优先走,因为角上的不会被再次翻转
    for x, y in possibleMoves:
        if isOnCorner(x, y):
            return [x, y]

    bestScore = -1
    for x, y in possibleMoves:
        dupeBoard = getBoardCopy(board)
        makeMove(dupeBoard, computerTile, x, y)
        # 按照分数选择走法,优先选择翻转后分数最多的走法
        score = getScoreOfBoard(dupeBoard)[computerTile]
        if score > bestScore:
            bestMove = [x, y]
            bestScore = score
    return bestMove

# 是否游戏结束
def isGameOver(board):
    for x in range(8):
        for y in range(8):
            if board[x][y] == 'none':
                return False
    return True


# 初始化
pygame.init()
mainClock = pygame.time.Clock()

# 加载图片
boardImage = pygame.image.load('board.png')
boardRect = boardImage.get_rect()
blackImage = pygame.image.load('black.png')
blackRect = blackImage.get_rect()
whiteImage = pygame.image.load('white.png')
whiteRect = whiteImage.get_rect()

basicFont = pygame.font.SysFont(None, 48)
gameoverStr = 'Game Over Score '

mainBoard = getNewBoard()
resetBoard(mainBoard)

turn = whoGoesFirst()
if turn == 'player':
    playerTile = 'black'
    computerTile = 'white'
else:
    playerTile = 'white'
    computerTile = 'black'

print(turn) 

# 设置窗口
windowSurface = pygame.display.set_mode((boardRect.width, boardRect.height))
pygame.display.set_caption('黑白棋')


gameOver = False


# 游戏主循环
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            terminate()
        if gameOver == False and turn == 'player' and event.type == MOUSEBUTTONDOWN and event.button == 1:
            x, y = pygame.mouse.get_pos()
            col = int((x-BOARDX)/CELLWIDTH)
            row = int((y-BOARDY)/CELLHEIGHT)
            if makeMove(mainBoard, playerTile, col, row) == True:
                if getValidMoves(mainBoard, computerTile) != []:
                    turn = 'computer'

    windowSurface.fill(BACKGROUNDCOLOR)
    windowSurface.blit(boardImage, boardRect, boardRect)

    if (gameOver == False and turn == 'computer'):
        x, y = getComputerMove(mainBoard, computerTile)
        makeMove(mainBoard, computerTile, x, y)
        savex, savey = x, y

        # 玩家没有可行的走法了
        if getValidMoves(mainBoard, playerTile) != []:
            turn = 'player'

    windowSurface.fill(BACKGROUNDCOLOR)
    windowSurface.blit(boardImage, boardRect, boardRect)
    
    for x in range(8):
        for y in range(8):
            rectDst = pygame.Rect(BOARDX+x*CELLWIDTH+2, BOARDY+y*CELLHEIGHT+2, PIECEWIDTH, PIECEHEIGHT)
            if mainBoard[x][y] == 'black':
                windowSurface.blit(blackImage, rectDst, blackRect)
            elif mainBoard[x][y] == 'white':
                windowSurface.blit(whiteImage, rectDst, whiteRect)

    if isGameOver(mainBoard):
        scorePlayer = getScoreOfBoard(mainBoard)[playerTile]
        scoreComputer = getScoreOfBoard(mainBoard)[computerTile]
        outputStr = gameoverStr + str(scorePlayer) + ":" + str(scoreComputer)
        text = basicFont.render(outputStr, True, BLACK, BLUE)
        textRect = text.get_rect()
        textRect.centerx = windowSurface.get_rect().centerx
        textRect.centery = windowSurface.get_rect().centery
        windowSurface.blit(text, textRect)
    
    pygame.display.update()
    mainClock.tick(FPS)


展开阅读全文

没有更多推荐了,返回首页