def main(): pygame.init() pygame.display.set_caption('BattleShips') screen = pygame.display.set_mode((scr_width, scr_height)) screen.fill(style.WHITE) # init fields usr_field = Field(surface=screen, cells=10, topleft=20, back_color=style.SOFT_BLUE) enemy_field = Field(surface=screen, cells=10, topleft=445, back_color=style.SOFT_RED) pygame.draw.line(screen, style.BLACK, (scr_width // 2, 0), (scr_width // 2, scr_height)) run = True # main loop while run: for event in pygame.event.get(): # close event if event.type == pygame.QUIT: run = False if event.type == pygame.MOUSEBUTTONDOWN: # get position event if event.button == 1: pos = pygame.mouse.get_pos() x, y = pos if x in range(0, scr_width // 2): usr_field.get_position(pos) elif x in range(scr_width // 2, scr_width): enemy_field.get_position(pos) # end event # draw fields usr_field.draw_field() enemy_field.draw_field() # draw ships ship1 = Ship(style.RED, 40, 40) screen.blit(ship1.image, ship1.rect) pygame.display.update() pygame.display.flip() # update display
class Player(object): def __init__(self, name, size): self.name = name self.ships = [] self.field_size = size self.my_field = Field(size, is_enemy=False) self.enemy_field = Field(size, is_enemy=True) self.verbose = True def __str__(self): return self.name def print_for_player(self, message): if self.verbose: print(message) def place_ships(self): self.print_for_player("Now it's time for "+self.name+' to place ships!') for length, count in SHIPS_SET: for _ in range(count): while True: try: ship = self.__class__.ship_input(length, self.field_size) if not ship.valid_ship_position(self.field_size): self.print_for_player('Ship is out of field.') continue for other_ship in self.ships: if other_ship.intersects(ship): raise IndexError self.ships.append(ship) self.print_for_player('Ship is added!') self.my_field.add_ship(ship) if self.verbose: self.my_field.draw_field() except ValueError: self.print_for_player('Bad input.') continue except IndexError: self.print_for_player('Ship is intersecting with other ship') continue else: break @staticmethod def ship_input(length, field_size): print('Place ship with length '+str(length)) orientation = '-' if length != 1: orientation = get_input('Enter orientation, | or - :') if orientation not in ['|', '-']: raise ValueError() cords = get_input('Enter coordinates of upper-left corner of ship (F7 for example):') x = letter_to_int(cords[0]) y = int(cords[1:])-1 if (x not in range(0, field_size)) or (y not in range(0, field_size)): raise ValueError() ship = Ship(x, y, length, orientation) return ship def draw_fields(self): print('Your field:') self.my_field.draw_field() print('Your shots:') self.enemy_field.draw_field() def make_move(self): while True: try: cords = get_input(self.name+', take a shot! Enter shot coordinates (A1 for example):') x = letter_to_int(cords[0]) y = int(cords[1:])-1 if (x not in range(0, self.field_size)) or (y not in range(0, self.field_size)): raise ValueError() except ValueError: print('Bad input.') continue else: break return x, y
class BoardWidget(QFrame): """ Класс фрейма, содержащий в себе основную логику игры. """ def __init__(self, board, field_dimension, cell_length, win_width, current_player_color=None, is_cut_now=False, cells_for_load=None, white_set=set(), black_set=set(), chosen_x=None, chosen_y=None, mouse_x=None, mouse_y=None, game_mode=None, really_player_color=None): super().__init__() self.walking_checkers = [] self.field_dimension = field_dimension self.cell_length = cell_length self.really_player_color = really_player_color self.game_mode = game_mode self.cells_for_load = cells_for_load self.board = board self.timer = QTimer() white_player = Player(CHECKER_WHITE_COLOR, white_set) black_player = Player(CHECKER_BLACK_COLOR, black_set) self.game_field = Field(white_player, black_player, field_dimension, self.cell_length, cells_for_load) if current_player_color is None: self.current_player = self.game_field.white_player else: self.current_player = self.game_field.get_player_by_color( current_player_color) if self.really_player_color == CHECKER_BLACK_COLOR: if self.game_mode == 'PvE': white_player.is_really_player = False else: if self.game_mode == 'PvE': black_player.is_really_player = False self.chosen_x = chosen_x self.chosen_y = chosen_y self.mouse_x = mouse_x self.mouse_y = mouse_y self.is_white_winner = False self.is_black_winner = False self.is_cut_now = is_cut_now self.win_width = win_width self.setGeometry(300, 100, self.win_width, self.win_width) def paintEvent(self, q_paint_event): """ Метод отрисовки. """ qPainter = QPainter() qPainter.begin(self) self.main(qPainter) self.update() qPainter.end() if self.is_black_winner or self.is_white_winner: self.show_result_window() def main(self, qPainter): """ Основной метод, содержащий логику. """ self.game_field.draw_field(qPainter) self.players = { self.game_field.white_player: self.game_field.black_player, self.game_field.black_player: self.game_field.white_player } if not self.timer.isActive(): if not self.is_cut_now and len(self.walking_checkers) == 0: self.find_walking_checkers() if len(self.walking_checkers) == 0 and len( self.current_player.checkers) != 0: self.board.close() self.end_window = EndGameWindow('Nobody is winner...') self.end_window.show() if self.mouse_x is not None or not self.current_player.is_really_player: column, row = self.mouse_x, self.mouse_y if not self.current_player.is_really_player: chosen_cell = choice(self.walking_checkers) chosen_cell.is_chosen = True self.chosen_x, self.chosen_y = chosen_cell.y, chosen_cell.x empty_cell = choice(chosen_cell.positions) row, column = empty_cell.y, empty_cell.x self.current_player.is_complete = False if self.chosen_x is None: self.current_player.is_complete = False if not self.game_field.field[row][column].checker: pass else: chosen_cell = self.game_field.field[row][column] if chosen_cell in self.current_player.checkers and chosen_cell.is_walking: self.chosen_x, self.chosen_y = row, column chosen_cell.is_chosen = True else: if self.game_field.field[self.chosen_x][ self.chosen_y].is_correct_cut( self.game_field.field[row][column], self.game_field): self.cut_move(row, column) elif not self.is_cut_now: self.make_step(row, column) if self.current_player.is_complete: self.change_player() self.mouse_x = None self.mouse_y = None def find_walking_checkers(self): """ Метод ищёт шашки, которыми может ходить текущий игрок. """ result_positions = [] max_len = 0 for checker in self.current_player.checkers: checker.find_longest_cut(None, self.game_field, result_positions, self.current_player, checker) current_len = max(len(list) for list in checker.positions) max_len = max(current_len, max_len) for checker in self.current_player.checkers: way = [] if max_len != 0: for list in checker.positions: if len(list) == max_len: if list[0] not in way: way.append(list[0]) checker.positions = way if len(checker.positions) > 0: checker.is_walking = True self.walking_checkers.append(checker) if len(self.walking_checkers) == 0: for checker in self.current_player.checkers: checker.positions = checker.find_positions_after_step( self.current_player, self.game_field) if len(checker.positions) > 0: checker.is_walking = True self.walking_checkers.append(checker) def cut_move(self, checked_x, checked_y): """ Логика хода со срубом. Параметры - координаты шашки, на которую планируется сделать ход. """ if self.game_field.field[checked_x][ checked_y] in self.game_field.field[self.chosen_x][ self.chosen_y].positions: self.is_cut_now = True previous_cell = self.game_field.field[self.chosen_x][self.chosen_y] enemy_cells = self.game_field.field[self.chosen_x][ self.chosen_y].get_enemies( self.game_field.field[checked_x][checked_y], self.game_field) self.game_field.field[self.chosen_x][self.chosen_y].cut( self.game_field.field[checked_x][checked_y], enemy_cells, self) result_positions = [] self.game_field.field[self.chosen_x][self.chosen_y].positions = [] self.game_field.field[self.chosen_x][ self.chosen_y].find_longest_cut( previous_cell, self.game_field, result_positions, self.current_player, self.game_field.field[self.chosen_x][self.chosen_y]) max_len = max( len(list) for list in self.game_field.field[self.chosen_x][ self.chosen_y].positions) way = [] if max_len != 0: for list in self.game_field.field[self.chosen_x][ self.chosen_y].positions: if len(list) == max_len: if list[0] not in way: way.append(list[0]) self.game_field.field[self.chosen_x][self.chosen_y].positions = way if len(self.game_field.field[checked_x][checked_y].positions) == 0: self.current_player.is_complete = True self.game_field.field[checked_x][checked_y].is_chosen = False self.chosen_x, self.chosen_y = None, None self.is_cut_now = False self.game_field.field[checked_x][checked_y].check_is_king( self.game_field, self.is_cut_now) def make_step(self, checked_x, checked_y): """ Логика хода без сруба. Параметры - координаты шашки, на которую планируется сделать ход. """ if self.game_field.field[checked_x][ checked_y] in self.game_field.field[self.chosen_x][ self.chosen_y].positions: if self.game_field.field[self.chosen_x][ self.chosen_y].is_step_possible( self.game_field.field[checked_x][checked_y], self.current_player, self.game_field): self.game_field.field[self.chosen_x][self.chosen_y].move( self.game_field.field[checked_x][checked_y], self.current_player, self.walking_checkers) self.current_player.is_complete = True self.game_field.field[checked_x][checked_y].check_is_king( self.game_field, self.is_cut_now) self.game_field.field[self.chosen_x][self.chosen_y].is_chosen = False self.chosen_x, self.chosen_y = None, None def change_player(self): """ Метод меняет текущего игрока. """ self.walking_checkers = [] if not self.is_cut_now: for i in range(self.field_dimension): for j in range(self.field_dimension): self.game_field.field[i][j].is_walking = False self.game_field.field[i][j].positions = [] self.game_field.field[i][j].is_chosen = False self.game_field.field[i][j].visited = False self.game_field.field[i][j].is_cut_down = False other_player = self.players[self.current_player] if self.current_player.is_really_player: self.timer.setSingleShot(True) self.timer.start(600) self.current_player = other_player def show_result_window(self, run_in_test=False): """ Метод открывает окошко с результатом игры. Параметр - флаг, который по умолчанию false, за исключением случаев тестирования. (Сделано, чтобы при тестировании не открывались всплывающие окна). """ with open('load_game.txt', 'w', encoding='utf-8') as f: f.truncate() text = 'White player is winner!' if self.is_black_winner else 'Black player is winner!' self.board.close() self.end_window = EndGameWindow(text) if not run_in_test: self.end_window.show() def mousePressEvent(self, QMouseEvent): """ Метод устанавливает координаты точки, на которую был совершён клик. """ self.mouse_x = QMouseEvent.pos().x() // self.cell_length self.mouse_y = QMouseEvent.pos().y() // self.cell_length def check_is_someone_winner(self): """ Метод проверяет, не является ли кто-то из игроков победителем. """ if self.game_field.white_player.checkers_count == 0: self.is_black_winner = True elif self.game_field.black_player.checkers_count == 0: self.is_white_winner = True