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


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

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

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

    一、项目演示

    二、代码

    完整代码如下,用到的素材(图片等)下载地址为:https://www.itprojects.cn/web/material/details.html?id=15

      1 from tkinter import *
      2 from tkinter.messagebox import *
      3 import random
      4 
      5 root = Tk('黑白棋')
      6 root.title("黑白棋(更多项目实例请访问www.itprojects.cn)")
      7 # 加载图片
      8 imgs = [PhotoImage(file='black.png'), PhotoImage(file='white.png'), PhotoImage(file='board.png'), PhotoImage(file='info2.png')]
      9 
     10 
     11 def resetBoard(board):
     12     """重置棋盘"""
     13     for x in range(8):
     14         for y in range(8):
     15             board[x][y] = 'none'
     16     # Starting pieces:
     17     board[3][3] = 'black'
     18     board[3][4] = 'white'
     19     board[4][3] = 'white'
     20     board[4][4] = 'black'
     21 
     22 
     23 def getNewBoard():
     24     """开局时建立新棋盘"""
     25     board = []
     26     for i in range(8):
     27         board.append(['none'] * 8)
     28     return board
     29 
     30 
     31 def isValidMove(board, tile, xstart, ystart):
     32     """是否是合法走法,如果合法返回需要翻转的棋子列表"""
     33     # 如果该位置已经有棋子或者出界了,返回False
     34     if not isOnBoard(xstart, ystart) or board[xstart][ystart] != 'none':
     35         return False
     36     # 临时将tile 放到指定的位置
     37     board[xstart][ystart] = tile
     38     if tile == 'black':
     39         otherTile = 'white'
     40     else:
     41         otherTile = 'black'
     42     # 要被翻转的棋子
     43     tilesToFlip = []
     44     for xdirection, ydirection in [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]:
     45         x, y = xstart, ystart
     46         x += xdirection
     47         y += ydirection
     48         if isOnBoard(x, y) and board[x][y] == otherTile:
     49             x += xdirection
     50             y += ydirection
     51             if not isOnBoard(x, y):
     52                 continue
     53             # 一直走到出界或不是对方棋子的位置
     54             while board[x][y] == otherTile:
     55                 x += xdirection
     56                 y += ydirection
     57                 if not isOnBoard(x, y):
     58                     break
     59             # 出界了,则没有棋子要翻转OXXXXX
     60             if not isOnBoard(x, y):
     61                 continue
     62             # 是自己的棋子OXXXXXXO
     63             if board[x][y] == tile:
     64                 while True:
     65                     x -= xdirection
     66                     y -= ydirection
     67                     # 回到了起点则结束
     68                     if x == xstart and y == ystart:
     69                         break
     70                     # 需要翻转的棋子
     71                     tilesToFlip.append([x, y])
     72     # 将前面临时放上的棋子去掉,即还原棋盘
     73     board[xstart][ystart] = 'none'  # restore the empty space
     74     # 没有要被翻转的棋子,则走法非法。翻转棋的规则。
     75     if len(tilesToFlip) == 0:  # If no tiles were flipped, this is not a valid move.
     76         return False
     77     return tilesToFlip
     78 
     79 
     80 def isOnBoard(x, y):
     81     """是否出界"""
     82     return x >= 0 and x <= 7 and y >= 0 and y <= 7
     83 
     84 
     85 def getValidMoves(board, tile):
     86     """获取可落子的位置"""
     87     validMoves = []
     88     for x in range(8):
     89         for y in range(8):
     90             if isValidMove(board, tile, x, y) != False:
     91                 validMoves.append([x, y])
     92     return validMoves
     93 
     94 
     95 def getScoreOfBoard(board):
     96     """获取棋盘上黑白双方的棋子数"""
     97     xscore = 0
     98     oscore = 0
     99     for x in range(8):
    100         for y in range(8):
    101             if board[x][y] == 'black':
    102                 xscore += 1
    103             if board[x][y] == 'white':
    104                 oscore += 1
    105     return {'black': xscore, 'white': oscore}
    106 
    107 
    108 def whoGoesFirst():
    109     """决定谁先走"""
    110     if random.randint(0, 1) == 0:
    111         return 'computer'
    112     else:
    113         return 'player'
    114 
    115 
    116 def makeMove(board, tile, xstart, ystart):
    117     """将一个tile棋子放到(xstart, ystart)"""
    118     tilesToFlip = isValidMove(board, tile, xstart, ystart)
    119     if tilesToFlip == False:
    120         return False
    121     board[xstart][ystart] = tile
    122     for x, y in tilesToFlip:  # tilesToFlip是需要翻转的棋子列表
    123         board[x][y] = tile  # 翻转棋子
    124     return True
    125 
    126 
    127 def getBoardCopy(board):
    128     """复制棋盘"""
    129     dupeBoard = getNewBoard()
    130     for x in range(8):
    131         for y in range(8):
    132             dupeBoard[x][y] = board[x][y]
    133     return dupeBoard
    134 
    135 
    136 def isOnCorner(x, y):
    137     """是否在角上"""
    138     return (x == 0 and y == 0) or (x == 7 and y == 0) or (x == 0 and y == 7) or (x == 7 and y == 7)
    139 
    140 
    141 def getComputerMove(board, computerTile):
    142     """电脑走法,AI"""
    143     # 获取所以合法走法
    144     possibleMoves = getValidMoves(board, computerTile)
    145     if not possibleMoves:  # 如果没有合法走法
    146         print("电脑没有合法走法")
    147         return None
    148 
    149     # 打乱所有合法走法
    150     random.shuffle(possibleMoves)
    151     # [x, y]在角上,则优先走,因为角上的不会被再次翻转
    152     for x, y in possibleMoves:
    153         if isOnCorner(x, y):
    154             return [x, y]
    155     bestScore = -1
    156     for x, y in possibleMoves:
    157         dupeBoard = getBoardCopy(board)
    158         makeMove(dupeBoard, computerTile, x, y)
    159         # 按照分数选择走法,优先选择翻转后分数最多的走法
    160         score = getScoreOfBoard(dupeBoard)[computerTile]
    161         if score > bestScore:
    162             bestMove = [x, y]
    163             bestScore = score
    164     return bestMove
    165 
    166 
    167 def isGameOver(board):
    168     """是否游戏结束"""
    169     for x in range(8):
    170         for y in range(8):
    171             if board[x][y] == 'none':
    172                 return False
    173     return True
    174 
    175 
    176 def drawQiPan():
    177     """画棋盘"""
    178     img1 = imgs[2]
    179     cv.create_image((360, 360), image=img1)
    180     cv.pack()
    181 
    182 
    183 def callback(event):
    184     """走棋"""
    185     global turn
    186     # print ("clicked at", event.x, event.y,turn)
    187     # x=(event.x)//40  #换算棋盘坐标
    188     # y=(event.y)//40
    189     if (gameOver == False and turn == 'computer'):  # 没轮到玩家走棋
    190         return
    191     col = int((event.x - 40) / 80)  # 换算棋盘坐标
    192     row = int((event.y - 40) / 80)
    193     if mainBoard[col][row] != "none":
    194         showinfo(title="提示", message="已有棋子")
    195     if makeMove(mainBoard, playerTile, col, row) == True:  # 将一个玩家棋子放到(col, row)
    196         if getValidMoves(mainBoard, computerTile) != []:
    197             turn = 'computer'
    198     # 电脑走棋
    199     if getComputerMove(mainBoard, computerTile) == None:
    200         turn = 'player'
    201         showinfo(title="玩家继续", message="玩家继续")
    202     else:
    203         computerGo()
    204         # 重画所有的棋子和棋盘
    205     drawAll()
    206     drawCanGo()
    207     if isGameOver(mainBoard):  # 游戏结束,显示双方棋子数量
    208         scorePlayer = getScoreOfBoard(mainBoard)[playerTile]
    209         scoreComputer = getScoreOfBoard(mainBoard)[computerTile]
    210         outputStr = gameoverStr + "玩家:" + str(scorePlayer) + ":" + "电脑:" + str(scoreComputer)
    211         showinfo(title="游戏结束提示", message=outputStr)
    212 
    213 
    214 def computerGo():
    215     """电脑走棋"""
    216     global turn
    217     if (gameOver == False and turn == 'computer'):
    218         x, y = getComputerMove(mainBoard, computerTile)  # 电脑AI走法
    219         makeMove(mainBoard, computerTile, x, y)
    220         savex, savey = x, y
    221         # 玩家没有可行的走法了,则电脑继续,否则切换到玩家走
    222         if getValidMoves(mainBoard, playerTile) != []:
    223             turn = 'player'
    224         else:
    225             if getValidMoves(mainBoard, computerTile) != []:
    226                 showinfo(title="电脑继续", message="电脑继续")
    227                 computerGo()
    228 
    229 
    230 def drawAll():
    231     """重画所有的棋子和棋盘"""
    232     drawQiPan()
    233     for x in range(8):
    234         for y in range(8):
    235             if mainBoard[x][y] == 'black':
    236                 cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[0])
    237                 cv.pack()
    238             elif mainBoard[x][y] == 'white':
    239                 cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[1])
    240                 cv.pack()
    241 
    242 
    243 def drawCanGo():
    244     """画提示位置"""
    245     list1 = getValidMoves(mainBoard, playerTile)
    246     for m in list1:
    247         x = m[0]
    248         y = m[1]
    249         cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[3])
    250         cv.pack()
    251 
    252 
    253 if __name__ == '__main__':
    254     # 初始化
    255     gameOver = False
    256     gameoverStr = 'Game Over Score '
    257     mainBoard = getNewBoard()
    258     resetBoard(mainBoard)
    259     turn = whoGoesFirst()
    260     showinfo(title="游戏开始提示", message=turn + "先走!")
    261     print(turn, "先走!")
    262     if turn == 'player':
    263         playerTile = 'black'
    264         computerTile = 'white'
    265     else:
    266         playerTile = 'white'
    267         computerTile = 'black'
    268         computerGo()
    269 
    270     # 设置窗口
    271     cv = Canvas(root, bg='green', width=720, height=780)
    272     # 重画所有的棋子和棋盘
    273     drawAll()
    274     drawCanGo()
    275     cv.bind("<Button-1>", callback)
    276     cv.pack()
    277     root.mainloop()
  • 相关阅读:
    【转】 springBoot(5)---单元测试,全局异常
    【转】 springBoot(4)---热部署,配置文件使用
    【转】 springBoot(3)---目录结构,文件上传
    【转】 springBoot(2)---快速创建项目,初解jackson
    【转】 springBoot(1)---springboot初步理解
    【转】 SpringBoot+MyBatis+MySQL读写分离
    简单请求 vs 非简单请求
    H5新增的API
    图片
    vue更新dom的diff算法
  • 原文地址:https://www.cnblogs.com/dong4716138/p/14496281.html
Copyright © 2020-2023  润新知