繁体   English   中英

如何在 python 中使用逻辑运算符

[英]How to use logical operators in python

我必须检查棋盘上的某些动作是否合法。

合法的举动是:

  • 对于 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()
if selected_unit.kind is 'P' or 'A' or 'K':

应该

if selected_unit.kind == 'P' or selected_unit.kind == 'A' or selected_unit.kind == 'K':

等等。

为了写得更简洁,你可以做类似的事情

if selected_unit.kind in 'PAK':

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM