|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
- import tkinter as tk
- from tkinter import messagebox
- import random
- class ChineseChess:
- def __init__(self, master):
- self.master = master
- self.master.title("中国象棋")
- self.canvas = tk.Canvas(master, width=670, height=750, bg="#EDAA56")
- self.canvas.pack()
- # 游戏状态
- self.board = {}
- self.current_player = "red"
- self.selected_piece = None
- # 初始化棋盘
- self.init_board()
- self.draw_board()
- # 绑定事件
- self.canvas.bind("<Button-1>", self.on_click)
- def init_board(self):
- # 初始化棋子位置(红方在下方)
- initial_setup = [
- # 红方棋子
- ((0, 9), "车", "red"), ((1, 9), "马", "red"), ((2, 9), "相", "red"),
- ((3, 9), "仕", "red"), ((4, 9), "帅", "red"), ((5, 9), "仕", "red"),
- ((6, 9), "相", "red"), ((7, 9), "马", "red"), ((8, 9), "车", "red"),
- ((1, 7), "炮", "red"), ((7, 7), "炮", "red"),
- *[((i * 2, 6), "兵", "red") for i in range(0, 5)],
- # 黑方棋子
- ((0, 0), "车", "black"), ((1, 0), "马", "black"), ((2, 0), "象", "black"),
- ((3, 0), "士", "black"), ((4, 0), "将", "black"), ((5, 0), "士", "black"),
- ((6, 0), "象", "black"), ((7, 0), "马", "black"), ((8, 0), "车", "black"),
- ((1, 2), "炮", "black"), ((7, 2), "炮", "black"),
- *[((i * 2, 3), "卒", "black") for i in range(0, 5)]
- ]
- for pos, piece, color in initial_setup:
- self.board[pos] = {"type": piece, "color": color}
- print('self.board=', self.board)
- def draw_board(self):
- self.canvas.delete("all")
- # 绘制棋盘线条
- for i in range(10):
- y = 50 + i * 70
- self.canvas.create_line(50, y, 50 + 8 * 70, y, width=2, fill='green')
- for i in range(9):
- x = 50 + i * 70
- self.canvas.create_line(x, 50, x, 50 + 4 * 70, width=2, fill='green')
- self.canvas.create_line(x, 50 + 5 * 70, x, 50 + 9 * 70, width=2, fill='green')
- self.canvas.create_line(50, 50 + 4 * 70, 50, 50 + 5 * 70, width=2, fill='green')
- self.canvas.create_line(50 + 8 * 70, 50 + 4 * 70, 50 + 8 * 70, 50 + 5 * 70, width=2, fill='green')
- # 绘制九宫斜线
- self.canvas.create_line(50 + 3 * 70, 50, 50 + 5 * 70, 50 + 2 * 70, width=2, fill='green')
- self.canvas.create_line(50 + 3 * 70, 50 + 2 * 70, 50 + 5 * 70, 50, width=2, fill='green')
- self.canvas.create_line(50 + 3 * 70, 50 + 7 * 70, 50 + 5 * 70, 50 + 9 * 70, width=2, fill='green')
- self.canvas.create_line(50 + 3 * 70, 50 + 9 * 70, 50 + 5 * 70, 50 + 7 * 70, width=2, fill='green')
- # 绘制棋子
- for (x, y), piece in self.board.items():
- self.draw_piece(x, y, piece["type"], piece["color"])
- # 绘制当前玩家提示
- self.canvas.create_text(335, 730, text=f"当前玩家:{self.current_player}", font=("simhei", 14), fill="blue")
- def draw_piece(self, x, y, piece_type, color):
- x_pixel = 50 + x * 70
- y_pixel = 50 + y * 70
- self.canvas.create_oval(x_pixel - 32, y_pixel - 32, x_pixel + 32, y_pixel + 32,
- fill=color, outline=color)
- text_color = "white"
- self.canvas.create_text(x_pixel, y_pixel, text=piece_type,
- font=("楷体", 28), fill=text_color)
- def on_click(self, event):
- x = round((event.x - 50) / 70)
- y = round((event.y - 50) / 70)
- pos = (x, y)
- if not (0 <= x <= 8 and 0 <= y <= 9):
- return
- if not self.selected_piece:
- if pos in self.board and self.board[pos]["color"] == self.current_player:
- self.selected_piece = pos
- self.highlight_position(pos)
- else:
- start_pos = self.selected_piece
- if self.is_valid_move(start_pos, pos):
- self.move_piece(start_pos, pos)
- self.check_game_over()
- # 切换玩家并触发AI移动
- self.current_player = "black"
- self.draw_board()
- if self.current_player == "black":
- self.master.after(100, self.ai_move)
- self.selected_piece = None
- self.draw_board()
- def highlight_position(self, pos):
- x, y = pos
- x_pixel = 50 + x * 70
- y_pixel = 50 + y * 70
- self.canvas.create_rectangle(x_pixel - 35, y_pixel - 35, x_pixel + 35, y_pixel + 35,
- outline="yellow", width=3)
- def is_valid_move(self, start, end, board=None):
- if board is None:
- board = self.board
- if start not in board:
- return False
- piece = board[start]
- target_piece = board.get(end)
- if target_piece and target_piece["color"] == piece["color"]:
- return False
- move_type = piece["type"]
- if move_type == "车":
- return self.validate_rook(start, end, board)
- elif move_type in ("马", "馬"):
- return self.validate_knight(start, end, board)
- elif move_type in ("象", "相"):
- return self.validate_elephant(start, end, piece["color"], board)
- elif move_type in ("士", "仕"):
- return self.validate_advisor(start, end, piece["color"], board)
- elif move_type in ("将", "帅"):
- return self.validate_king(start, end, piece["color"], board)
- elif move_type == "炮":
- return self.validate_cannon(start, end, board)
- elif move_type in ("兵", "卒"):
- return self.validate_pawn(start, end, piece["color"], board)
- return False
- def validate_rook(self, start, end, board):
- x1, y1 = start
- x2, y2 = end
- if x1 != x2 and y1 != y2:
- return False
- step = 1 if x2 > x1 or y2 > y1 else -1
- if x1 == x2:
- for y in range(y1 + step, y2, step):
- if (x1, y) in self.board:
- return False
- else:
- for x in range(x1 + step, x2, step):
- if (x, y1) in self.board:
- return False
- return True
- def validate_knight(self, start, end, board):
- x1, y1 = start
- x2, y2 = end
- dx = abs(x2 - x1)
- dy = abs(y2 - y1)
- if not ((dx == 2 and dy == 1) or (dx == 1 and dy == 2)):
- return False
- # 检查蹩脚
- if dx == 2:
- mx = (x1 + x2) // 2
- if (mx, y1) in self.board:
- return False
- else:
- my = (y1 + y2) // 2
- if (x1, my) in self.board:
- return False
- return True
- def validate_elephant(self, start, end, color, board):
- x1, y1 = start
- x2, y2 = end
- dx = abs(x2 - x1)
- dy = abs(y2 - y1)
- if dx != 2 or dy != 2:
- return False
- # 检查田心
- mx, my = (x1 + x2) // 2, (y1 + y2) // 2
- if (mx, my) in self.board:
- return False
- # 不能过河
- if (color == "black" and y2 > 4) or (color == "red" and y2 < 5):
- return False
- return True
- def validate_advisor(self, start, end, color, board):
- x1, y1 = start
- x2, y2 = end
- dx = abs(x2 - x1)
- dy = abs(y2 - y1)
- if dx != 1 or dy != 1:
- return False
- # 九宫范围
- if color == "black":
- return 3 <= x2 <= 5 and 0 <= y2 <= 2
- else:
- return 3 <= x2 <= 5 and 7 <= y2 <= 9
- def validate_king(self, start, end, color, board):
- x1, y1 = start
- x2, y2 = end
- dx = abs(x2 - x1)
- dy = abs(y2 - y1)
- if dx + dy != 1:
- return False
- # 九宫范围
- if color == "black":
- return 3 <= x2 <= 5 and 0 <= y2 <= 2
- else:
- return 3 <= x2 <= 5 and 7 <= y2 <= 9
- def validate_cannon(self, start, end, board):
- x1, y1 = start
- x2, y2 = end
- if x1 != x2 and y1 != y2:
- return False
- count = 0
- if x1 == x2:
- step = 1 if y2 > y1 else -1
- for y in range(y1 + step, y2, step):
- if (x1, y) in self.board:
- count += 1
- else:
- step = 1 if x2 > x1 else -1
- for x in range(x1 + step, x2, step):
- if (x, y1) in self.board:
- count += 1
- target_piece = self.board.get(end)
- if target_piece:
- return count == 1 # 吃子需要隔一个棋子
- else:
- return count == 0 # 移动不能有棋子阻挡
- def validate_pawn(self, start, end, color, board):
- x1, y1 = start
- x2, y2 = end
- dx = abs(x2 - x1)
- dy = y2 - y1 if color == "black" else y1 - y2
- # 只能移动一格
- if dx + abs(y2 - y1) != 1:
- return False
- # 前进方向判断
- if color == "black":
- if y1 <= 4: # 未过河
- return y2 == y1 + 1 and x2 == x1
- else: # 过河后
- return dy == 1 or (dy == 0 and dx == 1)
- else:
- if y1 >= 5: # 未过河
- return y2 == y1 - 1 and x2 == x1
- else: # 过河后
- return dy == 1 or (dy == 0 and dx == 1)
- def move_piece(self, start, end):
- self.board[end] = self.board[start]
- del self.board[start]
- def check_game_over(self):
- # 检查是否存在将帅
- has_red_king = any(p["type"] == "帅" for p in self.board.values())
- has_black_king = any(p["type"] == "将" for p in self.board.values())
- if not has_red_king:
- self.show_winner("black")
- elif not has_black_king:
- self.show_winner("red")
- def show_winner(self, winner):
- messagebox.showinfo("游戏结束", f"{winner}方获胜!")
- self.master.destroy()
- # 新增AI相关方法
- def ai_move(self):
- best_score = -float('inf')
- best_moves = []
- for start in list(self.board.keys()):
- piece = self.board[start]
- if piece["color"] != self.current_player:
- continue
- for x in range(9):
- for y in range(10):
- end = (x, y)
- if self.is_valid_move(start, end):
- score = self.evaluate_move(start, end)
- if score > best_score:
- best_score = score
- best_moves = [(start, end)]
- elif score == best_score:
- best_moves.append((start, end))
- if best_moves:
- best_move = random.choice(best_moves)
- self.move_piece(best_move[0], best_move[1])
- self.check_game_over()
- self.current_player = "red"
- self.draw_board()
- def evaluate_move(self, start, end):
- temp_board = {pos: dict(data) for pos, data in self.board.items()}
- current_color = temp_board[start]["color"]
- score = 0
- # 吃子得分
- target_piece = temp_board.get(end)
- if target_piece and target_piece["color"] != current_color:
- score += self.get_piece_value(target_piece)
- # 模拟移动
- temp_board[end] = temp_board[start]
- del temp_board[start]
- # 检查是否被对方吃
- opponent_color = "red" if current_color == "black" else "black"
- for pos in list(temp_board.keys()):
- piece = temp_board[pos]
- if piece["color"] == opponent_color:
- if self.is_valid_move(pos, end, temp_board):
- score -= self.get_piece_value(temp_board[end]) * 0.5 # 被吃风险折扣
- return score
- def get_piece_value(self, piece):
- values = {
- "将": 1000, "帅": 1000,
- "车": 90, "炮": 45, "马": 40,
- "士": 20, "仕": 20, "象": 20, "相": 20,
- "卒": 10, "兵": 10
- }
- return values.get(piece["type"], 0)
- if __name__ == "__main__":
- root = tk.Tk()
- game = ChineseChess(root)
- root.mainloop()
复制代码 |
|