TicTacToe: если сообщение об ошибке не появляется сразу

Я новичок в Python и попытался создать полностью автоматическую игру в крестики-нолики, в которой вы можете увидеть, player1 имеет преимущество, если вы позволите ему начинать с середины, и я хотел бы получить отзывы о нем и областях улучшения. То есть это что-то безумное, что-то, что я делаю неправильно, или что-то, что я должен уточнить относительно структуры и кодирования?

Я спрашиваю, потому что я настолько новичок в Python, что мне трудно понять, где мне остановиться и где я должен потратить больше времени на улучшение кода. Я также расскажу ниже, где, на мой взгляд, мой код слаб, и хотел бы услышать ваш отзыв по этому комментарию.

Вкратце о том, как это работает: вы начинаете с звонка main() и решите, во сколько игр вы хотите сыграть, ответив на первый вопрос, затем вы должны решить, какую большую игровую поверхность вы хотели бы из 3, 5 и 7, ответив на второй вопрос, и, наконец, выберите свой сценарий (1 или 2 ), ответив на последний вопрос. 1 — это сценарий, когда все ходы автоматические, а 2 — сценарий, в котором player1 ставит свой первый ход посередине. Затем вы получите сюжет со статистикой всех раундов игры.

Меня больше всего беспокоит то, что сообщения об ошибках, если вы укажете неправильное значение для board_size, games или сценария, появляются после того, как вы ответили на все вопросы, а не сразу — что вы думаете об этом? Я попытался указать сообщения об ошибках, чтобы компенсировать это, хотя я не нашел способа, чтобы они появлялись сразу.

import numpy as np
import random 
import matplotlib.pyplot as plt


# creating an empty board
def create_board(board_size):
    return np.zeros((board_size,board_size), dtype=int)

def find_placement_scenario_one(board): 
 
    lst = [] 
   
    for i in range(len(board)): 
        for j in range(len(board)): 
           
            if board[i][j] == 0: 
                lst.append((i, j)) 
    return(lst)

def random_placeout_scenario_one(board, player): 
    selection = find_placement_scenario_one(board) 
    current_loc = random.choice(selection)
    board[current_loc] = player 
    return(board) 

def find_placement_scenario_two(board, board_size):
    l=[]
    
    for i in range(len(board)): 
         for j in range(len(board)): 
             
             if board_size == 3:
                 if board[i][j] == 0: 
                     l.append((1, 1)) 
             if board_size == 5:
                 if board[i][j] == 0: 
                     l.append((2, 2)) 
             if board_size == 7:
                 if board[i][j] == 0: 
                     l.append((3, 3)) 
    return(l) 

def placeout_scenario_two(board, player, board_size):
    
    player = 1
    selection = find_placement_scenario_two(board, board_size) 
    current_loc = random.choice(selection) 
    board[current_loc] = player 
    return(board) 

def check_row(board, player):
    for x in range(len(board)): 
        win = True
      
        for y in range(len(board)): 
            if board[x, y] != player: 
                win = False
                continue
              
        if win == True: 
            return(win) 
    return(win) 

def check_column(board, player):
      for x in range(len(board)): 
        win = True
      
        for y in range(len(board)): 
            if board[y][x] != player: 
                win = False
                continue
              
        if win == True: 
            return(win) 
      return(win) 

def check_diagonal(board, player):
    win = True
    y = 0
    for x in range(len(board)): 
        if board[x, x] != player: 
            win = False
    if win: 
        return win 
    win = True
    if win: 
        for x in range(len(board)): 
            y = len(board) - 1 - x 
            if board[x, y] != player: 
                win = False
    return win 


def evaluate(board): 
    winner = 0
   
    for player in [1, 2]: 
        if (check_row(board, player) or
            check_column(board,player) or
            check_diagonal(board,player)): 
              
            winner = player 
           
    if np.all(board != 0) and winner == 0: 
        winner = -1
    return winner

