Десять тысяч: кости игра для нескольких игроков - последующие


Я выполнила совет, данный здесь и в других местах, насколько я понимаю: десять тысяч: кости игра для нескольких игроков

Я добавил компьютерного игрока, а также. Помоги мне сделать его еще лучше. Что такое ошибочные, лишние или не подходящие для Python, как это может быть? Есть ли заявления или методы я, очевидно, не знают? Мое использование классов соответствующие, или я мог еще двигаться, говорить, set_player() из Game класса?

import random
import collections
import numpy as np

msg = ('''
                    Welcome to Ten Thousand
                           The Game!
Objective:
    Score 10,000 points.
    Any turn in which a player ends with more than 10,000 points will be the 
    final turn.
    If multiple players finish with more than 10,000 points, the winner is the
    player with the most points.

To score:
    1's and 5's are worth 100 and 50 points respectively.
    Three-of-a-kind is worth the die number x 100. (Three 1's is 1000 points)
    Four-of-a-kind is worth double the same Three-of-a-kind.
    Five-of-a-kind is double Four-of-a-kind.
    Six of any number is worth 5000 points.
    A six dice straight is worth 1500 points.
    Three pairs are also worth 1500 points.

To play:
    Your dice will appear in [brackets].
    Choose your dice by the reference number located above your dice.
    You must score 500 points to get on the board.
    You'll press Enter a lot. Sorry about that. There will be graphics soon.
    Try and break things! If you do, please tell my how you did it.
    Screen shots of the error message are especially helpful.
    Have fun and thanks for helping me develop my first app!!
''')

valuedict = {1:
                {
                0: 0,
                1: 100,
                2: 200,
                3: 1000,
                4: 2000,
                5: 4000,
                6: 5000
                },
            2: {
                0: 0,
                1: 0,
                2: 0,
                3: 200,
                4: 400,
                5: 800,
                6: 5000
                },
            3: {
                0: 0,
                1: 0,
                2: 0,
                3: 300,
                4: 600,
                5: 1200,
                6: 5000
                },
            4: {
                0: 0,
                1: 0,
                2: 0,
                3: 400,
                4: 800,
                5: 1600,
                6: 5000
                },
            5: {
                0: 0,
                1: 50,
                2: 100,
                3: 500,
                4: 1000,
                5: 2000,
                6: 5000
                },
            6: {
                0: 0,
                1: 0,
                2: 0,
                3: 600,
                4: 1200,
                5: 2400,
                6: 5000
                }
                }


class Game:
    def __init__(self, player_list):
        self.player_list = player_list

    def set_player(self, player_list=[]):
        '''Sets number of players and player names.'''
        players = int(input('How many humans are playing?''\n', ))
        digi_player = input('Do you want to play against Digital Overlord? y/n''\n')
        if digi_player == r'y':
            name = 'Digital Overlord'
            self.name = ComPlayer(name)
            player_list.append(self.name)
        x = 0
        while x < players:
            name = input(f'Player {x + 1}, Enter your name:''\n', )
            self.name = Player(name)
            player_list.append(self.name)
            x += 1
        return player_list


class Player:
    def __init__(self, name, total_score=0):
        self.total_score = total_score
        self.name = name

    def pick(self, roll):
        '''Takes user input to choose dice by index. Returns choices.'''
        choice_list = []
        try:
            while True:
                choose = int(input(
'''Choose which die to keep by position 1-6
Type position number, then enter. Repeat for all choices.
Press enter when finished
'''
                            ))-1
                if choose >= len(roll):
                    print(f'\n{choose} not available\n')
                    continue
                if choose in choice_list:
                    print('\nYou can only pick a die once.\nNo cheating!')
                    continue
                else:
                    choice_list.append(choose)
        except ValueError:
            choice = [roll[x] for x in choice_list]
            False
        if choice is not None:
            counts = collections.Counter(choice)
            for _ in counts.items():
                if valuedict[_[0]][_[1]] == 0 and is_full_house(choice) == 0 \
                        and is_straight(choice) == 0:
                    print(f'\n{_[0]} is not a keeper.\nNo cheating!')
                    choice = None
        if choice is None:
            choice = []
        return choice


class ComPlayer:
    def __init__(self, name, total_score=0):
        self.total_score = total_score
        self.name = name

    def pick(self, roll):
        '''Allows computer to choose dice. Boop beep.'''
        counts = collections.Counter(roll)
        keepers = np.zeros(6, dtype=int)
        if is_full_house(roll) > sum(valuedict[die][count] for die, count
                    in counts.items()):
            keepers = list(roll)
        elif is_straight(roll) == 1500:
            keepers = list(roll)
        else:
            for _ in counts.items():
                if valuedict[_[0]][_[1]] > 0:
                    for x in range(len(roll)):
                        if roll[x] == _[0]:
                            keepers = np.insert(keepers, x, _[0])
                            keepers = np.delete(keepers, x + 1)
            while 0 in keepers:
                try:
                    for y in range(len(keepers)):
                        if keepers[y] == 0:
                            keepers = np.delete(keepers, y)
                except IndexError:
                    pass
        choice = list(keepers)
        if choice == []:
            return []
        return choice

