Найти - Пользователи
Полная версия: крестики нолики с ИИ
Начало » Python для новичков » крестики нолики с ИИ
1 2 3
m1r42
py.user.next
Если бы у меня было время писать, я бы написал.
Бьюсь об заклад, что на весь этот текст вы потратили больше времени чем потратили бы на набросок программы. И всем было бы понятно о чем идёт речь, достаточно было бы глянуть на ваш код и на мой и сравнить. Но, и на этом спасибо. Ваши мысли действительно здравые и приносят людям пользу. Хочу лишь заметить, что здание возводят с фундамента. Будет фундамент значит будет и крыша, не будет фундамента нет смысла изучать стропильную систему и плевать как там ляжет мауэрлат потому что здание все равно либо не достроится либо рухнет.
py.user.next
m1r42
Бьюсь об заклад, что на весь этот текст вы потратили больше времени чем потратили бы на набросок программы.
В программе смысла нет, в тексте - есть. Когда сюда будут приходить периодически реально интересующиеся тем, что такое ООП и что такое не ООП, то я буду по своим тегам находить эти сообщения свои и направлять этих интересующихся на эти свои сообщения, чтобы это всё по второму, третьему, десятому разу не писать. Поэтому я их так готовлю хорошо, вычищаю от ошибок, проясняю неясности и так далее.

А чтобы программу делать, мне нужно сидеть сначала UML-диаграмму классов делать, которая поможет оптимально подобрать классы, на которые эту игру можно разложить, чтобы она нигде не закупорилась в процессе разработки потом. Ты-то думаешь, что код на лету придумывается, просто берёшь, придумываешь и всё, и готово, а разработка она не так происходит. Поспешишь - людей насмешишь, вот это главный принцип в разработке. Чик-чик и в продакшен - это вариант для тех, кто работает не для себя. Написал и забыл, не работает - и похрен. Но у них и опыт соответствующий накапливается - опыт в стиле чик-чик. А нормального опыта у них нет. Почему вот у них нихера никакого софта своего и нет в итоге. Он может двадцать лет работать где-то, где за него частенько что-то дописывали другие там разные приходящие и уходящие, а потом всем рассказывать, что он разрабатывал то, разрабатывал это, только забывать упоминать при этом, что он не целиком это разрабатывал и концепцию тоже не придумывал там всю, а что там он сделал треть только, если не четверть, а концепцией вообще какой-то другой архитектор занимался там, который как раз и специализировался на всём этом, на всех этих методах анализа и проектирования, прочитал там десяток книжек чисто по теме. Про GoF-шаблоны они тоже любят поговорить. А почему? А потому что это лёгкая хрень и её легко выучить. Только вот они подменяют понятия и пытаются ООП представить в виде такого просто набора GoF-шаблонов и всё, как будто эти GoF-шаблоны центральное место какое-то в ООП занимают. А это не так, это просто мелочёвка. ООП - тема обширная и её не так-то просто освоить.

Ты вот когда делаешь объект, придумываешь его, какие у тебя критерии того, какие в нём методы должны быть, а каких методов в нём быть не должно? Вот ты знаешь про атомарность методов? что методы должны быть атомарны? Это, знаешь, всё не так просто. Вроде пишешь, вроде у тебя всё получается типа само собой, а потом раз и ты видишь, что у тебя объектик поехал в какой-то ситуации. Поначалу было не видно и всё было нормально, а тут раз и при каком-то его применении он явно не подходит, потому что что-то у него не то с методами, как будто там неполный набор этих методов или как будто эти методы друг друга цепляют и эти методы ещё и поменять нельзя, потому что придётся весь объект удалять, а он уже где-то там используется именно в таком виде именно с такими методами. Это всё не так просто.
m1r42
py.user.next
Ты вот когда делаешь объект, придумываешь его, какие у тебя критерии того, какие в нём методы должны быть, а каких методов в нём быть не должно?
Думаю, что с таким подходом можно всю жизнь думать, но так ничего и не сделать. Проблема в том, что есть ограниченное количество времени на выполнение той или иной задачи и с этим ничего не поделать, время не остановишь. В середине декабря передо мной стояла задача до НГ ввести в работу программу по учету оборудования и ремонтов в моей организации. Две недели ушло на написание базовой версии 1.0. Сейчас конец января, программа уже умеет многое, что изначально даже не задумывалось, но в процессе разработки выяснилось, что можно использовать накопленные в БД данные для многих других целей. Версия уже выросла до 1.7 т.е. сделано уже 7 релизов после ввода в эксплуатацию и пока я не столкнулся с ошибками проектирования, т.е. столкнулся, но это легко решилось. Но ведь я мог бы изначально продумать всё что мне будет необходимо и сразу сдалеть “правильно”, увы неуспев запустить в работу программу к сроку. За полтора месяца проект вырос до 5000 строк и вырастет еще больше, так как появляются новые задумки по применению данных которые накапливаются в БД. Да, сейчас я смотрю на свой проект уже другими глазами. Знаю, что есть недочеты, но я получил опыт и в следующем проекте он мне пригодится. Если бы я учился только по книгам, а не на опыте, то скорей всего из под моей клавиатуры еще не вышло бы ни одной полезной программы.
m1r42
py.user.next
Да ты не сможешь просто даже добавить туда логирование, просто физически не сможешь.
Это имелось ввиду?
 import inspect
