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黑洞网,博客园同步跟新
赞 (0)