Четвърта задача

  1. Аз го разбирам така:

    А какъв е статусът, ако дъската е празна?

    'Game in progress.'

    Играта се играе, но на практика никой просто не е поставил още.

    Кога статусът на играта е "Draw!"?

    Когато няма победител и дъската е запълнена. Вярно, че може по-отрано да се определи дали играта ще завърши наравно, но не мисля, че AI-то трябва да ти убива последните надежди :\

  2. Между другото много внимавайте как точно е форматиран изхода от print() в примера. Много е важно да го форматирате по същия начин, в противен случай ще загубите точки.

    >>> print(board)
                      # Тук има нов ред    
      -------------   # 2 спейса, 13 тирета, нов ред
    3 |   |   |   |   # всяка клетка е от 3 спейса
      -------------
    2 |   | O |   |   # О, X очевидно са в средата
      -------------
    1 |   |   | X |
      -------------
        A   B   C     # 4 спейса, буква, 3 спейса .. след C има 2 спейса и нов ред
    
  3. Никъде не е казано изрично, затова реших да попитам: когато някоя от двете страни спечели играта, но дъската не е попълнена изцяло, играта трябва да приключва нали?(т.е. да не се позволява да се попълват останалите празни полета)

  4. Напротив, можеш да си позволяваш според мен, но да кажем ако в един момент Х печели, и в края на играта имаш и линия на О-тата, да не ти изкара О печели. Т.е. след като е станало ясно, че Х печели, до края трябва game_status() да връща Х печели. Иначе защо да не позволяваш да се попълват?

  5. Никъде не е казано изрично, затова реших да попитам: когато някоя от двете страни спечели играта, но дъската не е попълнена изцяло, играта трябва да приключва нали?

    Да, играта е приключила в този момент. Ако имаш game_status различен от 'Game in progress.' не би следвало изобщо да се опитваш да обработваш следващи ходове.

    Т.е. прави "нищо".

  6. След като има победител играчите могат да продължат да правят каквото си искат с играта, не трябва да има как да променят резултата, също като когато се играе на хартия.

    Не виждам защо победата трябва да е изключение, при положение че това е нормален край на играта.

    Същото важи и за равен резултат.

  7. А приоритетите на изключенията какви са? Тоест в ситуации като следните кои изключения трябва да се вдигат:

    board['A1']='X' board['ERROR']='X'

    board['ERROR']='VALUE'

    board["A1"] = 'X' board["A1"] = 'X'

    и други.

  8. Имаш в предвид няколко различни инстанции на TicTacToeBoard? Ако наличието им чупи играта това не е на добре. Ако си държиш информацията, която се отнася до съответната инстанция в нея самата не би трябвало да имаш такива проблеми.

  9. @Мария, да ако това не е възможно значи бъркаш нещо.

    Самата идея на това да моделираш нещо като class почти винаги е за да можеш да създаваш множество независими инстанции от него по всяко време.

    Т.е по дефиниция трябва да можеш да имаш няколко различни инстанции на TicTacToeBoard едновременно също както по дефиниция трябва да можеш да имаш няколко различни инстанции на клас Person например.

  10. Упси :innocent: копи->пейст не е добра практика :)

    А да попитам изключенията чупят ли играта? Смисъл след като имаме примерно невалиден ход, може ли да подадем коректен ход и да продължим играта или трябва да почнем от начало :?

  11. Предвид формата на примерните тестове и на един от отговорите на Людмил по-горе, предполагам, че няма да се изисква да продължаваш играта. Според мене, ако има грешка, просто ще тестват дали се поражда съответното изключение и край на теста.

  12. Не виждам защо да не трябва да можеш да продължиш играта. Ако хвърляш изключение преди да промениш нещо по дъската нямаш никакъв проблем да я продължиш. Все едно на живо решаваш да сложиш нещо като не си на ход и противника да те плесне през ръцете преди да го сложиш. Играта пак може да продължи.

  13. Според предоставените ни unittest-ове играта трябва да гърми при срещане на exception. Първоначално пробвах да я направя така, че да продължава, но тогава получавах грешка: AssertionError: InvalidKey not raised

  14. Не играта гърми, а самия метод за записване в клетка. Можеш да направиш нещо такова:

    d = TicTacToeBoard()
    d["A1"] = 'O'
    try:
        d["A2"] = 'O'
    except NotYourTurn:
        print("Опа, сори!")
    
    d["B2"] = 'X'
    # и играта продължава като A2 е празно
    
  15. Георги е на прав път. Всъщност задачата не е съвсем да моделирате самата игра, а само правилата ѝ.

    Един клас е добре измислен когато върши само едно нещо -- в случая имплементира правилата на играта.

    Ако имаше някакво изискване за интерактивност щяхме да искаме да има още един клас грижещ се за потребителският интерфейс като цяло, например class TicTacToeGame

    Представете си един прост Game клас така:

    class TicTacToeGame:
        def __init__(self):
            self.board = TicTacToeBoard()
            while self.board.game_status() == "Game in progress.":
                print(self.board)
                self.player_turn()
    
         def player_turn(self):
            coords, move = self.get_player_input() # Примерно
            try:
                self.board[coords] = move
            except Exception as error:
                # Казваме на играча каква е грешката
                # и му даваме да опита отново
                print(error)
                self.player_turn(self)
    

    Тъй като в момента нямаме изискване за интерактивност, мисля че въпросът "трябва ли да продължи играта" е грешен. Просто ние в момента не моделираме цяла игра.

  16. Не съм сигурен до колко се подразбира (или дали изобщо се подразбира), но правейки си извод от неизискваната интерактивност ние не трябва да се грижим за правилният резултат на следният случай: >>> b = TicTacToeBoard() >>> b['A3'] = 'X' >>> b['B2'] = 'O' >>> b['A2'] = 'X' >>> b['B3'] = 'O' >>> b['A1'] = 'X' >>> b['B1'] = 'O'

    Тук принта е: ------------- 3 | X | O | | ------------- 2 | X | O | | ------------- 1 | X | O | | ------------- A B C

    В зависимост от това какво сме писали може да получим 2-та резултата от game_status()

    b.game_status() 'X wins!'

    или

    b.game_status() 'O wins!'

    Като на всички ни е ясно, че X е печеливш.

    .. И за да се върнем на предположението ми, ние не трябва да се грижим за правилният резултат в този и подобни случай, когато game_status() не е извикано веднага след като някой е спечелил.

    ЕDIT Людмил: когато пействате код трябва да го индентвате с 4 спейса навътре за да го форматира Markdown като код.

  17. Мисля че Людмил отговори на твоя въпрос.

    "След като има победител играчите могат да продължат да правят каквото си искат с играта, не трябва да има как да променят резултата, също като когато се играе на хартия.

    Не виждам защо победата трябва да е изключение, при положение че това е нормален край на играта.

    Същото важи и за равен резултат."

    Тоест като има победител ти можеш да записваш още, но винаги трябва да ти връща b.game_status() 'X wins!' в твоя случай, независимо как си го написал :).

  18. @Георги това да можеш да промениш победителя е нарушение на правилата, това не трябва да може да се случва. След като има вече победител стойността на game_status() не трябва да може да се променя.

  19. Здравейте,

    Имам 2 въпроса:

    1. Ако се опитам да 'GET'-на празно(непопълнено) поле, какво трябва да се изведе - празен стринг, единичен интервал...
    2. Ако изходът от играта е ясен предварително(има ясен победител преди да са запълнени всички полета), и се опитвам да вкарам невалидни данни, за да попълня празните полета, трябва ли да гърмя с exception или да си замълчавам тихичко. Въпросът ми е следствие от коментара на Кирил:

    Ако имаш game_status различен от 'Game in progress.' не би следвало изобщо да се опитваш да обработваш следващи ходове.

    Т.е. прави "нищо".

    Извинявам се, ако е било отговорено на някой от въпросите ми.

  20. Здрасти,

    1. празните полета трябва да връщат празен интервал ' '.

    2. Ако в играта има вече победител би трябвало да можеш да попълваш празните квадратчета, но не трябва да можеш да променяш резултата.

Трябва да сте влезли в системата, за да може да отговаряте на теми.