You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
454 lines
17 KiB
454 lines
17 KiB
from abc import ABC, abstractmethod
|
|
from tkinter import Tk, Canvas
|
|
import tkinter as tk
|
|
from functools import partial
|
|
count = 0
|
|
|
|
|
|
class chess(ABC):
|
|
|
|
def __init__(self, x:int, y:int, color:bool, type:int)->None:
|
|
self.x = x
|
|
self.y = y
|
|
self.color = color
|
|
self.type = type
|
|
|
|
def move_able(self, map:map, x1:int, y1:int)->bool:
|
|
chess_map = map.chess_map
|
|
try:
|
|
chess_color = map.chess_map[x1][y1].color
|
|
color = self.color
|
|
if chess_color < 2 and color != chess_color or chess_color == 2:
|
|
return True
|
|
else:
|
|
return False
|
|
except:
|
|
print((x1, y1))
|
|
print((len(chess_map), len(chess_map[0])))
|
|
return False
|
|
|
|
def if_blank(self, map:map, x1:int, y1:int)->bool:
|
|
chess_color = map.chess_map[x1][y1].color
|
|
if chess_color == 2:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def if_enemy(self, map:map, x1:int, y1:int)->bool:
|
|
chess_color = map.chess_map[x1][y1].color
|
|
color = self.color
|
|
if chess_color < 2 and chess_color != color:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def within_range(self, map:map, x1:int, y1:int)->bool:
|
|
edge = map.edge
|
|
row = map.row
|
|
col = map.col
|
|
return edge <= x1 < edge + col and edge <= y1 < edge + row
|
|
|
|
def not_pass_river(self, map:map, y1)->bool:
|
|
y = map.river[self.color]
|
|
return y[0] <= y1 <= y[1]
|
|
|
|
@abstractmethod
|
|
def get_all_moveable_position(self, map:map):
|
|
pass
|
|
|
|
@abstractmethod
|
|
def __repr__(self):
|
|
pass
|
|
|
|
class chess_che(chess):
|
|
|
|
vector = [(1, 0), (0, 1), (-1, 0), (0, -1)]
|
|
def get_all_moveable_position(self, map:map)->list:
|
|
x1 = self.x
|
|
y1 = self.y
|
|
vector = self.vector
|
|
ans = []
|
|
if_enemy = self.if_enemy
|
|
if_blank = self.if_blank
|
|
for i in vector:
|
|
delta_x = i[0]
|
|
delta_y = i[1]
|
|
x = x1 + delta_x
|
|
y = y1 + delta_y
|
|
while if_blank(map, x, y):
|
|
ans.append((x, y))
|
|
x += delta_x
|
|
y += delta_y
|
|
if if_enemy(map, x, y):
|
|
ans.append((x, y))
|
|
return ans
|
|
|
|
def __repr__(self):
|
|
return "车"
|
|
|
|
class chess_ma(chess):
|
|
|
|
vector = [(1, 2, 0, 1), (1, -2, 0, -1), (2, 1, 1, 0), (2, -1, 1, 0), (-2, 1, -1, 0), (-1, 2, 0, 1), (-1, -2, 0, -1), (-2, -1, -1, 0)]
|
|
def get_all_moveable_position(self, map:map)->list:
|
|
x = self.x
|
|
y = self.y
|
|
vector = self.vector
|
|
move_able = self.move_able
|
|
if_blank = self.if_blank
|
|
return [(x + i[0], y + i[1]) for i in vector if move_able(map, x + i[0], y + i[1]) and if_blank(map, x + i[2], y + i[3])]
|
|
|
|
def __repr__(self):
|
|
return "马"
|
|
|
|
class chess_xiang(chess):
|
|
vector = [(2, 2), (2, -2), (-2, 2), (-2, -2)]
|
|
def get_all_moveable_position(self, map:map):
|
|
x = self.x
|
|
y = self.y
|
|
vector = self.vector
|
|
move_able = self.move_able
|
|
if_blank = self.if_blank
|
|
not_pass_river = self.not_pass_river
|
|
return [(x + i[0], y + i[1]) for i in vector if move_able(map, x + i[0], y + i[1]) and if_blank(map, x + i[0] // 2, y + i[1] // 2) and not_pass_river(map, y + i[1])]
|
|
|
|
def __repr__(self):
|
|
return "相"
|
|
|
|
class chess_shi(chess):
|
|
vector = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
|
|
def get_all_moveable_position(self, map:map):
|
|
x = self.x
|
|
y = self.y
|
|
vector = self.vector
|
|
pos = map.handsome[self.color]
|
|
if x == pos[0] and y == pos[1]:
|
|
move_able = self.move_able
|
|
return [(x + i[0], y + i[1]) for i in vector if move_able(map, x + i[0], y + i[1])]
|
|
|
|
else:
|
|
if(self.move_able(map, pos[0], pos[1])):
|
|
return [pos]
|
|
else:
|
|
return []
|
|
|
|
def __repr__(self):
|
|
return "仕"
|
|
|
|
class chess_jiang(chess):
|
|
vector = [(-1, 0), (0, -1), (1, 0), (0, 1)]
|
|
def within_range(self, map:map, x1:int, y1:int)->bool:
|
|
pos = map.handsome[self.color]
|
|
x = pos[0]
|
|
y = pos[1]
|
|
return x - 1 <= x1 <= x + 1 and y - 1 <= y1 <= y + 1
|
|
|
|
def get_all_moveable_position(self, map:map):
|
|
x = self.x
|
|
y = self.y
|
|
vector = self.vector
|
|
move_able = self.move_able
|
|
within_range = self.within_range
|
|
return [(x + i[0], y + i[1]) for i in vector if move_able(map, x + i[0], y + i[1]) and within_range(map, x + i[0], y + i[1])]
|
|
|
|
def __repr__(self):
|
|
return "将"
|
|
|
|
class chess_pao(chess):
|
|
|
|
vector = [(1, 0), (0, 1), (-1, 0), (0, -1)]
|
|
|
|
def get_all_moveable_position(self, map:map):
|
|
x = self.x
|
|
y = self.y
|
|
vector = self.vector
|
|
if_blank = self.if_blank
|
|
if_enemy = self.if_enemy
|
|
ans = []
|
|
for i in vector:
|
|
delta_x = i[0]
|
|
delta_y = i[1]
|
|
x1 = x + delta_x
|
|
y1 = y + delta_y
|
|
while if_blank(map, x1, y1):
|
|
ans.append((x1, y1))
|
|
x1 += delta_x
|
|
y1 += delta_y
|
|
x1 += delta_x
|
|
y1 += delta_y
|
|
while if_blank(map, x1, y1):
|
|
x1 += delta_x
|
|
y1 += delta_y
|
|
if if_enemy(map, x1, y1):
|
|
ans.append((x1, y1))
|
|
return ans
|
|
|
|
def __repr__(self):
|
|
return "炮"
|
|
|
|
class chess_bing(chess):
|
|
vector = [[[(0, 1)], [(1, 0), (-1, 0), (0, 1)]], [[(0, -1)], [(1, 0), [-1, 0], (0, -1)]]]
|
|
def get_all_moveable_position(self, map:map):
|
|
move_able = self.move_able
|
|
color = self.color
|
|
x = self.x
|
|
y = self.y
|
|
vector = self.vector[color][1 - self.not_pass_river(map, y)]
|
|
return [(x + i[0], y + i[1]) for i in vector if move_able(map, x + i[0], y + i[1])]
|
|
|
|
def __repr__(self):
|
|
return "兵"
|
|
|
|
class chess_blank(chess):
|
|
def __init__(self):
|
|
self.color = 2
|
|
|
|
def get_all_moveable_position(self, map:map):
|
|
pass
|
|
|
|
def __repr__(self):
|
|
return " "
|
|
|
|
class chess_block(chess):
|
|
def __init__(self):
|
|
self.color = 3
|
|
|
|
def get_all_moveable_position(self, map:map):
|
|
pass
|
|
|
|
def __repr__(self):
|
|
return "**"
|
|
|
|
|
|
|
|
class process:
|
|
def __init__(self, start:tuple, end:tuple, eaten_chess:chess)->None:
|
|
self.start = start
|
|
self.end = end
|
|
self.eaten_chess = eaten_chess
|
|
|
|
class map:
|
|
chess_map = []
|
|
col = 9
|
|
row = 10
|
|
edge = 2
|
|
river = [(edge, edge + row // 2 - 1), (edge + row // 2, edge + row)]
|
|
handsome = [(edge + col // 2, edge + 1), (edge + col // 2, edge + row - 2)]
|
|
exist_chess = []
|
|
score = 0
|
|
score_standard = [100, 80, 40, 30, 10000, 80, 20]
|
|
level_score = [10000000 if i % 2 == 0 else -10000000 for i in range(100)]
|
|
lock = [0, 0, 0] #0: 未锁定 1:已锁定
|
|
def __init__(self):
|
|
col = self.col
|
|
row = self.row
|
|
edge = self.edge
|
|
chess_map = [[chess_blank() if edge <= i < edge + col and edge <= j < row + edge else chess_block() for j in range(row + edge * 2)] for i in range(col + edge * 2)]
|
|
with open("map_data.txt", "r") as fp:
|
|
map_data = fp.readlines()
|
|
for data in map_data:
|
|
data_list = data.split()
|
|
x = int(data_list[0]) + edge
|
|
y = int(data_list[1]) + edge
|
|
color = int(data_list[2])
|
|
type = int(data_list[3])
|
|
if type == 0:
|
|
chess_map[x][y] = chess_che(x , y, color, type)
|
|
chess_map[x][edge * 2 + row - 1 - y] = chess_che(x, edge * 2 + row - 1 - y, 1 - color, type)
|
|
elif type == 1:
|
|
chess_map[x][y] = chess_ma(x , y, color, type)
|
|
chess_map[x][edge * 2 + row - 1 - y] = chess_ma(x, edge * 2 + row - 1 - y, 1 - color, type)
|
|
elif type == 2:
|
|
chess_map[x][y] = chess_xiang(x , y, color, type)
|
|
chess_map[x][edge * 2 + row - 1 - y] = chess_xiang(x, edge * 2 + row - 1 - y, 1 - color, type)
|
|
elif type == 3:
|
|
chess_map[x][y] = chess_shi(x , y, color, type)
|
|
chess_map[x][edge * 2 + row - 1 - y] = chess_shi(x, edge * 2 + row - 1 - y, 1 - color, type)
|
|
elif type == 4:
|
|
chess_map[x][y] = chess_jiang(x , y, color, type)
|
|
chess_map[x][edge * 2 + row - 1 - y] = chess_jiang(x, edge * 2 + row - 1 - y, 1 - color, type)
|
|
elif type == 5:
|
|
chess_map[x][y] = chess_pao(x , y, color, type)
|
|
chess_map[x][edge * 2 + row - 1 - y] = chess_pao(x, edge * 2 + row - 1 - y, 1 - color, type)
|
|
elif type == 6:
|
|
chess_map[x][y] = chess_bing(x , y, color, type)
|
|
chess_map[x][edge * 2 + row - 1 - y] = chess_bing(x, edge * 2 + row - 1 - y, 1 - color, type)
|
|
self.chess_map = chess_map
|
|
|
|
def show(self)->None:
|
|
row = self.row
|
|
col = self.col
|
|
edge = self.edge
|
|
chess_map = self.chess_map
|
|
for i in range(row + edge * 2):
|
|
for j in range(col + edge * 2):
|
|
print(chess_map[j][i], end = "")
|
|
print()
|
|
|
|
def draw(self, root, canvas):
|
|
canvas.delete(tk.ALL)
|
|
canvas.create_rectangle(50, 50, 50 + 50 * 8, 50 + 50 * 9)
|
|
for i in range(100, 100 + 50 * 8, 50): #画横线
|
|
canvas.create_line(50, i, 50 + 50 * 8, i)
|
|
for i in range(100, 100 + 50 * 8, 50): #画竖线
|
|
canvas.create_line(i, 50, i, 50 + 4 * 50)
|
|
canvas.create_line(i, 50 + 50 * 5, i, 50 + 50 * 9)
|
|
chess_map = self.chess_map
|
|
for i in chess_map:
|
|
for j in i:
|
|
if j.color < 2:
|
|
canvas.create_oval(50 * (j.x - 1) - 20, 50 * (j.y - 1) - 20, 50 * (j.x - 1) + 20, 50 * (j.y - 1) + 20, fill = "white")
|
|
canvas.create_text(50 * (j.x - 1), 50 * (j.y - 1), text = j.__repr__(), fill = "black" if j.color == 0 else "red", font=('Old English Text MT',20))
|
|
|
|
def get_ans(self, pro:process, cur_depth:int, max_depth:int, color:bool, primer_color:bool, cur_score):
|
|
global count
|
|
count += 1
|
|
x2, y2 = pro.end
|
|
chess_end = self.chess_map[x2][y2]
|
|
level_score = self.level_score
|
|
score_standard = self.score_standard
|
|
if cur_depth % 2 == 1 and cur_depth > 1: #如果是奇数
|
|
if level_score[cur_depth - 1] < cur_score - 200:
|
|
return cur_score + 100
|
|
elif cur_depth % 2 == 0 and cur_depth > 1:
|
|
if level_score[cur_depth - 1] > cur_score + 200:
|
|
return cur_score - 100
|
|
if cur_depth == max_depth:
|
|
return cur_score
|
|
get_ans = self.get_ans
|
|
chess_map = self.chess_map
|
|
x3, y3 = pro.start
|
|
chess_start = chess_map[x3][y3]
|
|
chess_map[x3][y3] = chess_blank()
|
|
chess_map[x2][y2] = chess_start
|
|
chess_start.x = x2
|
|
chess_start.y = y2
|
|
if cur_depth % 2 == 1: #奇数找最大值
|
|
score = -1000000
|
|
for i in chess_map:
|
|
for j in i:
|
|
if j.color == color:
|
|
x1 = j.x
|
|
y1 = j.y
|
|
for x, y in j.get_all_moveable_position(self):
|
|
pro = process((x1, y1), (x, y), chess_map[x][y])
|
|
if chess_map[x][y].color == 1 - primer_color:
|
|
t = get_ans(pro, cur_depth + 1, max_depth, 1 - color, primer_color, cur_score + score_standard[chess_map[x][y].type])
|
|
elif chess_map[x][y].color == primer_color: #被吃加10点debuff
|
|
t = get_ans(pro, cur_depth + 1, max_depth, 1 - color, primer_color, cur_score - score_standard[chess_map[x][y].type] - 10)
|
|
else:
|
|
t = get_ans(pro, cur_depth + 1, max_depth, 1 - color, primer_color, cur_score)
|
|
if t > score:
|
|
score = t
|
|
if score > level_score[cur_depth]:
|
|
level_score[cur_depth] = score
|
|
|
|
|
|
else:
|
|
score = 1000000
|
|
for i in chess_map:
|
|
for j in i:
|
|
if j.color == color:
|
|
x1 = j.x
|
|
y1 = j.y
|
|
for x, y in j.get_all_moveable_position(self):
|
|
pro = process((x1, y1), (x, y), chess_map[x][y])
|
|
if chess_map[x][y].color == 1 - primer_color:
|
|
t = get_ans(pro, cur_depth + 1, max_depth, 1 - color, primer_color, cur_score + score_standard[chess_map[x][y].type])
|
|
elif chess_map[x][y].color == primer_color: #同理
|
|
t = get_ans(pro, cur_depth + 1, max_depth, 1 - color, primer_color, cur_score - score_standard[chess_map[x][y].type] - 10)
|
|
else:
|
|
t = get_ans(pro, cur_depth + 1, max_depth, 1 - color, primer_color, cur_score)
|
|
if t < score:
|
|
score = t
|
|
if score < level_score[cur_depth]:
|
|
level_score[cur_depth] = score
|
|
chess_start.x = x3
|
|
chess_start.y = y3
|
|
chess_map[x3][y3] = chess_start
|
|
chess_map[x2][y2] = chess_end
|
|
return score
|
|
|
|
|
|
def next(self, pro):
|
|
chess_map = self.chess_map
|
|
x1 = pro.start[0]
|
|
y1 = pro.start[1]
|
|
x2 = pro.end[0]
|
|
y2 = pro.end[1]
|
|
chess_start = chess_map[x1][y1]
|
|
chess_start.x = x2
|
|
chess_start.y = y2
|
|
chess_map[x2][y2] = chess_start
|
|
chess_map[x1][y1] = chess_blank()
|
|
|
|
def get_pro(self, depth):
|
|
score = -10000
|
|
get_ans = self.get_ans
|
|
chess_map = self.chess_map
|
|
score_standard = self.score_standard
|
|
for i in chess_map:
|
|
for j in i:
|
|
if j.color == 1:
|
|
for x, y in j.get_all_moveable_position(self):
|
|
pro = process((j.x, j.y), (x, y), chess_map[x][y])
|
|
t = get_ans(pro, 2, depth, 0, 1, 0 if chess_map[x][y].color == 2 else score_standard[chess_map[x][y].type])
|
|
if t > score:
|
|
score = t
|
|
p = pro
|
|
self.level_score = [10000000 if i % 2 == 0 else -10000000 for i in range(100)]
|
|
return p
|
|
|
|
def call_back(self, root, canvas, depth, event):
|
|
print((self.lock[0], self.lock[1], self.lock[2]))
|
|
chess_map = self.chess_map
|
|
lock = self.lock
|
|
for i in range(50, 50 + 50 * 9, 50):
|
|
for j in range(50, 50 + 50 * 10, 50):
|
|
if (event.x - i) ** 2 + (event.y - j) ** 2 < 20 ** 2:
|
|
x = i // 50 + 1
|
|
y = j // 50 + 1
|
|
if chess_map[x][y].color < 3:
|
|
if lock[2] == 0: #如果未锁定
|
|
if chess_map[x][y].color < 2:
|
|
lock[2] = 1
|
|
lock[0] = x
|
|
lock[1] = y
|
|
elif lock[0] == x and lock[1] == y: #如果锁定的是一样的棋子
|
|
lock[2] = 0
|
|
else:
|
|
if chess_map[lock[0]][lock[1]].color == 0:
|
|
if chess_map[x][y].color == 1 or chess_map[x][y].color == 2:
|
|
lock[2] = 0 #解锁
|
|
pro = process((lock[0], lock[1]), (x, y), chess_map[x][y])
|
|
self.next(pro)
|
|
self.draw(root, canvas)
|
|
root.update()
|
|
pro = self.get_pro(depth)
|
|
self.next(pro)
|
|
self.draw(root, canvas)
|
|
global count
|
|
print(count)
|
|
count = 0
|
|
elif chess_map[x][y].color == 0: #不用解锁
|
|
lock[0] = x
|
|
lock[1] = y
|
|
return
|
|
return
|
|
|
|
def run(self, depth)->None:
|
|
chess_map = self.chess_map
|
|
get_ans = self.get_ans
|
|
root = Tk()
|
|
canvas = Canvas(master = root, height = 550, width = 500)
|
|
canvas.bind("<Button-1>", partial(self.call_back, root, canvas, depth))
|
|
canvas.pack()
|
|
self.draw(root, canvas)
|
|
root.mainloop()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test = map()
|
|
test.run(6) |