今天分享给大家的是采用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()

python3+tkinter实现的黑白棋,代码完整 100%能运行的更多相关文章

  1. 用Dart写的黑白棋游戏

    2013年11月,Dart语言1.0稳定版SDK发布,普天同庆.从此,网页编程不再纠结了. 在我看来,Dart语法简直就是C#的升级版,太像了.之所以喜欢Ruby的一个重要理由是支持mixin功能,而 ...

  2. [CareerCup] 8.8 Othello Game 黑白棋游戏

    8.8 Othello is played as follows: Each Othello piece is white on one side and black on the other. Wh ...

  3. 黑白棋游戏 (codevs 2743)题解

    [问题描述] 黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子.这16枚棋子的每一种放置方案都构成一个游戏状态.在棋盘上拥有1条公共边的2个方格称为相邻方 ...

  4. bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)

    黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...

  5. 【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋

    Description 黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是 ...

  6. 从0开始 Java实习 黑白棋

    黑白棋的设计 代码如下: import java.util.*; public class Chess{ char[][] chess = new char[16][16]; public stati ...

  7. 51nod 1368:黑白棋 二分图最大匹配

    1368 黑白棋 题目来源: TopCoder 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  取消关注 有一个N*M的棋盘(1<=N,M< ...

  8. P2490 [SDOI2011]黑白棋

    P2490 [SDOI2011]黑白棋 题意 一个 \(1*n\) 的棋盘上,A 可以移动白色棋子,B 可以移动黑色的棋子,其中白色不能往左,黑色不能往右.他们每次操作可以移动 1 到 \(d\) 个 ...

  9. Python3中的新特性(3)——代码迁移与2to3

    1.将代码移植到Python2.6 建议任何要将代码移植到Python3的用户首先将代码移植到Python2.6.Python2.6不仅与Python2.5向后兼容,而且支持Python3中的部分新特 ...

随机推荐

  1. 牛客练习赛63 C.牛牛的揠苗助长

    题意:有一个长度为\(n\)的数组,从第一天开始,第\(i\)天可以使\(i\)位置上的数\(+1\),当\(i=n\)时,下次从\(i=1\)再开始,另外,在每天结束时,你可以使任意一个位置上的数\ ...

  2. zoj3623 Battle Ships

    Battle Ships is a new game which is similar to Star Craft. In this game, the enemy builds a defense ...

  3. Codeforces Round #653 (Div. 3) A. Required Remainder (数学)

    题意:有三个正整数\(x,y,n\),再\(1\)~\(n\)中找一个最大的数\(k\),使得\(k\ mod\ x=y\). 题解:先记\(tmp=n/x\),再判断\(tmp*x+y\)的值是否大 ...

  4. LINUX - 文件读写缓存

    遇到一个进程core掉后日志打印不出来的问题: 参考如下: [引用] 只有正常退出,才能做到flush.否则将写失败. 之后有百度了下中文资料,发现同样的结论. "fflush库函数的作用是 ...

  5. Linux系统诊断必备技能之二:日志查询常用命令详解

    一.概述 日常运维工作中,排查线上环境问题,少不了去线上查日志.而使用什么命令,能快速准确地查到我们需要查找地日志信息,也是我们需要掌握的一项技能.下面介绍一下日常工作常用到的查看日志命令:tail, ...

  6. KEIL + STM32 续

    接上一篇,debug出现问题 1.手动安装STM32 芯片包   Keil.STM32F1xx_DFP.2.2.0.pack; https://www.keil.com/dd2/Pack/ 百度网盘  ...

  7. ysoserial-URLDNS学习

    简述 ysoserial很强大,花时间好好研究研究其中的利用链对于了解java语言的一些特性很有帮助,也方便打好学习java安全的基础,刚学反序列化时就分析过commoncollections,但是是 ...

  8. favicon.ico All In One

    favicon.ico All In One link rel="icon" type="image/x-icon" href="http://exa ...

  9. CSS pseudo classes All In One

    CSS pseudo classes All In One CSS 伪类 https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes ...

  10. what's the print number means after called the setTimeout function in Chrome console?

    what's the print number means after called the setTimeout function in Chrome console? javascript fun ...