Я должен проверить, являются ли некоторые ходы законными на шахматной доске.
Допустимые ходы:
- для P (pikeman) только на один квадрат вверх, вниз, влево,и справа
- для A (лучник) так же, как для P, плюс один квадрат по диагонали (вверх-влево, вверх-вправо, вниз-влево, вниз-вправо)
- для K (рыцарь) так же, как и для P, A, плюс два квадрата вверх, вниз, влево, вправо и каждое диагональное направление
Алгоритм, который я пытаюсь написать:
if the unit kind is P or A or K:
if the position is up:
move up
if the position is down:
move down
if the position is left:
move left
if the position id right:
move right
if the unit kind is A or K:
if the position id up-left:
move up-left
if the position is up-right:
move up-right
if the position is down-left:
move down_left
if the position is down-right:
move down right
if unit kind is K:
if the position is two squares up:
move two squares up
if the position is two squares down:
move two squares down
if the position is two squares left:
move two squares left
if the position is two squares right:
move two squares right
if the position is two squares up-right:
move two squares up-right
if the position is two squares up-left:
move two squares up-left
if the position is two squares down-right:
move two squares down-right
if the position is two squares down-left:
move two squares down-left
В моем коде я совершенно уверен, что сделал то же самое, но по какой-то причине все работает нормально, за исключением того факта, что буква P также может переместиться на одну клетку по диагонали.
Что я делаюнеправильно? Я думаю, что ошибка связана с логическими операторами 'и' и 'или', но я не могу понять, что это такое. Я уже пробовал разные решения, но всегда есть какой-то юнит, который не может переместиться туда, куда он действительно должен.
Вот самая простая версия кода:
import pygame
import sys
# initialize pygame
pygame.init()
# set the window
window_size = (800, 800)
game_window = pygame.display.set_mode(window_size)
pygame.display.set_caption('My Canvas')
# define colours
colours = {
'black': (0, 0, 0),
'white': (255, 255, 255),
'gold': (153, 153, 0),
'green': (0, 180, 0)
}
# define classes
class Square:
def __init__(self, colour, left, top):
self.surface = game_window
self.colour = colour
self.width = 100
self.height = 100
self.left = left
self.top = top
self.rect = self.left, self.top, self.width, self.height
def draw_square(self):
pygame.draw.rect(self.surface, self.colour, self.rect)
def get_square_position(self):
return self.left, self.top
def get_square_colour(self):
return self.colour
class Unit:
def __init__(self, colour, left, top):
self.surface = game_window
self.colour = colour
self.left = left
self.top = top
self.kind = None
def get_unit_position(self):
return self.left, self.top
def get_square_on(self):
return pygame.Rect(self.left, self.top, 100, 100)
class Pikeman(Unit):
def __init__(self, colour, left, top):
super().__init__(colour, left, top)
self.shape_left = self.left + 10
self.shape_top = self.top + 10
self.current_position = Pikeman.get_unit_position(self)
self.left = left
self.top = top
self.width = 80
self.height = 80
self.square_on = pygame.Rect(left, top, 100, 100)
self.kind = 'P'
def draw_unit(self):
pygame.draw.rect(self.surface, self.colour, (self.shape_left, self.shape_top, self.width, self.height))
pygame.draw.rect(self.surface, colours.get('gold'),
(self.shape_left, self.shape_top, self.width, self.height), 3)
pygame.draw.rect(self.surface, colours.get('gold'),
(self.shape_left + 5, self.shape_top + 5, self.width - 10, self.height - 10), 2)
pygame.font.init()
my_font_size = 50
my_font = pygame.font.SysFont('Time New Roman', my_font_size)
text_surface = my_font.render('P', 1, colours.get('gold'))
x_centre = self.shape_left + self.width / 2
y_centre = self.shape_top + self.height / 2
centre_text = text_surface.get_rect(center=(x_centre, y_centre))
self.surface.blit(text_surface, centre_text)
def set_unit_position(self, left, top):
self.shape_left = left + 10
self.shape_top = top + 10
self.left = left
self.top = top
self.square_on = pygame.Rect(left, top, 100, 100)
draw_chessboard()
for white_unit in white_army:
if white_unit.get_unit_position() is not selected_unit.new_position:
white_unit.draw_unit()
for black_unit in black_army:
if black_unit.get_unit_position() is not selected_unit.get_unit_position():
black_unit.draw_unit()
self.draw_unit()
class Archer(Unit):
def __init__(self, colour, left, top):
super().__init__(colour, left, top)
self.left = left
self.top = top
self.width = 80
self.height = 80
self.square_on = pygame.Rect(left, top, 100, 100)
if self.colour is colours.get('white'):
self.shape_left = self.left + 10, self.top + 90
self.shape_top = self.left + 10 + (((self.left + 90) - (self.left + 10)) / 2), self.top + 10
self.shape_right = self.left + 90, self.top + 90
self.current_position = Archer.get_unit_position(self)
else:
self.shape_left = self.left + 10, self.top + 10
self.shape_top = self.left + 10 + (((self.left + 90) - (self.left + 10)) / 2), self.top + 90
self.shape_right = self.left + 90, self.top + 10
self.current_position = Archer.get_unit_position(self)
self.kind = 'A'
def draw_unit(self):
if self.colour is colours.get('white'):
pygame.draw.polygon(self.surface, self.colour, (self.shape_left, self.shape_top, self.shape_right))
pygame.draw.polygon(self.surface, colours.get('gold'),
(self.shape_left, self.shape_top, self.shape_right), 3)
pygame.draw.polygon(self.surface, colours.get('gold'),
((self.left + 20, self.top + 85),
(self.left + 50 + (((self.left + 80) - (self.left + 80)) / 2), self.top + 20),
(self.left + 80, self.top + 85)), 2)
pygame.font.init()
my_font_size = 50
my_font = pygame.font.SysFont('Time New Roman', my_font_size)
text_surface = my_font.render('A', 1, colours.get('gold'))
x_centre = self.left + 50
y_centre = self.top + 60
centre_text = text_surface.get_rect(center=(x_centre, y_centre))
self.surface.blit(text_surface, centre_text)
else:
pygame.draw.polygon(self.surface, self.colour, (self.shape_left, self.shape_top, self.shape_right))
pygame.draw.polygon(self.surface, colours.get('gold'), (self.shape_left, self.shape_top, self.shape_right),
3)
pygame.draw.polygon(self.surface, colours.get('gold'),
((self.left + 20, self.top + 15),
(self.left + 50 + (((self.left + 80) - (self.left + 80)) / 2), self.top + 80),
(self.left + 80, self.top + 15)), 2)
pygame.font.init()
my_font_size = 50
my_font = pygame.font.SysFont('Time New Roman', my_font_size)
text_surface = my_font.render('A', 1, colours.get('gold'))
x_centre = self.left + 50
y_centre = self.top + 35
centre_text = text_surface.get_rect(center=(x_centre, y_centre))
self.surface.blit(text_surface, centre_text)
def set_unit_position(self, left, top):
self.left = left
self.top = top
self.square_on = pygame.Rect(left, top, 100, 100)
if self.colour is colours.get('white'):
self.shape_left = self.left + 10, self.top + 90
self.shape_top = self.left + 10 + (((self.left + 90) - (self.left + 10)) / 2), self.top + 10
self.shape_right = self.left + 90, self.top + 90
else:
self.shape_left = self.left + 10, self.top + 10
self.shape_top = self.left + 10 + (((self.left + 90) - (self.left + 10)) / 2), self.top + 90
self.shape_right = self.left + 90, self.top + 10
draw_chessboard()
for white_unit in white_army:
if white_unit.get_unit_position() != selected_unit.new_position:
white_unit.draw_unit()
for black_unit in black_army:
if black_unit.get_unit_position() is not selected_unit.get_unit_position():
black_unit.draw_unit()
self.draw_unit()
class Knight(Unit):
def __init__(self, colour, left, top):
super().__init__(colour, left, top)
self.left = left
self.top = top
self.width = 80
self.height = 8
self.shape_left = self.left + 50
self.shape_top = self.top + 50
self.square_on = pygame.Rect(left, top, 100, 100)
self.kind = 'K'
def draw_unit(self):
pygame.draw.circle(self.surface, self.colour, (self.shape_left, self.shape_top), 40)
pygame.draw.circle(self.surface, colours.get('gold'), (self.shape_left, self.shape_top), 40, 3)
pygame.draw.circle(self.surface, colours.get('gold'), (self.shape_left, self.shape_top), 32, 1)
pygame.font.init()
my_font_size = 50
my_font = pygame.font.SysFont('Time New Roman', my_font_size)
text_surface = my_font.render('K', 1, colours.get('gold'))
x_centre = self.shape_left
y_centre = self.shape_top
centre_text = text_surface.get_rect(center=(x_centre, y_centre))
self.surface.blit(text_surface, centre_text)
def set_unit_position(self, left, top):
self.shape_left = left + 50
self.shape_top = top + 50
self.left = left
self.top = top
self.square_on = pygame.Rect(left, top, 100, 100)
draw_chessboard()
for white_unit in white_army:
if white_unit.get_unit_position() is not selected_unit.new_position:
white_unit.draw_unit()
for black_unit in black_army:
if black_unit.get_unit_position() is not selected_unit.get_unit_position():
black_unit.draw_unit()
self.draw_unit()
# define functions
def draw_chessboard():
for left in range(0, 800, 100):
for top in range(0, 800, 100):
if left in range(0, 800, 200) and top in range(0, 800, 200):
colour = colours.get('white')
square_object = Square(colour, left, top)
square_object.draw_square()
if left in range(100, 800, 200) and top in range(100, 800, 200):
colour = colours.get('white')
square_object = Square(colour, left, top)
square_object.draw_square()
if left in range(100, 800, 200) and top in range(0, 800, 200):
colour = colours.get('black')
square_object = Square(colour, left, top)
square_object.draw_square()
if left in range(0, 800, 200) and top in range(100, 800, 200):
colour = colours.get('black')
square_object = Square(colour, left, top)
square_object.draw_square()
def highlight_square(square_on):
pygame.draw.rect(game_window, colours.get('green'), square_on, 5)
def is_legal_move(selected_unit):
squares_occupied = []
for white_unit_square in white_army:
squares_occupied.append(white_unit_square.get_square_on())
for black_unit_square in black_army:
squares_occupied.append(black_unit_square.get_square_on())
for square_occupied in squares_occupied:
if square_occupied.collidepoint(new_position[0], new_position[1]):
print('cannot move here, this square if occupied by a friendly unit!')
return False
# legal moves common between pikemen, archers, and knights
if selected_unit.kind is 'P' or 'A' or 'K':
# legal up move
if (current_position[0] < new_position[0] < current_position[0] + 100) and \
(current_position[1] - 100) < new_position[1] < (current_position[1]):
if 0 < new_position[1] < 800:
selected_unit.new_position = current_position[0], current_position[1] - 100
print('legal up move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal down move
if (current_position[0] < new_position[0] < current_position[0] + 100) and \
(current_position[1] + 200) > new_position[1] > (current_position[1] + 100):
if 0 < new_position[1] < 800:
selected_unit.new_position = current_position[0], current_position[1] + 100
print('legal down move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal left move
if (current_position[0] - 100 < new_position[0] < current_position[0]) and \
(current_position[1] + 100) > new_position[1] > (current_position[1]):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] - 100, current_position[1]
print('legal left move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal right move
if (current_position[0] + 100 < new_position[0] < current_position[0] + 200) and \
(current_position[1] + 100) > new_position[1] > (current_position[1]):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] + 100, current_position[1]
print('legal right move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal moves in common between archers and knights
if selected_unit.kind is 'K' or 'A':
# legal left-up move
if (current_position[0] - 100 < new_position[0] < current_position[0]) and \
(current_position[1] - 100 < new_position[1] < current_position[1]):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] - 100, current_position[1] - 100
print('legal left-up move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal right-up move
if (current_position[0] + 100 < new_position[0] < current_position[0] + 200) and \
(current_position[1] - 100 < new_position[1] < current_position[1]):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] + 100, current_position[1] - 100
print('legal right-up move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal left-backward move
if (current_position[0] - 100 < new_position[0] < current_position[0]) and \
(current_position[1] + 100 < new_position[1] < current_position[1] + 200):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] - 100, current_position[1] + 100
print('legal left-down move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal right-backward move
if (current_position[0] + 100 < new_position[0] < current_position[0] + 200) and \
(current_position[1] + 100 < new_position[1] < current_position[1] + 200):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] + 100, current_position[1] + 100
print('legal right-down move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal moves exclusive to knights
if selected_unit.kind is 'K':
# legal long up move
if (current_position[0] < new_position[0] < current_position[0] + 100) and \
(current_position[1] - 200) < new_position[1] < (current_position[1] - 100):
if 0 < new_position[1] < 800:
selected_unit.new_position = current_position[0], current_position[1] - 200
print('legal long up move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal long down move
if (current_position[0] < new_position[0] < current_position[0] + 100) and \
current_position[1] + 200 < new_position[1] < (current_position[1] + 300):
if 0 < new_position[1] < 800:
selected_unit.new_position = current_position[0], current_position[1] + 200
print('legal long down move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal long left move
if (current_position[0] - 200 < new_position[0] < current_position[0] - 100) and \
current_position[1] < new_position[1] < (current_position[1] + 100):
if 0 < new_position[1] < 800:
selected_unit.new_position = current_position[0] - 200, current_position[1]
print('legal long left move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal long right move
if (current_position[0] + 200 < new_position[0] < current_position[0] + 300) and \
current_position[1] < new_position[1] < (current_position[1] + 100):
if 0 < new_position[1] < 800:
selected_unit.new_position = current_position[0] + 200, current_position[1]
print('legal long left move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal left-up long move
if (current_position[0] - 200 < new_position[0] < current_position[0] - 100) and \
(current_position[1] - 200 < new_position[1] < current_position[1] - 100):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] - 200, current_position[1] - 200
print('legal left-up long move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal right-up long move
if (current_position[0] + 200 < new_position[0] < current_position[0] + 300) and \
(current_position[1] - 200 < new_position[1] < current_position[1] - 100):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] + 200, current_position[1] - 200
print('legal right-up long move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal left-down long move
if (current_position[0] - 200 < new_position[0] < current_position[0] - 100) and \
(current_position[1] + 200 < new_position[1] < current_position[1] + 300):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] - 200, current_position[1] + 200
print('legal left-down long move to ' + str(selected_unit.new_position))
return True
else:
return False
# legal right-down long move
if (current_position[0] + 200 < new_position[0] < current_position[0] + 300) and \
(current_position[1] + 200 < new_position[1] < current_position[1] + 300):
if 0 < new_position[0] < 800:
selected_unit.new_position = current_position[0] + 200, current_position[1] + 200
print('legal right-down long move to ' + str(selected_unit.new_position))
return True
else:
return False
def get_current_position():
return selected_unit.square_on[0], selected_unit.square_on[1]
def get_new_position():
return selected_unit.get_unit_position()
# initialise events
selected_unit = None
game_state = 'no unit selected'
turn = 'white army'
print('---' + str(turn).upper() + ', IS YOUR TURN---')
# initialise board and units
draw_chessboard()
white_army = []
for x in range(200, 600, 100):
y = 700
a_pikeman = Pikeman(colours.get('white'), x, y,)
a_pikeman.draw_unit()
white_army.append(a_pikeman)
for x in range(200, 600, 100):
y = 600
an_archer = Archer(colours.get('white'), x, y, )
an_archer.draw_unit()
white_army.append(an_archer)
for x in range(100, 700, 500):
y = 600
a_knight = Knight(colours.get('white'), x, y)
a_knight.draw_unit()
white_army.append(a_knight)
black_army = []
for x in range(200, 600, 100):
y = 0
a_pikeman = Pikeman(colours.get('black'), x, y,)
a_pikeman.draw_unit()
black_army.append(a_pikeman)
for x in range(200, 600, 100):
y = 100
an_archer = Archer(colours.get('black'), x, y, )
an_archer.draw_unit()
black_army.append(an_archer)
for x in range(100, 700, 500):
y = 100
a_knight = Knight(colours.get('black'), x, y)
a_knight.draw_unit()
black_army.append(a_knight)
armies = white_army + black_army
# main loop
while 1:
# event loop
for event in pygame.event.get():
if event.type is pygame.QUIT:
sys.exit()
# mouse click handling
if event.type == pygame.MOUSEBUTTONDOWN:
new_position = pygame.mouse.get_pos()
# unit not selected
if game_state is 'no unit selected':
if turn is 'white army':
for white_unit in white_army:
if white_unit.square_on.collidepoint(new_position[0], new_position[1]):
selected_unit = white_unit
game_state = 'unit selected'
print(str(game_state) + ', this unit is ' + str(selected_unit.kind))
elif turn is 'black army':
for black_unit in black_army:
if black_unit.square_on.collidepoint(new_position[0], new_position[1]):
selected_unit = black_unit
game_state = 'unit selected'
print(str(game_state) + 'this unit is ' + str(selected_unit.kind))
elif game_state == 'unit selected':
if turn is 'white army':
current_position = selected_unit.square_on
if is_legal_move(selected_unit):
game_state = 'unit movement allowed'
turn = 'black army'
else:
print('move not allowed, choose another square')
elif turn is 'black army':
current_position = selected_unit.square_on
if is_legal_move(selected_unit):
game_state = 'unit movement allowed'
turn = 'white army'
else:
print('move not allowed, choose another square')
# application loop
# highlight square
if game_state == 'unit selected':
highlight_square(selected_unit.square_on)
# move unit
if game_state == 'unit movement allowed':
selected_unit.set_unit_position(selected_unit.new_position[0], selected_unit.new_position[1])
game_state = 'no unit selected'
print('unit moved')
print('---' + str(turn).upper() + ', IS YOUR TURN---')
selected_unit = None
pygame.display.update()