python3+tkinter實現的黑白棋,程式碼完整 100%能執行

dong4716138發表於2021-03-07

今天分享給大家的是採用Python3+tkinter製作而成的小專案——黑白棋

tkinter是Python內建的圖形化模組,簡單易用,一般的小型UI程式可以快速用它實現,具體的tkinter相關知識王老師會在以後開闢專欄單獨講解

我們先來看看這個黑白棋專案吧

一、專案演示

 

 

二、程式碼

完整程式碼如下,用到的素材(圖片等)下載地址為:https://www.itprojects.cn/detail.html?example_id=f00fd7f9722b363f9dc15cf08d80e212

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

 

相關文章