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

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)