|
|
import os
|
|
|
from tkinter import *
|
|
|
import tkinter.messagebox
|
|
|
from utils import *
|
|
|
import tkinter.scrolledtext as st
|
|
|
from chess import *
|
|
|
from PIL import Image, ImageTk
|
|
|
from datetime import datetime
|
|
|
import time
|
|
|
import numpy as np
|
|
|
|
|
|
chess = Chess()
|
|
|
crossline = []
|
|
|
verline = []
|
|
|
regretnum = 0
|
|
|
handlenum = 0
|
|
|
flag = 0
|
|
|
root = Tk() # 窗口对象
|
|
|
root.title('五子棋') # 窗口标题
|
|
|
|
|
|
x = 10
|
|
|
y = 10
|
|
|
root.geometry('1000x700+'+str(x)+'+'+str(y)) # 窗口大小 width x height + x + y(x,y为在当前界面的坐标)
|
|
|
# 创建一个主目录菜单,也被称为顶级菜单
|
|
|
main_menu = Menu(root)
|
|
|
|
|
|
# menu_font2 = ("Arial", 14)
|
|
|
# main_menu.config(font=menu_font2)
|
|
|
|
|
|
gamefile = Menu(main_menu, tearoff=False)
|
|
|
|
|
|
|
|
|
local = True
|
|
|
# local = False
|
|
|
if local == True:
|
|
|
path = ""
|
|
|
else:
|
|
|
path = "/data/workspace/myshixun/finalchess/"
|
|
|
# path = ""
|
|
|
|
|
|
# 新增"文件"菜单的菜单项,并使用 accelerator 设置菜单项的快捷键
|
|
|
# gamefile.add_command (label="新建",command=menuCommand,accelerator="Ctrl+N")
|
|
|
|
|
|
|
|
|
# 人-机白对弈
|
|
|
def peoCompWhite():
|
|
|
refresh()
|
|
|
chess.chessMode = 1
|
|
|
mainCon.switch_mode(chess)
|
|
|
print(chess.chessMode)
|
|
|
chess.playing(1, root, canvas, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
|
|
|
|
|
|
# 人-机黑对弈
|
|
|
def peoCompBlack():
|
|
|
refresh()
|
|
|
chess.chessMode = 2
|
|
|
mainCon.switch_mode(chess)
|
|
|
print(chess.chessMode)
|
|
|
chess.playing(2, root, canvas, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
|
|
|
|
|
|
# 双人模式
|
|
|
def doublePeople():
|
|
|
refresh()
|
|
|
chess.chessMode = 0
|
|
|
mainCon.switch_mode(chess)
|
|
|
print(chess.chessMode)
|
|
|
chess.playing(0, root, canvas, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
|
|
|
|
|
|
# 开始游戏
|
|
|
def startGame():
|
|
|
win = Tk()
|
|
|
win.title("开始游戏")
|
|
|
win.geometry('500x300+100+100')
|
|
|
Label(win, text="五子棋", width=120, height=2).place(x=-175, y=50)
|
|
|
Button(win, text="人机模式(机白)", command=peoCompWhite, width=20, height=2).place(x=170, y=100)
|
|
|
Button(win, text="人机模式(机黑)", command=peoCompBlack, width=20, height=2).place(x=170, y=150)
|
|
|
Button(win, text="双人模式", command=doublePeople, width=20, height=2).place(x=170, y=200)
|
|
|
|
|
|
|
|
|
# !退出游戏 还没有定义
|
|
|
def quitgame():
|
|
|
pass
|
|
|
|
|
|
|
|
|
# 保存棋局
|
|
|
def saveCurrentBoard():
|
|
|
# 创建一个空的二维数组data来保存当前棋盘状态
|
|
|
data = [[0 for j in range(19)] for i in range(19)]
|
|
|
|
|
|
file = open(path +'data.txt', 'w')
|
|
|
file.truncate(0)
|
|
|
for i in range(0, 19):
|
|
|
for j in range(0, 19):
|
|
|
data[i][j] = chess.chessData[i][j]['Cstate']
|
|
|
data = np.mat(data)
|
|
|
b = ''
|
|
|
for i in range(0, 19):
|
|
|
for j in range(0, 19):
|
|
|
b += str(data[i, j]) + '\t'
|
|
|
b += '\n'
|
|
|
file.writelines(b)
|
|
|
# print(data)
|
|
|
# 创建一个空的二维数组data来保存当前棋盘落子步骤
|
|
|
data1 = [[0 for j in range(19)] for i in range(19)]
|
|
|
for i in range(0, 19):
|
|
|
for j in range(0, 19):
|
|
|
data1[i][j] = chess.chessData[i][j]['Cstep']
|
|
|
data = np.mat(data1)
|
|
|
b = ''
|
|
|
for i in range(0, 19):
|
|
|
for j in range(0, 19):
|
|
|
b += str(data[i, j]) + '\t'
|
|
|
b += '\n'
|
|
|
file.writelines(b)
|
|
|
# 将游戏模式、当前步数和胜利状态转换为字符串,并写入文件
|
|
|
Chess_Mode = str(chess.chessMode) + '\n'
|
|
|
file.write(Chess_Mode)
|
|
|
step = str(chess.currentStep) + '\n'
|
|
|
file.write(step)
|
|
|
WinFLAG = str(chess.winFlag) + '\n'
|
|
|
file.write(WinFLAG)
|
|
|
file.close()
|
|
|
|
|
|
|
|
|
# 重装棋局
|
|
|
def resetLastBoard():
|
|
|
refresh()
|
|
|
# 读取保存的数据文件
|
|
|
file = open(path + 'data.txt', 'r+', encoding='utf-8')
|
|
|
data = file.readlines()
|
|
|
rtu = []
|
|
|
for i in data:
|
|
|
rtu.append(i.strip())
|
|
|
for i in range(0, 19):
|
|
|
j = 0
|
|
|
rtu1 = rtu[i].split("\t")
|
|
|
for x in rtu1:
|
|
|
chess.chessData[i][j]['Cstate'] = int(x)
|
|
|
j += 1
|
|
|
for i in range(19, 38):
|
|
|
j = 0
|
|
|
rtu1 = rtu[i].split("\t")
|
|
|
for x in rtu1:
|
|
|
chess.chessData[i - 19][j]['Cstep'] = int(x)
|
|
|
j += 1
|
|
|
chess.chessMode = int(rtu[len(rtu) - 3])
|
|
|
chess.currentStep = int(rtu[len(rtu) - 2])
|
|
|
chess.winFlag = int(rtu[len(rtu) - 1])
|
|
|
file.close()
|
|
|
|
|
|
# 设置为记录中的模式
|
|
|
mainCon.switch_mode(chess)
|
|
|
|
|
|
for x in range(19):
|
|
|
for y in range(19):
|
|
|
if chess.chessData[x][y]['Cstate'] == 1:
|
|
|
chess.Chessimg[x][y] = canvas.create_image(x * 36.8 + 41 - 14, y * 34.6 + 21, image=whiteChPieceImg, anchor=W)
|
|
|
elif chess.chessData[x][y]['Cstate'] == 2:
|
|
|
chess.Chessimg[x][y] = canvas.create_image(x * 36.8 + 41 - 14, y * 34.6 + 21, image=blackChPieceImg, anchor=W)
|
|
|
if chess.chessMode == 1 and chess.winFlag == 0:
|
|
|
chess.myColor = 2
|
|
|
chess.player2Color = 1
|
|
|
if chess.currentStep % 2 == 0:
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 0, 1, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到玩家下棋了!')
|
|
|
elif chess.currentStep % 2 != 0:
|
|
|
pass # 正常不会出现电脑不落子的情况
|
|
|
# chess.player = 0
|
|
|
# chess.player2 = 1
|
|
|
# chess.playGameBlack(root, None, None, canvas, blackChPieceImg, whiteChPieceImg, result, photos1, photos2)
|
|
|
elif chess.chessMode == 2 and chess.winFlag == 0:
|
|
|
chess.myColor = 1
|
|
|
chess.player2Color = 2
|
|
|
if chess.currentStep % 2 == 0:
|
|
|
pass # 正常不会出现电脑不落子的情况
|
|
|
# chess.player = 0
|
|
|
# chess.player2 = 1
|
|
|
# chess.playGameWhite(root, None, None, canvas, blackChPieceImg, whiteChPieceImg, result, photos1, photos2)
|
|
|
if chess.currentStep % 2 != 0:
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 0, 1, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到玩家下棋了!')
|
|
|
elif chess.chessMode == 0 and chess.winFlag == 0:
|
|
|
chess.myColor = 2
|
|
|
chess.player2Color = 1
|
|
|
if chess.currentStep % 2 == 0:
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 1, 1, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到先手下棋了!')
|
|
|
elif chess.currentStep % 2 != 0:
|
|
|
chess.player = 0
|
|
|
chess.player2 = 1
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到后手下棋了!')
|
|
|
elif chess.winFlag == 1:
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='对局已经结束了')
|
|
|
|
|
|
|
|
|
# 随机棋局
|
|
|
def randomChessboard():
|
|
|
refresh()
|
|
|
if local:
|
|
|
folder_path = "./data"
|
|
|
else:
|
|
|
folder_path = path + "data"
|
|
|
txt_files = [f for f in os.listdir(folder_path) if f.endswith('.txt')]
|
|
|
if txt_files:
|
|
|
random_file = random.choice(txt_files)
|
|
|
file_path = os.path.join(folder_path, random_file)
|
|
|
file = open(file_path, 'r+', encoding='utf-8')
|
|
|
data = file.readlines()
|
|
|
rtu = []
|
|
|
for i in data:
|
|
|
rtu.append(i.strip())
|
|
|
for i in range(0, 19):
|
|
|
j = 0
|
|
|
rtu1 = rtu[i].split("\t")
|
|
|
for x in rtu1:
|
|
|
chess.chessData[i][j]['Cstate'] = int(x)
|
|
|
j += 1
|
|
|
for i in range(19, 38):
|
|
|
j = 0
|
|
|
rtu1 = rtu[i].split("\t")
|
|
|
for x in rtu1:
|
|
|
chess.chessData[i - 19][j]['Cstep'] = int(x)
|
|
|
j += 1
|
|
|
chess.chessMode = int(rtu[len(rtu) - 3])
|
|
|
chess.currentStep = int(rtu[len(rtu) - 2])
|
|
|
chess.winFlag = int(rtu[len(rtu) - 1])
|
|
|
file.close()
|
|
|
|
|
|
# 创建棋子
|
|
|
for x in range(19):
|
|
|
for y in range(19):
|
|
|
if chess.chessData[x][y]['Cstate'] == 1:
|
|
|
chess.Chessimg[x][y] = canvas.create_image(x * 36.8 + 41 - 14, y * 34.6 + 21, image=whiteChPieceImg, anchor=W)
|
|
|
elif chess.chessData[x][y]['Cstate'] == 2:
|
|
|
chess.Chessimg[x][y] = canvas.create_image(x * 36.8 + 41 - 14, y * 34.6 + 21, image=blackChPieceImg, anchor=W)
|
|
|
|
|
|
# 设置为记录中的模式
|
|
|
mainCon.switch_mode(chess)
|
|
|
|
|
|
for x in range(19):
|
|
|
for y in range(19):
|
|
|
if chess.chessData[x][y]['Cstate'] == 1:
|
|
|
chess.Chessimg[x][y] = canvas.create_image(x * 36.8 + 41 - 14, y * 34.6 + 21, image=whiteChPieceImg, anchor=W)
|
|
|
elif chess.chessData[x][y]['Cstate'] == 2:
|
|
|
chess.Chessimg[x][y] = canvas.create_image(x * 36.8 + 41 - 14, y * 34.6 + 21, image=blackChPieceImg, anchor=W)
|
|
|
if chess.chessMode == 1 and chess.winFlag == 0:
|
|
|
chess.myColor = 2
|
|
|
chess.player2Color = 1
|
|
|
if chess.currentStep % 2 == 0:
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到玩家下棋了!')
|
|
|
elif chess.currentStep % 2 != 0:
|
|
|
pass # 正常不会出现电脑不落子的情况
|
|
|
# chess.player = 0
|
|
|
# chess.player2 = 1
|
|
|
# chess.playGameBlack(root, None, None, canvas, blackChPieceImg, whiteChPieceImg, result, photos1, photos2)
|
|
|
elif chess.chessMode == 2 and chess.winFlag == 0:
|
|
|
chess.myColor = 1
|
|
|
chess.player2Color = 2
|
|
|
if chess.currentStep % 2 == 0:
|
|
|
pass # 正常不会出现电脑不落子的情况
|
|
|
# chess.player = 0
|
|
|
# chess.player2 = 1
|
|
|
# chess.playGameWhite(root, None, None, canvas, blackChPieceImg, whiteChPieceImg, result, photos1, photos2)
|
|
|
if chess.currentStep % 2 != 0:
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到玩家下棋了!')
|
|
|
elif chess.chessMode == 0 and chess.winFlag == 0:
|
|
|
chess.myColor = 2
|
|
|
chess.player2Color = 1
|
|
|
if chess.currentStep % 2 == 0:
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 0, 1, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到先手下棋了!')
|
|
|
elif chess.currentStep % 2 != 0:
|
|
|
chess.player = 0
|
|
|
chess.player2 = 1
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='轮到后手下棋了!')
|
|
|
elif chess.winFlag == 1:
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='对局已经结束了')
|
|
|
|
|
|
|
|
|
menu_font2 = ("Microsoft YaHei UI", 12)
|
|
|
|
|
|
gamefile.add_command(label="开始游戏", command=startGame, font=menu_font2)
|
|
|
gamefile.add_command(label="保存当前局面", command=saveCurrentBoard, accelerator="Ctrl+O", font=menu_font2)
|
|
|
gamefile.add_command(label="重装以前局面", command=resetLastBoard, accelerator="Ctrl+S", font=menu_font2)
|
|
|
gamefile.add_command(label="随机棋局", command=randomChessboard, font=menu_font2)
|
|
|
main_menu.add_cascade(label="游戏", menu=gamefile) # 在主目录菜单上新增"文件"选项,并通过menu参数与下拉菜单绑定
|
|
|
|
|
|
|
|
|
# 游戏规则
|
|
|
def helpGame():
|
|
|
msg = '''
|
|
|
1、对局双方各执一色棋子。
|
|
|
2、空棋盘开局。
|
|
|
3、黑棋虽先行,但有禁手:黑方不能在一步之内形成两个“活三”“活四”或一步之内形成“长连”(指一步形成超过五子连珠)。白方自由,无禁手。
|
|
|
4、棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
|
|
|
5、黑方的第一枚棋子可下在棋盘任意交叉点上。
|
|
|
'''
|
|
|
tkinter.messagebox.showinfo(title='游戏规则', message=msg)
|
|
|
|
|
|
|
|
|
main_menu.add_command(label="帮助", command=helpGame)
|
|
|
root.config(menu=main_menu)
|
|
|
|
|
|
# 棋盘背景画面
|
|
|
canvas = Canvas(root, bg='white', width=1000, height=800)
|
|
|
photoImg = Image.open(path + "image/背景.png").resize((1000, 800))
|
|
|
imgBG = ImageTk.PhotoImage(photoImg)
|
|
|
canvas.create_image(0, 330, image=imgBG, anchor=W)
|
|
|
photoQipan = Image.open(path + "image/棋盘-空.png").resize((730, 700))
|
|
|
photoQipan = ImageTk.PhotoImage(photoQipan)
|
|
|
canvas.create_image(10, 350, image=photoQipan, anchor=W)
|
|
|
|
|
|
|
|
|
# # 绘制棋盘
|
|
|
cross(canvas)
|
|
|
canvas.place(x=0, y=0)
|
|
|
|
|
|
|
|
|
class Player:
|
|
|
def NextMove(self, chess, blackch, whitech):
|
|
|
pass
|
|
|
def Suggestion(self):
|
|
|
pass
|
|
|
|
|
|
|
|
|
class HumanPlayer(Player):
|
|
|
|
|
|
def NextMove(self, chessData, chess, blackch, whitech):
|
|
|
playerx = float(format(chessData.x))
|
|
|
playery = float(format(chessData.y))
|
|
|
print("playerx",playerx)
|
|
|
print("playery",playery)
|
|
|
if chess.winFlag == 0:
|
|
|
print("chess.player", chess.player)
|
|
|
print("chess.player2", chess.player2)
|
|
|
print("chess.currentStep % 2 == 0", chess.currentStep % 2 == 0)
|
|
|
# if chess.player == 1 and chess.player2 == 0 and chess.currentStep % 2 == 0:
|
|
|
if chess.player == 1 and chess.player2 == 0:
|
|
|
# 判断玩家点击的位置是否可以落子,并落子
|
|
|
print("human 落子")
|
|
|
if chess.playerLocation(playerx, playery, canvas, blackch, whitech):
|
|
|
# 如果使用了落子建议,则删除掉所画的落子点
|
|
|
for i in chess.OvaloneNew:
|
|
|
canvas.delete(i)
|
|
|
# 控制玩家下棋状态
|
|
|
chess.player = 0
|
|
|
chess.player2 = 1
|
|
|
# 判断此次落子是否结束游戏
|
|
|
chess.Gameover = chess.chessCheck()
|
|
|
# 设置右上方面板当前落子方状态显示
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackch, whitech, photos1, photos2)
|
|
|
if chess.winFlag == 1:
|
|
|
chess.resultshow(root, canvas, whitech, blackch)
|
|
|
root.update()
|
|
|
# elif chess.player2 == 1 and chess.player == 0 and chess.currentStep % 2 != 0:
|
|
|
elif chess.player2 == 1 and chess.player == 0:
|
|
|
print("human 落子")
|
|
|
if chess.playerLocation(playerx, playery, canvas, blackch, whitech):
|
|
|
for i in chess.OvaloneNew:
|
|
|
canvas.delete(i)
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackch, whitech, photos1, photos2)
|
|
|
chess.Gameover = chess.chessCheck()
|
|
|
if chess.winFlag == 1:
|
|
|
chess.resultshow(root, canvas, whitech, blackch)
|
|
|
root.update()
|
|
|
|
|
|
# 最新的得到建议的函数
|
|
|
def Suggestion(self):
|
|
|
if chess.gameEnd() or chess.currentStep == 0:
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='请在对局中使用!')
|
|
|
return
|
|
|
# 滚动框
|
|
|
global Text
|
|
|
x = root.winfo_x()
|
|
|
y = root.winfo_y()
|
|
|
# x = 10
|
|
|
# y = 10
|
|
|
root.geometry('1000x800+' + str(x) + '+' + str(y))
|
|
|
Text = st.ScrolledText(root, bg='#522418', font=('Arial', 12), bd=2, relief='groove') # 创建一个带滚动条的文本框,用于展示计算过程
|
|
|
Text.place(x=0, y=685, height=100, width=1000)
|
|
|
Text.configure(foreground='white')
|
|
|
Text.delete('1.0', 'end')
|
|
|
Text.insert('2.0', '落子建议步骤:\n')
|
|
|
if chess.winFlag != 1:
|
|
|
if chess.depth >= 9:
|
|
|
chess.depth = 8
|
|
|
if chess.chessMode == 1:
|
|
|
color = 2
|
|
|
elif chess.chessMode == 2:
|
|
|
color = 1
|
|
|
elif chess.chessMode == 0:
|
|
|
if chess.player == 1 and chess.player2 == 0:
|
|
|
color = 2
|
|
|
elif chess.player == 0 and chess.player2 == 1:
|
|
|
color = 1
|
|
|
pos, message = chess.returnPostionNew(chess.depth, color) # 调用估值函数
|
|
|
Text.insert('end', '最佳落子点为:{}\n'.format(chess.maxScorePos))
|
|
|
Text.insert('end', message)
|
|
|
# print("pos:",pos)
|
|
|
print(pos)
|
|
|
# 画点
|
|
|
drawChess(canvas, pos, chess)
|
|
|
root.update()
|
|
|
|
|
|
|
|
|
class RobotPlayer(Player):
|
|
|
|
|
|
def NextMove(self, chessData, chess, blackch, whitech):
|
|
|
playerx = float(format(chessData.x))
|
|
|
playery = float(format(chessData.y))
|
|
|
print("playerx",playerx)
|
|
|
print("playery",playery)
|
|
|
if chess.winFlag == 0:
|
|
|
print("chess.player", chess.player)
|
|
|
print("chess.player2", chess.player2)
|
|
|
# print("chess.currentStep % 2 == 0", chess.currentStep % 2 == 0)
|
|
|
if chess.player == 1 and chess.player2 == 0:
|
|
|
# if chess.player == 1 and chess.player2 == 0 and chess.currentStep % 2 == 0:
|
|
|
# ai落子
|
|
|
print("ai 落子")
|
|
|
if chess.aiLocation(canvas, blackch, whitech):
|
|
|
# 如果使用了落子建议,则删除掉所画的落子点
|
|
|
for i in chess.OvaloneNew:
|
|
|
canvas.delete(i)
|
|
|
chess.player = 0
|
|
|
chess.player2 = 1
|
|
|
# 判断此次落子是否结束游戏
|
|
|
chess.Gameover = chess.chessCheck()
|
|
|
# 设置右上方面板当前落子方状态显示
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackch, whitech, photos1, photos2)
|
|
|
if chess.winFlag == 1:
|
|
|
chess.resultshow(root, canvas, whitech, blackch)
|
|
|
root.update()
|
|
|
elif chess.player2 == 1 and chess.player == 0:
|
|
|
# elif chess.player2 == 1 and chess.player == 0 and chess.currentStep % 2 != 0:
|
|
|
# if chess.playerLocation(playerx, playery, canvas, blackch, whitech):
|
|
|
print("ai 落子")
|
|
|
if chess.aiLocation(canvas, blackch, whitech):
|
|
|
print("ai 落子成功")
|
|
|
for i in chess.OvaloneNew:
|
|
|
canvas.delete(i)
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 0, 1, chess.chessMode, blackch, whitech, photos1, photos2)
|
|
|
chess.Gameover = chess.chessCheck()
|
|
|
print("chess.Gameover", chess.Gameover)
|
|
|
if chess.winFlag == 1:
|
|
|
chess.resultshow(root, canvas, whitech, blackch)
|
|
|
root.update()
|
|
|
|
|
|
# 最新的得到建议的函数
|
|
|
def Suggestion(self):
|
|
|
if chess.gameEnd() or chess.currentStep == 0:
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='请在对局中使用!')
|
|
|
return
|
|
|
# 滚动框
|
|
|
global Text
|
|
|
x = root.winfo_x()
|
|
|
y = root.winfo_y()
|
|
|
# x = 10
|
|
|
# y = 10
|
|
|
root.geometry('1000x800+' + str(x) + '+' + str(y))
|
|
|
Text = st.ScrolledText(root, bg='#522418', font=('Arial', 12), bd=2, relief='groove') # 创建一个带滚动条的文本框,用于展示计算过程
|
|
|
Text.place(x=0, y=685, height=100, width=1000)
|
|
|
Text.configure(foreground='white')
|
|
|
Text.delete('1.0', 'end')
|
|
|
Text.insert('2.0', '落子建议步骤:\n')
|
|
|
if chess.winFlag != 1:
|
|
|
if chess.depth >= 9:
|
|
|
chess.depth = 8
|
|
|
if chess.chessMode == 1:
|
|
|
color = 2
|
|
|
elif chess.chessMode == 2:
|
|
|
color = 1
|
|
|
elif chess.chessMode == 0:
|
|
|
if chess.player == 1 and chess.player2 == 0:
|
|
|
color = 2
|
|
|
elif chess.player == 0 and chess.player2 == 1:
|
|
|
color = 1
|
|
|
pos, message = chess.returnPostionNew(chess.depth, color) # 调用估值函数
|
|
|
Text.insert('end', '最佳落子点为:{}\n'.format(chess.maxScorePos))
|
|
|
Text.insert('end', message)
|
|
|
print("pos:", pos)
|
|
|
# 画点
|
|
|
drawChess(canvas, pos, chess)
|
|
|
root.update()
|
|
|
|
|
|
|
|
|
class mainControl():
|
|
|
def __init__(self):
|
|
|
self.player1 = HumanPlayer()
|
|
|
self.player2 = RobotPlayer()
|
|
|
self.current_player = self.player1
|
|
|
|
|
|
def switch_mode(self, chess):
|
|
|
# 切换当前模式
|
|
|
if chess.chessMode == 1:
|
|
|
self.player1 = HumanPlayer()
|
|
|
self.player2 = RobotPlayer()
|
|
|
self.current_player = self.player1
|
|
|
elif chess.chessMode == 2:
|
|
|
# 先落一个黑子,然后与chess.chessMode == 1相同
|
|
|
self.player1 = RobotPlayer()
|
|
|
self.player2 = HumanPlayer()
|
|
|
self.current_player = self.player2
|
|
|
elif chess.chessMode == 0:
|
|
|
self.player1 = HumanPlayer()
|
|
|
self.player2 = HumanPlayer()
|
|
|
self.current_player = self.player1
|
|
|
print(type(self.player1))
|
|
|
print(type(self.player2))
|
|
|
|
|
|
|
|
|
def switch_player(self):
|
|
|
# 切换当前玩家
|
|
|
if self.current_player == self.player1:
|
|
|
self.current_player = self.player2
|
|
|
else:
|
|
|
self.current_player = self.player1
|
|
|
print(self.current_player)
|
|
|
|
|
|
def on_mouse_click(self, chessdata):
|
|
|
# 如果是人机对弈
|
|
|
if type(self.player1) is not type(self.player2):
|
|
|
# 处理鼠标点击事件
|
|
|
self.current_player.NextMove(chessdata, chess, blackChPieceImg, whiteChPieceImg)
|
|
|
# 落子后切换玩家
|
|
|
self.switch_player()
|
|
|
# print("on_mouse_click 换!")
|
|
|
self.current_player.NextMove(chessdata, chess, blackChPieceImg, whiteChPieceImg)
|
|
|
# 落子后切换玩家
|
|
|
self.switch_player()
|
|
|
# print("on_mouse_click 换!")
|
|
|
# 如果是玩家对弈或者机器人对弈
|
|
|
elif type(self.player1) is type(self.player2):
|
|
|
# 处理鼠标点击事件
|
|
|
self.current_player.NextMove(chessdata, chess, blackChPieceImg, whiteChPieceImg)
|
|
|
# 落子后切换玩家
|
|
|
self.switch_player()
|
|
|
|
|
|
def suggestion(self):
|
|
|
# 处理落子推荐
|
|
|
self.current_player.Suggestion()
|
|
|
|
|
|
mainCon = mainControl()
|
|
|
canvas.bind('<Button-1>', mainCon.on_mouse_click)
|
|
|
|
|
|
|
|
|
# 图片创建
|
|
|
blackChPieceImg = Image.open(path + "image/黑子-小.png").resize((40, 40))
|
|
|
blackChPieceImg = ImageTk.PhotoImage(blackChPieceImg)
|
|
|
whiteChPieceImg = Image.open(path + "image/白子-小.png").resize((40, 40))
|
|
|
whiteChPieceImg = ImageTk.PhotoImage(whiteChPieceImg)
|
|
|
result = Image.open(path + "image/resultshow.PNG").resize((100, 42))
|
|
|
result = ImageTk.PhotoImage(result)
|
|
|
photos1 = Image.open(path + "image/上方button-选中.png").resize((110, 45))
|
|
|
photos1 = ImageTk.PhotoImage(photos1)
|
|
|
photos2 = Image.open(path + "image/上方button-未选中.png").resize((110, 45))
|
|
|
photos2 = ImageTk.PhotoImage(photos2)
|
|
|
|
|
|
# 棋盘
|
|
|
# photoQipan=Image.open("image/棋盘-空.png").resize((730,700))
|
|
|
# photoQipan=ImageTk.PhotoImage(photoQipan)
|
|
|
# canvas.create_image(10,350,image=photoQipan,anchor=W)
|
|
|
|
|
|
# 当前落子方
|
|
|
# photocur = Image.open("image/当前落子方背景.png").resize((100, 30))
|
|
|
# photocur = ImageTk.PhotoImage(photocur)
|
|
|
# canvas.create_image(720, 40, image = photocur,anchor=W)
|
|
|
canvas.create_text(800, 90, text='当前落子方', font='Arial,10', fill='white')
|
|
|
# lab_name = Label(root, text="当前落子方", font='Arial,10',fg='white',image=photocur,compound=CENTER)
|
|
|
# lab_name.place(x=630, y=85, width=100, height=30)
|
|
|
# 当前落子方跳选框
|
|
|
canvas.create_image(750, 145, image=photos2, anchor=W)
|
|
|
canvas.create_image(870, 145, image=photos2, anchor=W)
|
|
|
|
|
|
# 胜负判定
|
|
|
photoresult = Image.open(path + "image/胜负判定背景.PNG").resize((100, 30))
|
|
|
photoresult = ImageTk.PhotoImage(photoresult)
|
|
|
# canvas.create_image(630, 200, image = photoresult,anchor=W)
|
|
|
cur_result = Label(root, text='胜负判定', font='Arial,10', fg='white', image=photoresult, compound=CENTER)
|
|
|
cur_result.config(bg='#8B7355')
|
|
|
cur_result.place(x=750, y=190, width=100, height=30)
|
|
|
|
|
|
# 公告栏
|
|
|
photonotice = Image.open(path + "image/公告栏.png").resize((230, 130))
|
|
|
photonotice = ImageTk.PhotoImage(photonotice)
|
|
|
canvas.create_image(750, 300, image=photonotice, anchor=W)
|
|
|
|
|
|
|
|
|
# 按钮复盘
|
|
|
def review():
|
|
|
if chess.Reviewflag != 1:
|
|
|
chess.Reviewflag = 1
|
|
|
for x in range(19):
|
|
|
for y in range(19):
|
|
|
if chess.chessData[x][y]['Cstep'] != 0 and chess.chessData[x][y]['Cstate'] == 2:
|
|
|
reviewnum = Label(root, text=str(chess.chessData[x][y]['Cstep']), bg='#000', fg='#fff', font=("黑体", 8), width=1, height=1)
|
|
|
reviewnum.place(x=x*36.8 + 41 - 7, y=y*34.6 + 21 - 9, anchor='nw')
|
|
|
chess.Reviewlabel[x][y] = reviewnum
|
|
|
elif chess.chessData[x][y]['Cstep'] != 0 and chess.chessData[x][y]['Cstate'] == 1:
|
|
|
reviewnum = Label(root, text=str(chess.chessData[x][y]['Cstep']), bg='#fff', fg='#000', font=("黑体", 8), width=1, height=1)
|
|
|
reviewnum.place(x=x*36.8 + 41 - 7, y=y*34.6 + 21 - 9, anchor='nw')
|
|
|
chess.Reviewlabel[x][y] = reviewnum
|
|
|
root.update()
|
|
|
|
|
|
|
|
|
photoreview = Image.open(path + "image/复盘.png").resize((100, 50))
|
|
|
photoreview = ImageTk.PhotoImage(photoreview)
|
|
|
# canvas.create_image(720, 300, image = photoresult,anchor=W)
|
|
|
btn_review = Button(root, text='复盘', font='Arial,12', width=85, height=35,
|
|
|
image=photoreview, command=review, bd=0)
|
|
|
|
|
|
btn_review.place(x=750, y=400)
|
|
|
|
|
|
|
|
|
# 按钮悔棋
|
|
|
def regretChess():
|
|
|
if chess.winFlag == 0:
|
|
|
# 首先撤销复盘,防止删不掉
|
|
|
concelReview()
|
|
|
global regretnum
|
|
|
regretnum = 1
|
|
|
if chess.currentStep == 1 and chess.chessMode == 2:
|
|
|
regretxFLAG = xregretFLAG[chess.currentStep - regretnum]
|
|
|
regretyFLAG = yregretFLAG[chess.currentStep - regretnum]
|
|
|
canvas.delete(chess.Chessimg[regretxFLAG][regretyFLAG])
|
|
|
chess.chessData[regretxFLAG][regretyFLAG]['Cstate'] = 0
|
|
|
chess.chessData[regretxFLAG][regretyFLAG]['Cstep'] = 0
|
|
|
chess.currentStep -= 1
|
|
|
chess.playing(2, root, canvas)
|
|
|
if chess.chessMode == 1 or chess.chessMode == 2 or chess.chessMode == 4:
|
|
|
# print(xregretFLAG)
|
|
|
# print(yregretFLAG)
|
|
|
for i in range(2):
|
|
|
regretxFLAG = xregretFLAG[chess.currentStep - regretnum]
|
|
|
regretyFLAG = yregretFLAG[chess.currentStep - regretnum]
|
|
|
canvas.delete(chess.Chessimg[regretxFLAG][regretyFLAG])
|
|
|
chess.chessData[regretxFLAG][regretyFLAG]['Cstate'] = 0
|
|
|
chess.chessData[regretxFLAG][regretyFLAG]['Cstep'] = 0
|
|
|
chess.currentStep -= 1
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
if chess.chessMode == 0:
|
|
|
regretxFLAG = xregretFLAG[chess.currentStep - regretnum]
|
|
|
regretyFLAG = yregretFLAG[chess.currentStep - regretnum]
|
|
|
canvas.delete(chess.Chessimg[regretxFLAG][regretyFLAG])
|
|
|
chess.chessData[regretxFLAG][regretyFLAG]['Cstate'] = 0
|
|
|
chess.chessData[regretxFLAG][regretyFLAG]['Cstep'] = 0
|
|
|
chess.currentStep -= 1
|
|
|
if chess.currentStep % 2 == 0:
|
|
|
chess.player = 1
|
|
|
chess.player2 = 0
|
|
|
chess.curLocation(canvas, 0, 1, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
elif chess.currentStep % 2 != 0:
|
|
|
chess.player = 0
|
|
|
chess.player2 = 1
|
|
|
chess.curLocation(canvas, 1, 0, chess.chessMode, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
elif chess.winFlag == 1:
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message='对局已经结束了!')
|
|
|
root.update()
|
|
|
|
|
|
|
|
|
photoregretch = Image.open(path + "image/悔棋.png").resize((100, 50))
|
|
|
photoregretch = ImageTk.PhotoImage(photoregretch)
|
|
|
btn_regret = Button(root, text='悔棋', font='Arial,12', width=85, height=35,
|
|
|
image=photoregretch, command=regretChess, bd=0)
|
|
|
btn_regret.place(x=850, y=400)
|
|
|
|
|
|
|
|
|
# 按钮撤销复盘
|
|
|
def concelReview():
|
|
|
if chess.Reviewflag == 1:
|
|
|
chess.Reviewflag = 0
|
|
|
for x in range(19):
|
|
|
for y in range(19):
|
|
|
if chess.chessData[x][y]['Cstep'] != 0 and chess.Reviewlabel[x][y] != 0:
|
|
|
chess.Reviewlabel[x][y].destroy()
|
|
|
chess.Reviewlabel[x][y] = 0
|
|
|
root.update()
|
|
|
|
|
|
|
|
|
photoconcel = Image.open(path + "image/撤销复盘.png").resize((100, 50))
|
|
|
photoconcel = ImageTk.PhotoImage(photoconcel)
|
|
|
btn_concel = Button(root, text='撤销复盘', font='Arial,12', width=85, height=35, image=photoconcel,
|
|
|
command=concelReview, bd=0)
|
|
|
btn_concel.place(x=750, y=460)
|
|
|
|
|
|
|
|
|
photoSuggest = Image.open(path + "image/落子建议按钮.png").resize((100, 50))
|
|
|
photoSuggest = ImageTk.PhotoImage(photoSuggest)
|
|
|
btnSuggest = Button(root, text='落子建议', font='Arial,12', width=85, height=35,
|
|
|
image=photoSuggest, command=mainCon.suggestion, bd=0)
|
|
|
btnSuggest.place(x=850, y=460)
|
|
|
|
|
|
|
|
|
# 按钮局面评估
|
|
|
def curNow():
|
|
|
|
|
|
if chess.depth >= 9:
|
|
|
chess.depth = 8
|
|
|
if chess.chessMode == 1:
|
|
|
color = 2
|
|
|
elif chess.chessMode == 2:
|
|
|
color = 1
|
|
|
chess.returnChess(chess.depth, color) # 调用估值函数
|
|
|
elif chess.chessMode == 0:
|
|
|
if chess.player == 1 and chess.player2 == 0:
|
|
|
color = 2
|
|
|
elif chess.player == 0 and chess.player2 == 1:
|
|
|
color = 1
|
|
|
chess.returnChess(chess.depth, color) # 调用估值函数
|
|
|
if chess.counts / chess.newCount == 1:
|
|
|
OwnCounter = random.uniform(0.5, 0.6)
|
|
|
else:
|
|
|
OwnCounter = chess.counts / chess.newCount
|
|
|
if color == 2:
|
|
|
# 1.判断x-轴是否活四或者连五
|
|
|
for x in range(15):
|
|
|
for y in range(19):
|
|
|
if (chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x + 1][y]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 2][y]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 3][y]['Cstate'] == 1 and chess.chessData[x + 4][y]['Cstate'] == 0 and
|
|
|
chess.chessData[x - 1][y]['Cstate'] == 0) or \
|
|
|
(chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x + 1][y]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 2][y]['Cstate'] == 1 and chess.chessData[x + 3][y]['Cstate'] == 1
|
|
|
and chess.chessData[x + 4][y]['Cstate'] == 1):
|
|
|
OwnCounter = OwnCounter - OwnCounter
|
|
|
# 2.判断y-轴是否活四或者连五
|
|
|
for x in range(19):
|
|
|
for y in range(15):
|
|
|
if (chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x][y + 1]['Cstate'] == 1 and
|
|
|
chess.chessData[x][y + 2]['Cstate'] == 1 and
|
|
|
chess.chessData[x][y + 3]['Cstate'] == 1 and chess.chessData[x][y + 4]['Cstate'] == 0 and
|
|
|
chess.chessData[x][y - 1]['Cstate'] == 0) or (
|
|
|
chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x][y + 1]['Cstate'] == 1 and
|
|
|
chess.chessData[x][y + 2]['Cstate'] == 1 and
|
|
|
chess.chessData[x][y + 3]['Cstate'] == 1 and chess.chessData[x][y + 4]['Cstate'] == 1):
|
|
|
OwnCounter = OwnCounter - OwnCounter
|
|
|
# 3.判断右上-左下是否活四或者连五
|
|
|
for x in range(15):
|
|
|
for y in range(4, 15):
|
|
|
if (chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x + 1][y - 1]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 2][y - 2]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 3][y - 3]['Cstate'] == 1 and chess.chessData[x + 4][y - 4]['Cstate'] == 0 and
|
|
|
chess.chessData[x - 1][y + 1]['Cstate'] == 0) or \
|
|
|
(chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x + 1][y - 1]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 2][y - 2]['Cstate'] == 1 and chess.chessData[x + 3][y - 3][
|
|
|
'Cstate'] == 1 and
|
|
|
chess.chessData[x + 4][y - 4]['Cstate'] == 1):
|
|
|
OwnCounter = OwnCounter - OwnCounter
|
|
|
# 4.判断左上-右下是否活四或者连五
|
|
|
for x in range(15):
|
|
|
for y in range(15):
|
|
|
if (chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x + 1][y + 1]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 2][y + 2]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 3][y + 3]['Cstate'] == 1 and chess.chessData[x + 4][y + 4][
|
|
|
'Cstate'] == 0 and chess.chessData[x - 1][y - 1]['Cstate'] == 0) or (
|
|
|
chess.chessData[x][y]['Cstate'] == 1 and chess.chessData[x + 1][y + 1]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 2][y + 2]['Cstate'] == 1 and
|
|
|
chess.chessData[x + 3][y + 3]['Cstate'] == 1 and chess.chessData[x + 4][y + 4][
|
|
|
'Cstate'] == 1):
|
|
|
OwnCounter = OwnCounter - OwnCounter
|
|
|
OwnCounter = OwnCounter - OwnCounter
|
|
|
|
|
|
OtherCouter = 1 - OwnCounter
|
|
|
msg = '当前落子方的胜率为' + str(round(OwnCounter, 4)*100) + '%!\n' + \
|
|
|
'当前对方的胜率为' + str(round(OtherCouter, 4)*100) + '%!'
|
|
|
tkinter.messagebox.showinfo(title='信息提示!', message=msg)
|
|
|
|
|
|
|
|
|
photocurnow = Image.open(path + "image/局面评估.png").resize((100, 50))
|
|
|
photocurnow = ImageTk.PhotoImage(photocurnow)
|
|
|
btn_elevalue = Button(root, text='局面评估', font='Arial,12', width=85, height=35, image=photocurnow,
|
|
|
command=curNow, bd=0)
|
|
|
btn_elevalue.place(x=750, y=520)
|
|
|
|
|
|
|
|
|
photostart = Image.open(path +"image/true.jpg").resize((100, 50))
|
|
|
photostart = ImageTk.PhotoImage(photostart)
|
|
|
btn_reset = Button(root, text='人机对战', font='Arial,12', width=85, height=35, image=photostart,
|
|
|
command=peoCompWhite, bg='#FFA500', bd=0)
|
|
|
btn_reset.place(x=800, y=580)
|
|
|
|
|
|
|
|
|
# 按钮重新开始
|
|
|
def refresh():
|
|
|
# 删除棋盘上可能的复盘数字
|
|
|
concelReview()
|
|
|
|
|
|
# 删除棋子
|
|
|
for x in range(19):
|
|
|
for y in range(19):
|
|
|
if chess.chessData[x][y]['Cstate'] != 0:
|
|
|
canvas.delete(chess.Chessimg[x][y])
|
|
|
if chess.Reviewlabel[x][y] != 0:
|
|
|
chess.Reviewlabel[x][y].destroy()
|
|
|
chess.chessData[x][y]['Cstate'] = 0
|
|
|
chess.chessData[x][y]['Cstep'] = 0
|
|
|
chess.Chessimg[x][y] = 0
|
|
|
chess.Reviewlabel[x][y] = 0
|
|
|
|
|
|
# 删除棋盘上可能留有的建议落子图
|
|
|
for i in chess.OvaloneNew:
|
|
|
canvas.delete(i)
|
|
|
|
|
|
# 这里需要重新添加一个刷新的东西类似于geometry这种,因为刷新有时候没有将画的建议位置删除
|
|
|
# x = root.winfo_x()
|
|
|
# y = root.winfo_y()
|
|
|
x = 10
|
|
|
y = 10
|
|
|
root.geometry('1000x700+' + str(x) + '+' + str(y))
|
|
|
|
|
|
canvas.create_image(750, 145, image=photos2, anchor=W)
|
|
|
canvas.create_image(870, 145, image=photos2, anchor=W)
|
|
|
photoqizi = Image.open(path + "image/棋盘-空.png").resize((730, 700))
|
|
|
photoqizi = ImageTk.PhotoImage(photoqizi)
|
|
|
canvas.create_image(10, 350, image=photoqizi, anchor=W)
|
|
|
cross(canvas)
|
|
|
|
|
|
# 重置棋盘的变量
|
|
|
chess.currentStep = 0 # 当前落子步数
|
|
|
chess.Gameover = 0 # 对局是否结束
|
|
|
chess.depth = 0 # 在棋盘搜索广度
|
|
|
chess.player = 0 # 轮到下棋的标志,1=下,0=不下
|
|
|
chess.myColor = 0 # 玩家选择的棋子颜色
|
|
|
chess.player2Color = 0 # 玩家2的棋子颜色
|
|
|
chess.winFlag = 0 # 胜利标志
|
|
|
|
|
|
# 清空结果展示
|
|
|
if chess.winFlag == 1:
|
|
|
chess.resultshow(root, canvas, whiteChPieceImg, blackChPieceImg)
|
|
|
|
|
|
# 重置玩家和变量
|
|
|
mainCon.switch_mode(chess)
|
|
|
chess.playing(chess.chessMode, root, canvas, blackChPieceImg, whiteChPieceImg, photos1, photos2)
|
|
|
|
|
|
root.update()
|
|
|
|
|
|
|
|
|
photorefresh = Image.open(path + "image/重新开始按钮.png").resize((100, 50))
|
|
|
photorefresh = ImageTk.PhotoImage(photorefresh)
|
|
|
btn_reset = Button(root, text='重新开始', font='Arial,12', width=85, height=35,
|
|
|
image=photorefresh, command=refresh, bg='#FFA500', bd=0)
|
|
|
btn_reset.place(x=850, y=520)
|
|
|
|
|
|
canvas.pack()
|
|
|
root.mainloop()
|