python3+tkinter实现的黑白棋,代码完整 100%能运行
今天分享给大家的是采用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%能运行的更多相关文章
- 用Dart写的黑白棋游戏
2013年11月,Dart语言1.0稳定版SDK发布,普天同庆.从此,网页编程不再纠结了. 在我看来,Dart语法简直就是C#的升级版,太像了.之所以喜欢Ruby的一个重要理由是支持mixin功能,而 ...
- [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 ...
- 黑白棋游戏 (codevs 2743)题解
[问题描述] 黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子.这16枚棋子的每一种放置方案都构成一个游戏状态.在棋盘上拥有1条公共边的2个方格称为相邻方 ...
- bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)
黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...
- 【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋
Description 黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是 ...
- 从0开始 Java实习 黑白棋
黑白棋的设计 代码如下: import java.util.*; public class Chess{ char[][] chess = new char[16][16]; public stati ...
- 51nod 1368:黑白棋 二分图最大匹配
1368 黑白棋 题目来源: TopCoder 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 取消关注 有一个N*M的棋盘(1<=N,M< ...
- P2490 [SDOI2011]黑白棋
P2490 [SDOI2011]黑白棋 题意 一个 \(1*n\) 的棋盘上,A 可以移动白色棋子,B 可以移动黑色的棋子,其中白色不能往左,黑色不能往右.他们每次操作可以移动 1 到 \(d\) 个 ...
- Python3中的新特性(3)——代码迁移与2to3
1.将代码移植到Python2.6 建议任何要将代码移植到Python3的用户首先将代码移植到Python2.6.Python2.6不仅与Python2.5向后兼容,而且支持Python3中的部分新特 ...
随机推荐
- 病毒侵袭 HDU - 2896 板子题
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋--我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~ 但网路上总有那么些网站,开 ...
- centos 7下安装配置Supervisor
1.安装Supervisor centos下安装yum install supervisor 2. systemctl enable supervisord 开机自启 systemctl start ...
- HttpClient&&RestTemplate学习
1. 什么是HttpClient HttpClient是Apache下面的子项目,可以提供高效的,最新的,功能丰富的支持HTTP协议的客户端编程工具包. 2. 为什么要学习HttpClient Htt ...
- 01.原生态jdbc程序中问题总结
1.数据库启动包配置到工程目录中(mysql5.1) mysql-connector-java-5.1.7-bin.jar 2.jdbc原生态操作数据库(程序) 操作mysql数据库 1 packag ...
- Django用户注册、登录
一.用户注册 1 ''' 2 注册的表单模型 3 forms.py 的例子 4 ''' 5 6 from django import forms #表单功能 7 from django.contrib ...
- Cobbler服务引导第三方PE系统
通过Cobbler服务引导第三方PE系统 1.上传第三方ios到/root/Ushendu_win10.iso并增加菜单项 cobbler distro add --name=Ushendu_win1 ...
- Leetcode(144)-二叉树的前序遍历
给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 二叉树的前序遍历有递归 ...
- Go string 一清二楚
前言 字符串(string) 作为 go 语言的基本数据类型,在开发中必不可少,我们务必深入学习一下,做到一清二楚. 本文假设读者已经知道切片(slice)的使用,如不了解,可阅读 Go 切片 基本知 ...
- Python Web Framework All In One
Python Web Framework All In One Django and Flask are the top Python web frameworks so far. Django ht ...
- ReactDOM API All In One
ReactDOM API All In One React DOM API render() hydrate() unmountComponentAtNode() findDOMNode() crea ...