class Object(object):
    def save_log(self):
        print(inspect.getmembers(self, lambda myVar: not(inspect.isroutine(myVar))))
class Game(Object):
    def __init__(self):
        self.board = [['-', '-', '-'],
                      ['-', '-', '-'],
                      ['-', '-', '-'],
                      ]
    def make_move(self, x, y, symbol):
        """Делать ход"""
        if self.board[x][y] == '-':
            self.board[x][y] = symbol
            self.save_log()
        else:
            return False
        self.checking_the_board()
        return True
    def show_board(self):
        """Вывод доски в консоль"""
        for item in self.board:
            print(item)
    def checking_the_board(self):
        """Проверка доски"""
        pass
class AI(Object):
    def __init__(self, game):
        self.game = game
    def step(self):
        stop = False
        for row in range(3):
            if not stop:
                for column in range(3):
                    if self.game.board[row][column] == '-':
                        self.game.make_move(row, column, '0')
                        self.save_log()
                        stop = True
                        break
            else:
                break
game = Game()
a = AI(game)
while True:
    game.show_board()
    x = input('X >>> ')
    if x != 'q':
        y = input('Y >>> ')
        if y != 'q':
            if game.make_move(int(x), int(y), 'X'):
                print('ход сделан')
                a.step()
        else:
            break
    else:
        break
py.user.next
m1r42
Это имелось ввиду?
Да, типа такого.

Там у тебя должен быть объект Доска, объект ИИ, объект Игра. И вот этот цикл должен быть в объекте Игра. Объект Игра также должен выполнять операции над объектом Доска и над объектом ИИ. В объекте Игра их можно хранить в качестве свойств объекта Игра. Естественно, все классы этих объектов наследуются от класса Object. А класс Игра ещё не факт, что это конкретный класс, а не абстрактный класс для создания разных видов игр.

m1r42
За полтора месяца проект вырос до 5000 строк и вырастет еще больше
Ну да, программы не заканчиваются там на каких-то версиях. Они растут дальше. А чтобы они росли правильно, а не как икебана буквой зю, надо их правильно проектировать, иначе программа может врасти в саму себя и ты потом нихрена не сможешь сделать с этим, она прямо саму себя заблокирует. А чтобы их правильно проектировать, надо знать, как это делать вообще. А для того, чтобы знать, как это делать вообще, надо читать книжки от тех авторов, которые это всё изучили и прошли. Лучше учиться на чужих ошибках, чем, изобретая уже изобретённый велосипед, всему перетравмироваться от и до, пока понимаешь, как он там должен быть сделан, чтобы на нём именно ездить, а не падать с него.
m1r42
py.user.next
Да, типа такого.
Знаете, с вами дискутировать одно удовольствие. Я о многих вещех узнал именно из дискуссий с вами. Это очень круто. Снимаю шляпу, сэр. Я конечно задумывался о логгировании, но даже не знал с какой стороны подойти к процессу, а тут прямо меня осенило. Все гениальное просто, надо только найти подход к этому самому гениальному.
 import logging
logging.basicConfig(level=logging.INFO, filename="py_log.log", filemode="w",
                    format="%(asctime)s %(levelname)s %(message)s")
class Object(object):
    def save_log(self, *args):
        logging.info(args)
class Game(Object):
    def __init__(self):
        self.board = [['-', '-', '-'],
                      ['-', '-', '-'],
                      ['-', '-', '-'],
                      ]
    def make_move(self, x, y, symbol):
        """Делать ход"""
        if self.board[x][y] == '-':
            self.board[x][y] = symbol
            self.save_log(x, y, symbol)
        else:
            return False
        self.checking_the_board()
        return True
    def show_board(self):
        """Вывод доски в консоль"""
        for item in self.board:
            print(item)
    def checking_the_board(self):
        """Проверка доски"""
        pass
class AI(Object):
    def __init__(self, game):
        self.game = game
    def step(self):
        stop = False
        for row in range(3):
            if not stop:
                for column in range(3):
                    if self.game.board[row][column] == '-':
                        self.game.make_move(row, column, '0')
                        stop = True
                        break
            else:
                break
