-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
221 lines (193 loc) · 7.3 KB
/
main.py
File metadata and controls
221 lines (193 loc) · 7.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# chess_game.py
import tkinter as tk
from tkinter import messagebox
from board import *
from pieces import *
class ChessGame:
def __init__(self, root):
self.root = root
self.root.title('Chess')
self.canvas = tk.Canvas(root, width=SQUARE_SIZE*BOARD_SIZE, height=SQUARE_SIZE*BOARD_SIZE)
self.canvas.pack()
self.board = initial_board()
self.turn_white = True
self.selected = None
self.highlight_ids = []
self.piece_text_ids = []
for i in range(8):
row = []
for j in range(8):
row.append(None)
self.piece_text_ids.append(row)
self.draw_board()
self.canvas.bind('<Button-1>', self.on_click)
frame = tk.Frame(root)
frame.pack()
tk.Button(frame, text='Reset', command=self.reset).pack(side='left')
def reset(self):
self.board = initial_board()
self.turn_white = True
self.selected = None
self.redraw()
def draw_board(self):
self.canvas.delete('square')
for r in range(8):
for c in range(8):
x1 = c*SQUARE_SIZE
y1 = r*SQUARE_SIZE
x2 = x1 + SQUARE_SIZE
y2 = y1 + SQUARE_SIZE
color = LIGHT_COLOR if (r+c)%2==0 else DARK_COLOR
self.canvas.create_rectangle(x1,y1,x2,y2, fill=color, outline='', tags='square')
self.redraw_pieces()
def redraw(self):
self.canvas.delete('all')
self.draw_board()
def redraw_pieces(self):
for r in range(8):
for c in range(8):
if self.piece_text_ids[r][c] is not None:
self.canvas.delete(self.piece_text_ids[r][c])
self.piece_text_ids[r][c] = None
for r in range(8):
for c in range(8):
piece = self.board[r][c]
if piece is not None:
glyph = PIECE_GLYPHS[piece]
x = c*SQUARE_SIZE + SQUARE_SIZE//2
y = r*SQUARE_SIZE + SQUARE_SIZE//2
tid = self.canvas.create_text(x,y,text=glyph,font=('Arial',32),tags='piece')
self.piece_text_ids[r][c] = tid
def on_click(self, event):
c = event.x // SQUARE_SIZE
r = event.y // SQUARE_SIZE
if not inside(r,c):
return
piece = self.board[r][c]
if self.selected is None:
if piece is None:
return
if self.turn_white and not is_white(piece):
return
if not self.turn_white and not is_black(piece):
return
self.selected = (r,c)
self.highlight_square(r,c)
else:
sr, sc = self.selected
if self.try_move(sr, sc, r, c):
self.turn_white = not self.turn_white
if self.is_king_captured():
winner = 'White' if self.turn_white == False else 'Black'
messagebox.showinfo('Game Over', f'{winner} captured the king!')
self.reset()
self.selected = None
self.clear_highlights()
self.redraw_pieces()
def highlight_square(self, r, c):
self.clear_highlights()
x1 = c*SQUARE_SIZE
y1 = r*SQUARE_SIZE
x2 = x1 + SQUARE_SIZE
y2 = y1 + SQUARE_SIZE
hid = self.canvas.create_rectangle(x1,y1,x2,y2, outline='blue', width=3)
self.highlight_ids.append(hid)
def clear_highlights(self):
for hid in self.highlight_ids:
self.canvas.delete(hid)
self.highlight_ids = []
def try_move(self, sr, sc, tr, tc):
piece = self.board[sr][sc]
target = self.board[tr][tc]
if not self.is_legal_move(sr, sc, tr, tc):
return False
self.board[tr][tc] = piece
self.board[sr][sc] = None
return True
def is_legal_move(self, sr, sc, tr, tc):
piece = self.board[sr][sc]
if piece is None:
return False
target = self.board[tr][tc]
if is_white(piece) and not self.turn_white:
return False
if is_black(piece) and self.turn_white:
return False
dr = tr - sr
dc = tc - sc
abs_dr = abs(dr)
abs_dc = abs(dc)
# Pawn moves
if piece.upper() == 'P':
direction = -1 if is_white(piece) else 1
start_row = 6 if is_white(piece) else 1
# Move forward
if dc == 0 and target is None:
if dr == direction:
return True
if sr == start_row and dr == 2*direction and self.board[sr+direction][sc] is None:
return True
# Capture
if abs(dc) == 1 and dr == direction and target is not None:
if (is_white(piece) and is_black(target)) or (is_black(piece) and is_white(target)):
return True
return False
# Knight moves
if piece.upper() == 'N':
if (abs_dr, abs_dc) in [(2,1),(1,2)]:
if target is None or (is_white(piece) and is_black(target)) or (is_black(piece) and is_white(target)):
return True
return False
# Bishop moves
if piece.upper() == 'B':
if abs_dr == abs_dc and self.clear_path(sr, sc, tr, tc):
if target is None or (is_white(piece) and is_black(target)) or (is_black(piece) and is_white(target)):
return True
return False
# Rook moves
if piece.upper() == 'R':
if (dr == 0 or dc == 0) and self.clear_path(sr, sc, tr, tc):
if target is None or (is_white(piece) and is_black(target)) or (is_black(piece) and is_white(target)):
return True
return False
# Queen moves
if piece.upper() == 'Q':
if ((abs_dr == abs_dc) or (dr == 0 or dc == 0)) and self.clear_path(sr, sc, tr, tc):
if target is None or (is_white(piece) and is_black(target)) or (is_black(piece) and is_white(target)):
return True
return False
# King moves
if piece.upper() == 'K':
if max(abs_dr, abs_dc) == 1:
if target is None or (is_white(piece) and is_black(target)) or (is_black(piece) and is_white(target)):
return True
return False
return False
def clear_path(self, sr, sc, tr, tc):
dr = tr - sr
dc = tc - sc
step_r = 0 if dr == 0 else (1 if dr>0 else -1)
step_c = 0 if dc == 0 else (1 if dc>0 else -1)
r = sr + step_r
c = sc + step_c
while (r,c) != (tr,tc):
if self.board[r][c] is not None:
return False
r += step_r
c += step_c
return True
def is_king_captured(self):
white_king = False
black_king = False
for r in range(8):
for c in range(8):
piece = self.board[r][c]
if piece == 'K':
white_king = True
if piece == 'k':
black_king = True
return not (white_king and black_king)
if __name__ == '__main__':
root = tk.Tk()
game = ChessGame(root)
root.mainloop()