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()

 

posted @ 2021-03-07 20:46  dong4716138  阅读(1198)  评论(0编辑  收藏  举报