def is_full_house(choice):
    if choice is None:
        return 0
    else:
        if len(choice) == 6 and\
                    all(a == b for a, b in zip(*[iter(sorted(choice))]*2)):
            return 1500
        else:
            return 0

def is_straight(choice):
    if choice is None:
        return 0
    else:
        if sorted(choice) == list(range(1, 7)):
            return 1500
        else:
            return 0

def keep_score(choice):
    '''Scores choices from self.pick().'''
    score = 0
    counts = collections.Counter(choice)
    score = sum(valuedict[die][count] for die, count in counts.items())
    straight = is_straight(choice)
    full_house = is_full_house(choice)
    if score < straight or full_house:
        score = max(straight, full_house)
    if score == 0:
        print('\nNo keepers. What a bummer.\nYour score for this round is: 0')
        return 0
    return score

def throw(keepers_list):
    '''Rolls dice and returns rolls in a list.'''
    roll = [random.randint(1, 6) for _ in range(6-len(keepers_list))]
    return roll

def turn(player):
    '''One player turn.'''
    round_score = 0
    keepers_list = []
    throw_count = 0
    while True:
        roll = throw(keepers_list)
        print(f'\n{player.name}, your dice in []\n 1  2  3  4  5  6\n{roll}\n')
        choice = player.pick(roll)
        print(f'\nHere are your choices: {choice}')
        score = keep_score(choice)
        if score == 0:
            return False
        print(f'\nScore for this throw is: {score}')
        round_score += score
        print(f'\nTotal score for this turn is: {round_score}')
        keepers_list += choice
        if len(keepers_list) == 6:
            print('\nSix keepers! Roll \'em again!')
            keepers_list = []
            throw_count = -1
        if player.name != 'Digital Overlord':
            again = input('''
Roll again or keep?
Enter = roll K = keep'''
                    )
            if again == r'k':
                player.total_score += round_score
                if player.total_score < 500:
                    print('\nMust score at least 500 to get on the board.')
                    player.total_score = 0
                    round_score = 0
                    return False
                else:
                    print(f'\n{player.name}\'s score this turn: {round_score}')
                    return False
            else:
                throw_count += 1
        else:
            if round_score >= 500 and len(keepers_list) > 2:
                player.total_score += round_score
                print(f'\n{player.name}\'s score this turn: {round_score}')
                return False
            else:
                throw_count += 1
    return False

def take_turns(player_list):
    '''Sets winning score, switches between players'''
    winner_dict = {}
    while not any(player.total_score >= 10000 for player in player_list):
        for player in player_list:
            turn(player)
            for x in range(len(player_list)):
                print(f'\n{player_list[x].name}\'s total score is: '
                      f'{player_list[x].total_score}')
    for x in range(len(player_list)):
        winner_dict.update({player_list[x].total_score: player_list[x]})
    winner = winner_dict[max(winner_dict.keys())]
    False
    print(f'\nThe winner is {winner.name}, '
          f'with a score of: {winner.total_score}!!')
    return False

def main():
    player_list = Game.set_player(Game, [])
    take_turns(player_list)

print(msg)
if __name__=="__main__":
    main()