game = Game()
a = AI(game)
while True:
    game.show_board()
    x = input('X >>> ')
    if x != 'q':
        y = input('Y >>> ')
        if y != 'q':
            if game.make_move(int(x), int(y), 'X'):
                print('ход сделан')
                a.step()
        else:
            break
    else:
        break
m1r42
py.user.next
Там у тебя должен быть объект Доска, объект ИИ, объект Игра. И вот этот цикл должен быть в объекте Игра. Объект Игра также должен выполнять операции над объектом Доска и над объектом ИИ. В объекте Игра их можно хранить в качестве свойств объекта Игра. Естественно, все классы этих объектов наследуются от класса Object. А класс Игра ещё не факт, что это конкретный класс, а не абстрактный класс для создания разных видов игр.
Но это же код на коленке, естественно он из рода говнокодов, с целью на базовом уровне объяснить человеку, что прежде чем нагружать свою программу непонятными классами и аргументами, стоит задуматься, а надо ли все это, а можно ли сделать все проще, чтобы можно было смотреть в код и без каких-либо комментариев его понимать, в игры то я не играю (исключение HoMM III, который уже порядком надоел) вот и развлекаю в выходной день моск как могу.
py.user.next
py.user.next
Там у тебя должен быть объект Доска, объект ИИ, объект Игра. И вот этот цикл должен быть в объекте Игра. Объект Игра также должен выполнять операции над объектом Доска и над объектом ИИ. В объекте Игра их можно хранить в качестве свойств объекта Игра. Естественно, все классы этих объектов наследуются от класса Object. А класс Игра ещё не факт, что это конкретный класс, а не абстрактный класс для создания разных видов игр.
Думаю, там ещё должен быть объект Судья и объект Доска с результатами. И вот объект Игра содержит все эти вещи в себе и управляет ими, выполняя операции над ними и связывая их между собой.

Так что вот так оно примерно должно быть.

m1r42
нагружать свою программу непонятными классами и аргументами
Я вот тебе и говорю, что классы являются непонятными и вообще всё ООП является непонятным именно тогда, когда человек в них не разбирается, когда человек не умеет делать ООП. Вот тогда это и превращается в кашу и в ненужный бред, который хочется просто выкинуть и сделать всё попроще. Но оно и не для новичков, я тебе так скажу. Потому что ООП дополняет структурную парадигму программирования, а не заменяет её. То есть вот это примитивное всякое программирование, программирование без ООП, тебе уже нужно знать к тому времени, когда ты ООП изучать собрался. Поэтому новичком, который не знает, как правильно написать крестики-нолики вообще хотя бы как-то, нельзя быть. Нужно обязательно иметь опыт. Поэтому я вот и не поддерживаю такие подходы, когда новичков сразу на ООП кидают и начинают их там типа учить с такими типа лозунгами “вот мы сейчас им правильные мозги сразу сформируем, они не будут знать старых стилей, они не будут писать по-старому там, где нужно в ООП писать”. Это бред полный. Не знать Кнута, не знать сортировку пузырьковую - это такая бредятина. Потом начинается, что он пишет в ООП (ну, якобы в ООП, как его там убедили), но при этом простой массив перебрать не может вообще, потому что не умеет границы у массива определять, не знает, что такое массив с элементами и где там элементы и сколько их там и так далее. Ему нужен итератор, потому что без итератора у него сразу ступор и всё.
py.user.next
m1r42
Я конечно задумывался о логгировании, но даже не знал с какой стороны подойти к процессу
Я думаю, ты Board (класс Доска) назвал Game'ом (класс Игра). Потому что методы там от Board'а. Назови её Board обратно. А Game создай дополнительно и в Game засунь метод, в котором и будет этот цикл while, который у тебя там внизу.

Но конечно, тебе придётся прогу переделывать всю свою, потому что там у тебя вся эта структура неправильно организована. В основном там имена надо будет поменять все на другие.

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

То есть по закону Деметры объект Доска не должен знать про существование объекта Мозги (объект ИИ или объект Искусственный интеллект), а объект Мозги не должен знать, для чего и для кого его задействуют, для какой Доски, для какой Игры, он про существование этих объектов даже не знает. Объект Мозги знает только, что он находится внутри какого-то объекта Игра и всё, и эта Игра откуда-то сверху ему задаёт вопросики, а он на них просто отвечает и даёт ответы Игре. А что там, откуда пришло, для чего Игра ему задала эти вопросики, он не должен быть в курсе. Это закон Деметры. Части системы должны как можно меньше знать друг про друга. Идеально - это чтобы они вообще друг про друга не знали.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB