初学Python
,设计了一款简单的五子棋游戏。水平有限,欢迎批评指正
代码详见: https://gitee.com/liio/gobang
目录结构如下
卷 DATA 的文件夹 PATH 列表
卷序列号为 207A-076D
/.
│ gobang.py // 五子棋类文件
│ thread_stop.py // 线程停止文件(由于我的 tk_game.py 写的不是很好所以需要辅助关闭进程)
│ tk_game.py // UI 界面
│
└─source
└─img
background.png
background_c.png
chessboard.png
icon.ico
icon.png
def isWin(self, line_list=None):
if line_list is None:
line_list = self.arround()
for line in line_list:
if line[0].count(self.__playerid) >= 5:
for i in range(0, len(line[0]) - 4):
if line[0][i] == line[0][i + 1] == line[0][i + 2] == line[
0][i + 3] == line[0][i + 4] == self.__playerid:
return True
else:
return False
def arround(self=None, row=0, column=0):
if self is not None:
if len(self.getStep()) != 0:
row = ord(list(self.getStep().items())[-1][1][0]) - 97
column = ord(list(self.getStep().items())[-1][1][1]) - 97
else:
row = 7
column = 7
line_list, line_list1, line_list2, line_list3, line_list4 = [], [], [], [], []
line_list1_, line_list2_, line_list3_, line_list4_ = [], [], [], []
# 获取一整行
line_list1 = [list(Chess.__checkerboard[row])]
for i in range(len(Chess.__checkerboard[row])):
line_list1_.append([row, i])
line_list1.append(line_list1_)
# 获取一整列
line_list2 = [list(Chess.__checkerboard.T[column])]
for i in range(len(Chess.__checkerboard.T[column])):
line_list2_.append([i, column])
line_list2.append(line_list2_)
# 获取正斜线
if row >= column:
for i in range(14 - abs(row - column) + 1):
line_list3.append(Chess.__checkerboard[i +
abs(row - column)][i])
line_list3 = [line_list3]
for i in range(14 - abs(row - column) + 1):
line_list3_.append([i + abs(row - column), i])
line_list3.append(line_list3_)
if row < column:
for i in range(14 - abs(row - column) + 1):
line_list3.append(Chess.__checkerboard[i][i +
abs(row - column)])
line_list3 = [line_list3]
for i in range(14 - abs(row - column) + 1):
line_list3_.append([i, i + abs(row - column)])
line_list3.append(line_list3_)
# 获取反斜线
if row + column <= 14:
for i in range(row + column + 1):
line_list4.append(Chess.__checkerboard[i][row + column - i])
line_list4 = [line_list4]
for i in range(row + column + 1):
line_list4_.append([i, row + column - i])
line_list4.append(line_list4_)
if row + column > 14:
for i in range(28 - (row + column) + 1):
line_list4.append(
Chess.__checkerboard[14 - i][14 - (28 -
(row + column) - i)])
line_list4 = [line_list4]
for i in range(28 - (row + column) + 1):
line_list4_.append([14 - i, 14 - (28 - (row + column) - i)])
line_list4.append(line_list4_)
line_list.append(list(line_list1))
line_list.append(list(line_list2))
line_list.append(line_list3)
line_list.append(line_list4)
return line_list
def aiChess():
def get_score(id):
score = [[1, [0, 0, 0, 0, id], [1, 2, 4, 6, 0]],
[1, [id, 0, 0, 0, 0], [0, 6, 4, 2, 1]],
[1, [0, 0, 0, id, 0], [2, 4, 6, 0, 1]],
[1, [0, id, 0, 0, 0], [1, 0, 6, 4, 2]],
[10, [0, 0, id, 0, 0], [1, 10, 0, 10, 1]],
[50, [0, id, id, 0, 0], [50, 0, 0, 50, 10]],
[50, [0, 0, id, id, 0], [10, 50, 0, 0, 50]],
[50, [0, id, 0, id, 0], [10, 0, 50, 0, 10]],
[200, [id, id, 0, id, 0], [0, 0, 200, 0, 50]],
[500, [0, 0, id, id, id], [50, 200, 0, 0, 0]],
[500, [id, id, id, 0, 0], [0, 0, 0, 200, 50]],
[5000, [0, id, id, id, 0], [200, 0, 0, 0, 200]],
[5000, [0, id, 0, id, id, 0], [200, 0, 500, 0, 0, 200]],
[5000, [0, id, id, 0, id, 0], [200, 0, 0, 500, 0, 200]],
[5000, [id, id, id, 0, id], [0, 0, 0, 500, 0]],
[5000, [id, id, 0, id, id], [0, 0, 500, 0, 0]],
[5000, [id, 0, id, id, id], [0, 50000, 0, 0, 0]],
[5000, [id, id, id, id, 0], [0, 0, 0, 0, 50000]],
[5000, [0, id, id, id, id], [50000, 0, 0, 0, 0]],
[99999999, [id, id, id, id, id], [0, 0, 0, 0, 0]]]
return score
def dict_span(dict1: dict, dict2: dict):
weight = 100
dict1_keys = list(dict1.keys())
dict2_keys = list(dict2.keys())
re_dict = {}
for key in dict1_keys:
if key in dict2_keys:
re_dict[key] = (dict1[key] *
dict2[key]) / weight + dict2[key] + dict1[key]
else:
re_dict[key] = dict1[key]
for key in dict2_keys:
if key not in dict1_keys:
re_dict[key] = dict2[key]
return re_dict
def get_p_score(id):
p_score = {}
for s_line in get_score(id):
for _ in traversal_checkerboard():
for i in _:
for j in range((len(i[0]) - len(s_line[1])) + 1):
if i[0][j:len(s_line[1]) + j] == s_line[1]:
for p in range(
len(i[0][j + 1:len(s_line[1]) + j + 1])):
if str(i[0][j + 1:len(s_line[1]) + j +
1][p]) in p_score:
p_score[str(
i[1][j:len(s_line[1]) + j]
[p])] += s_line[0] * s_line[2][p]
else:
p_score[str(
i[1][j:len(s_line[1]) +
j][p])] = s_line[0] * s_line[2][p]
return p_score
score = get_p_score(2)
score_my = get_p_score(1)
score = dict_span(score, score_my)
if len(score) == 0:
score = dict_span(score, score_my)
return (eval(max(score, key=score.get))[0], eval(max(score,
key=score.get))[1])
def dicttoChees(step_dict):
Chess.step = step_dict.copy()
for r in range(len(Chess._Chess__checkerboard)):
for c in range(len(Chess._Chess__checkerboard[r])):
Chess._Chess__checkerboard[r][c] = 0
if len(step_dict) != 0:
for step in step_dict.items():
row = ord(step[1][0]) - 97
column = ord(step[1][1]) - 97
if step[0] % 2 == 0:
Chess._Chess__checkerboard[row][column] = 2
elif step[0] % 2 == 1:
Chess._Chess__checkerboard[row][column] = 1
def click(event):
if not w.isWin() and not b.isWin():
ismove_x = False
ismove_y = False
if 10 < event.x < 650 and 10 < event.y < 650:
if (event.x - START) % LENGTH < 20:
x = (event.x - START) // LENGTH
ismove_x = True
elif (event.x - START) % LENGTH > 24:
x = ((event.x - START) // LENGTH) + 1
ismove_x = True
if (event.y - START) % LENGTH < 20:
y = (event.y - START) // LENGTH
ismove_y = True
elif (event.y - START) % LENGTH > 24:
y = ((event.y - START) // LENGTH) + 1
ismove_y = True
if ismove_x and ismove_y:
move(y, x)
def sign(event):
# 获取鼠标实时位置,做出提示
# time.sleep(0.08)
canvas.delete("Sign")
ismove_x = False
ismove_y = False
if 10 < event.x < 650 and 10 < event.y < 650 and not w.isWin(
) and not b.isWin():
if (event.x - START) % LENGTH < 20:
x = (event.x - START) // LENGTH
ismove_x = True
elif (event.x - START) % LENGTH > 24:
x = ((event.x - START) // LENGTH) + 1
ismove_x = True
if (event.y - START) % LENGTH < 20:
y = (event.y - START) // LENGTH
ismove_y = True
elif (event.y - START) % LENGTH > 24:
y = ((event.y - START) // LENGTH) + 1
ismove_y = True
if ismove_x and ismove_y:
y1 = START + (LENGTH * y) - 20
x1 = START + (LENGTH * x) - 20
y2 = START + (LENGTH * y) + 20
x2 = START + (LENGTH * x) + 20
canvas.create_oval(x1 + 15,
y1 + 15,
x2 - 15,
y2 - 15,
fill='red',
tags='Sign')
#####落子与绘制棋盘
def move(y, x):
# 落子
global times
if not w.isWin() and not b.isWin():
if w.isPlayer():
if w.moveChessmen(y, x):
draw()
elif b.isPlayer():
if b.moveChessmen(y, x):
draw()
if w.isWin():
tkinter.messagebox.showinfo('提示', '白方获胜!')
if b.isWin():
tkinter.messagebox.showinfo('提示', '黑方获胜!')
def draw(step_dict=None):
# 绘制棋盘
canvas.delete('Piece')
color = {1: 'black', 0: 'white'}
if step_dict is None:
step_dict = Chess.getStep().copy()
for step in step_dict.items():
row = ord(step[1][0]) - 97
column = ord(step[1][1]) - 97
y1 = START + (LENGTH * row) - 20
x1 = START + (LENGTH * column) - 20
y2 = START + (LENGTH * row) + 20
x2 = START + (LENGTH * column) + 20
canvas.create_oval(x1,
y1,
x2,
y2,
fill=color[(step[0] % 2)],
tags='Piece')
if step[0] == len(step_dict.items()):
canvas.create_oval(x1 + 15,
y1 + 15,
x2 - 15,
y2 - 15,
fill='pink',
tags='Piece')
if order:
canvas.create_text(x1 + 20,
y1 + 20,
text=str(step[0]),
fill=color[int(not bool((step[0] % 2)))],
tags='Piece')
# print(draw_list) # 测试输出
def open_gs():
# 打开棋谱文件 TODO
gs_file = tkinter.filedialog.askopenfilename(title="选择棋谱",
initialdir=ex_folder,
filetypes=[("棋谱文件", ".sgf"),
("棋谱文件", ".gbs"),
("Gobang棋谱文件",
".gbs")])
if gs_file != '':
try:
with open(gs_file, encoding='utf-8') as f:
gs_text = f.read()
except UnicodeDecodeError:
with open(gs_file) as f:
gs_text = f.read()
finally:
step_dict = {}
step_list = re.findall(r"[\[']([a-z][a-z])['\]]", gs_text)
for i in range(len(step_list)):
step_dict[i + 1] = step_list[i]
score_mode(step_dict)
def save_gbs():
# 保存棋谱文件 `gbs` 格式
gbs_data = tkinter.filedialog.asksaveasfile(mode='w',
title="选择棋谱",
initialdir=ex_folder,
defaultextension=".espace",
filetypes=[("Gobang棋谱文件",
".gbs")])
if gbs_data is not None:
gbs_data.write(str(Chess.getStep()))