def choose_scenario(scenario, board_size):
    
    if board_size ==3 or board_size == 5 or board_size == 7:
        if scenario == 1 or scenario == 2:
        
            board, winner, counter = create_board(board_size), 0, 1
            
            if scenario == 1:
              
                while winner == 0: 
                    for player in [1, 2]:  
                        board = random_placeout_scenario_one(board, player)  
                        counter += 1
                        winner = evaluate(board) 
                        if winner != 0: 
                            break
                return(winner) 
            
            board, winner, counter = create_board(board_size), 0, 1
            
            if scenario == 2:
                
                board, winner, counter = create_board(board_size), 0, 1
              
                while winner == 0: 
                    for player in [2, 1]:  
                        board = placeout_scenario_two(board, player, board_size)
                        board = random_placeout_scenario_one(board, player) 
                        counter += 1
                        winner = evaluate(board) 
                        if winner != 0: 
                            break
                return(winner)       
            
    else:
        print('Playing surface does not exist, try again')
        
def save_stats(games, scenario, board_size):
    
    player1wins=0
    player2wins=0
    ties=0 
    
    for game in range(games):
        result=choose_scenario(scenario, board_size)
        if result==-1: ties+=1
        elif result==1: player1wins+=1
        else: player2wins+=1

    return [player1wins, player2wins, ties] # for returning
            
def print_and_save_stats(games, scenario, board_size):
    
     if board_size ==3 or board_size == 5 or board_size == 7:
        if scenario == 1 or scenario == 2:
                        
            player1wins, player2wins, ties = save_stats(games, scenario, board_size)
                            
            print('Player 1 wins:',player1wins)
            print('Player 2 wins:',player2wins)
            print('Tie:',ties)
                     
            # Fake dataset
            height = [player1wins, player2wins, ties]
            bars = ('Player 1', 'Player 2', 'Tie')
            y_pos = np.arange(len(bars))
             
            # Create bars and choose color
            plt.bar(y_pos, height, color = (0.5,0.1,0.5,0.6))
             
            # Add title and axis names
            plt.title('My title')
            plt.xlabel('')
            plt.ylabel('')
             
            # Limits for the Y axis
            plt.ylim(0,games)
             
            # Create names
            plt.xticks(y_pos, bars)
             
            # Show graphic
            plt.show()
            
        else:
            print('Scenario does not exist')
 
def main():
    
    try:
        
        games = int(input("How many games do you want to simulate? "))
        board_size = int(input("How big playing surface (3/5/7)? "))
        scenario = int(input('What scenario (1/2)? '))
        
        choose_scenario(scenario, board_size)
            
        print_and_save_stats(games, scenario, board_size)
        
    except ValueError:
        print('You have to answer all the question to start the game, try again')

1 ответ
1

Выглядит хорошо.

# creating an empty board
def create_board(board_size):
    return np.zeros((board_size,board_size), dtype=int)

find_placement_scenario_one это и шумное название, и его можно упростить. Я бы написал это так.

def available_spaces(board): 
    return np.argwhere(board==0)

random_placeout_scenario_one это еще одно странное имя. Оператор return также выглядит странно, так как вы все равно изменяете исходную плату. Я бы пропустил возврат, так как это ясно дает понять, что исходная плата модифицируется.

def make_random_move(board, player): 
    spaces = available_spaces(board) 
    space = random.choice(spaces)
    board[space] = player 

Проверки строк и диагоналей можно упростить с помощью numpy.

def is_winning_by_row(board, player):
    return any(
       all(row == player)
       for row in board
    )

def is_winning_by_col(board, player):
    return is_winning_by_row(board.transpose(), player)

def is_winning_by_diag(board, player):
    return any(
        all(np.diag(board_rotation) == player)
        for board_rotation in [board, np.fliplr(board)]
    ) 

def is_winning(board, player):
  return (
    is_winning_by_row(board, player) or
    is_winning_by_col(board, player) or
    is_winning_by_diag(board, player)
  )

Вы можете уменьшить мутацию в save_stats().

def save_stats(games, scenario, board_size):   
    game_results = [
        play_game(scenario, board_size) # formerly choose_scenario
        for _ in range(games)
    ]

    player1wins = game_results.count(1)
    player2wins = game_results.count(2)
    ties = game_results.count(-1)

    return player1wins, player2wins, ties

разное

Проверка размера доски — это глупо. Если указан недопустимый размер, вызовите исключение как можно раньше. Многократная проверка этого критерия вносит шум в ваш код.

Кроме того, ваше случайное размещение для ситуации 2, похоже, всегда размещает ходы только посередине, что кажется довольно неправильным.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *