打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
python3+tkinter实现的黑白棋,代码完整 100%能运行

今天分享给大家的是采用Python3+tkinter制作而成的小项目——黑白棋

tkinter是Python内置的图形化模块,简单易用,一般的小型UI程序可以快速用它实现,具体的tkinter相关知识王老师会在以后开辟专栏单独讲解

我们先来看看这个黑白棋项目吧

一、项目演示

二、代码

完整代码如下,用到的素材(图片等)下载地址为:www.itprojects.cn/detail.html…

from tkinter import *from tkinter.messagebox import *import randomroot = Tk('黑白棋')root.title("黑白棋(更多项目实例请访问www.itprojects.cn)")# 加载图片imgs = [PhotoImage(file='black.png'), PhotoImage(file='white.png'), PhotoImage(file='board.png'), PhotoImage(file='info2.png')]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 boarddef 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 tilesToFlipdef isOnBoard(x, y):    """是否出界"""    return x >= 0 and x <= 7 and y >= 0 and y <= 7def 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 validMovesdef 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'def makeMove(board, tile, xstart, ystart):    """将一个tile棋子放到(xstart, ystart)"""    tilesToFlip = isValidMove(board, tile, xstart, ystart)    if tilesToFlip == False:        return False    board[xstart][ystart] = tile    for x, y in tilesToFlip:  # tilesToFlip是需要翻转的棋子列表        board[x][y] = tile  # 翻转棋子    return Truedef getBoardCopy(board):    """复制棋盘"""    dupeBoard = getNewBoard()    for x in range(8):        for y in range(8):            dupeBoard[x][y] = board[x][y]    return dupeBoarddef 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)def getComputerMove(board, computerTile):    """电脑走法,AI"""    # 获取所以合法走法    possibleMoves = getValidMoves(board, computerTile)    if not possibleMoves:  # 如果没有合法走法        print("电脑没有合法走法")        return None    # 打乱所有合法走法    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 bestMovedef isGameOver(board):    """是否游戏结束"""    for x in range(8):        for y in range(8):            if board[x][y] == 'none':                return False    return Truedef drawQiPan():    """画棋盘"""    img1 = imgs[2]    cv.create_image((360, 360), image=img1)    cv.pack()def callback(event):    """走棋"""    global turn    # print ("clicked at", event.x, event.y,turn)    # x=(event.x)//40  #换算棋盘坐标    # y=(event.y)//40    if (gameOver == False and turn == 'computer'):  # 没轮到玩家走棋        return    col = int((event.x - 40) / 80)  # 换算棋盘坐标    row = int((event.y - 40) / 80)    if mainBoard[col][row] != "none":        showinfo(title="提示", message="已有棋子")    if makeMove(mainBoard, playerTile, col, row) == True:  # 将一个玩家棋子放到(col, row)        if getValidMoves(mainBoard, computerTile) != []:            turn = 'computer'    # 电脑走棋    if getComputerMove(mainBoard, computerTile) == None:        turn = 'player'        showinfo(title="玩家继续", message="玩家继续")    else:        computerGo()        # 重画所有的棋子和棋盘    drawAll()    drawCanGo()    if isGameOver(mainBoard):  # 游戏结束,显示双方棋子数量        scorePlayer = getScoreOfBoard(mainBoard)[playerTile]        scoreComputer = getScoreOfBoard(mainBoard)[computerTile]        outputStr = gameoverStr + "玩家:" + str(scorePlayer) + ":" + "电脑:" + str(scoreComputer)        showinfo(title="游戏结束提示", message=outputStr)def computerGo():    """电脑走棋"""    global turn    if (gameOver == False and turn == 'computer'):        x, y = getComputerMove(mainBoard, computerTile)  # 电脑AI走法        makeMove(mainBoard, computerTile, x, y)        savex, savey = x, y        # 玩家没有可行的走法了,则电脑继续,否则切换到玩家走        if getValidMoves(mainBoard, playerTile) != []:            turn = 'player'        else:            if getValidMoves(mainBoard, computerTile) != []:                showinfo(title="电脑继续", message="电脑继续")                computerGo()def drawAll():    """重画所有的棋子和棋盘"""    drawQiPan()    for x in range(8):        for y in range(8):            if mainBoard[x][y] == 'black':                cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[0])                cv.pack()            elif mainBoard[x][y] == 'white':                cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[1])                cv.pack()def drawCanGo():    """画提示位置"""    list1 = getValidMoves(mainBoard, playerTile)    for m in list1:        x = m[0]        y = m[1]        cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[3])        cv.pack()if __name__ == '__main__':    # 初始化    gameOver = False    gameoverStr = 'Game Over Score '    mainBoard = getNewBoard()    resetBoard(mainBoard)    turn = whoGoesFirst()    showinfo(title="游戏开始提示", message=turn + "先走!")    print(turn, "先走!")    if turn == 'player':        playerTile = 'black'        computerTile = 'white'    else:        playerTile = 'white'        computerTile = 'black'        computerGo()    # 设置窗口    cv = Canvas(root, bg='green', width=720, height=780)    # 重画所有的棋子和棋盘    drawAll()    drawCanGo()    cv.bind("<Button-1>", callback)    cv.pack()    root.mainloop()

本文首发于python黑洞网,博客园同步跟新



本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
envi二次开发中文件的读取和存储
AStar 算法简述(unity c#代码段)
ggplot2都有哪些使用不多但是却异常强大的图层函数
用程序来解数独
JS效果之图片切割 规则运动
OpenGL11
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服