265
11
задан 15 февраля 2018 в 04:02 Источник Поделиться
Комментарии
1 ответ


  • Правила Примечание: rulesheet не описать "шесть хранителей снова свернуть" правило в код.


  • import numpy as np

    Я не думаю, что numpy необходимо. Есть гораздо проще способы манипулирования встроенные списки в языке.



  • msg = ('''

    Нет необходимости, чтобы обернуть в скобки (они ничего не делают в этом контексте)



  • valuedict =

    valuedict - это ужасное имя переменной для переменной, которая содержит правила подсчета очков. Как насчет scoring_rules_table? valuedict не объяснить, что переменная содержит и для чего он используется. Ставя "dict" в имени переменной не поможет кто-нибудь разобраться что-нибудь; его тип будет очевидно из того, как его используют.



  • valuedict = {1:
    {
    0: 0,
    1: 100,
    2: 200,
    3: 1000,
    4: 2000,
    5: 4000,
    6: 5000
    },
    2: {

    Кроме того, я сомневаюсь в выборе исполнителей этой таблице как dict из dictС. Я думаю, было бы гораздо лучше реализовать это как list из listS (или list из array("I",..)С array модуль):

    scoring_rules = [ [0, 100, 200, 1000, 2000, 4000, 5000], [ ... ], ... ]

    Поскольку вы используете целые числа проиндексировать в нее, list будет работать, и имея dict просто стоит вам умчался. Или, поскольку каждый подсписок имеет те же размеры, реализовать его как 2-мерное numpy.ndarray.

    scoring_rules = np.array([[0, 100, 200,...],[...]], np.int32)

  • В-третьих, большая таблица данных, как это не должно быть частью вашего кода, это должен быть отдельный файл, либо файл python, который получает importЭД в compiletime, или чтения с системного диска (например, из файла CSV) в среде выполнения с помощью модуля.


  • class Game:

    Здесь нет строкой документации, поэтому я понятия не имею, что класс используется для. Цель использования классов для группировки связанных данных и/или функций. Ваш Game класс, кажется, не хранить любые данные (в __init__() никогда не вызывается, и член его в магазинах никогда нигде не применяется). А Game класс должен хранить данные об общем состоянии игры, например список игроков, чья очередь, и методы, которые используют и манипулируют состоянии всю игру. Список игроков будет одним из ее членов.



  •     def __init__(self, player_list):
    self.player_list = player_list

    Эта функция никогда не вызывается, и переменной-члена назначает не используется. Почему она существует?



  •     def set_player(self, player_list=[]):

    Список игроков-это аспект игры, поэтому она должна быть переменной (доступ через self.), а не параметр.



  •         '''Sets number of players and player names.'''
    players = int(input('How many humans are playing?''\n', ))

    Это позволит выйти на исключение, если пользователь не вводит целое число. Охраняй его try/except



  •         digi_player = input('Do you want to play against Digital Overlord? y/n''\n')
    if digi_player == r'y':

    Что если пользователь введет Y ? или некоторые вариации yes?



  •             name = 'Digital Overlord'
    self.name = ComPlayer(name)
    player_list.append(self.name)

    Какая цель self.name переменной-члена? Почему не местный? Это нужно для сохранения?



  •         x = 0
    while x < players:
    name = input(f'Player {x + 1}, Enter your name:''\n', )
    self.name = Player(name)
    player_list.append(self.name)
    x += 1

    Использовать for x in range(1, players+1). И опять же какова цель self.name? Это даже не имя, это Player экземпляра объекта.



  • class Player:

    Нужен строкой документации здесь тоже.



  •     def __init__(self, name, total_score=0):
    self.total_score = total_score
    self.name = name

    Когда вы когда-нибудь создать нового игрока с ненулевой суммарный результат?



  •     def pick(self, roll):
    '''Takes user input to choose dice by index. Returns choices.'''

    Нужен более описательное имя. Строкой документации должен быть понятнее.



  •         choice_list = []

    Порядок не имеет значения, поэтому он должен быть set



  •         try:
    while True:
    choose = int(input(

    Исключения должны быть исключительными ситуациями, а не обычным способом выхода из бесконечного цикла. Вы должны создать новую функцию, которая принимает строку и проверяет, если это целое число, и возвращает целое число или None. Затем проверить возвращаемое значение будет состояние вашего цикла. Вы можете вызывать эту функцию перед циклом, а также в цикле, или использовать "контур-с-половиной" способ.



  •                 if choose in choice_list:
    print('\nYou can only pick a die once.\nNo cheating!')

    Излишне враждебны, люди делают опечатки, как вы знаете.



  •         except ValueError:
    choice = [roll[x] for x in choice_list]
    False

    И except блок не должен иметь логики, надо только оправиться от исключения. Что False делала там?



  •         if choice is not None:

    Это if всегда быть приняты; choice никогда не будет None. Если постижение список не заканчивается с любой элементов вы получите пустой список. Но ваш код по-прежнему работает правильно, так в чем смысл if?



  •             for _ in counts.items():

    В _ переменная должна быть использована только за то, что не имеет значения. Она не должна быть фактической переменной цикла, если вы собираетесь использовать его.



  •                 if valuedict[_[0]][_[1]] == 0 and is_full_house(choice) == 0 \
    and is_straight(choice) == 0:
    print(f'\n{_[0]} is not a keeper.\nNo cheating!')
    choice = None

    Опять же, это напрасно карателей. Сделать одну ошибку и потерять свою очередь? Но даже если это то, что вы предполагаете, зачем продолжать с остальной частью петли? Просто break немедленно.



  •         if choice is None:
    choice = []

    Какая разница между тем, как ваш код обрабатывает None и [] что нужно использовать их обоих?



  • class ComPlayer:

    Либо ComPlayer должен быть подклассом Playerили ComPlayer и HumanPlayer оба должны быть подклассами Player. Устранить дублирование кода!



  •                             keepers = np.insert(keepers, x, _[0])
    keepers = np.delete(keepers, x + 1)

    Просто использовать обычные манипуляции список. Вместо вставки и удаления просто изменить пункт. Если вам действительно нужно, чтобы вставить или удалить в середине списка использовать обычные нарезки.



  •                 try:
    for y in range(len(keepers)):
    if keepers[y] == 0:
    keepers = np.delete(keepers, y)

    Если вы когда-нибудь собираетесь перебрать список и сделать что-то для каждого элемента, есть лучший способ сделать это, чем с помощью for петли. Также этот код не работает, если есть два последовательных 0 элементы. Гораздо проще просто сделать [y for y in keepers if y != 0]



  •         if choice == []:
    return []
    return choice

    Можно ли придумать более короткий путь для этого?



  • def is_full_house(choice):

    Эти типы функций правила игры и должны быть членами Game


        if choice is None:
    return 0
    else:
    if len(choice) == 6 and\

    Когда len(choice) будет нечто иное, чем 6?



  •                     all(a == b for a, b in zip(*[iter(sorted(choice))]*2)):

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


5
ответ дан 16 февраля 2018 в 08:02 Источник Поделиться