Найти - Пользователи
Полная версия: крестики нолики с ИИ
Начало » Python для новичков » крестики нолики с ИИ
1 2 3
AlexxGorr
2 py.user.next
да я только начал ооп изучать. спасибо за коммент
AlexxGorr
2 py.user.next
да я только начал ооп изучать. спасибо за коммент
AlexxGorr
стало немного понятнее
m1r42
Вот пример кода игры “крестики нолики” с ИИ. Максимально примитивный. Максимально понятный. Любая программа должна начинаться с продумывания архитектуры - это действие самое любимое мной в программировании. Далее рутина, типа написать ИИ.
Код конечно не тянет на оскар, но этого и не требуется. Требуется понять что за что должно отвечать и как это будет работать потом когда будет дописано.
Стараюсь в своем коде как можно меньше использовать наворотов. Навороты они для удобства и они входят в обиход программиста постепенно, в дальнейшем, привыкнув, уже не можешь от них отказаться, а в самом начале пути надо делать упор на архитектуру и логику.
ООП - это не страшно, это удобство к которому тоже привыкаешь.
 class Board:
    def __init__(self):
        self.board = [['-', '-', '-'],
                      ['-', '-', '-'],
                      ['-', '-', '-'],
                      ]
    def make_move(self, x, y, symbol):
        """Делать ход"""
        if self.board[x][y] == '-':
            self.board[x][y] = symbol
        else:
            return False
        self.checking_the_board()
        return True
    def show(self):
        """Вывод доски в консоль"""
        for item in self.board:
            print(item)
    def checking_the_board(self):
        """Проверка доски"""
        pass
class AI:
    def __init__(self, board):
        self.board = board
    def step(self):
        stop = False
        for row in range(3):
            if not stop:
                for column in range(3):
                    if self.board.board[row][column] == '-':
                        self.board.make_move(row, column, '0')
                        stop = True
                        break
            else:
                break
b = Board()
a = AI(b)
while True:
    b.show()
    x = input('X >>> ')
    if x != 'q':
        y = input('Y >>> ')
        if y != 'q':
            if b.make_move(int(x), int(y), 'X'):
                print('ход сделан')
                a.step()
        else:
            break
    else:
        break
В коде игрок - это человек который вводит данные с клавиатуры. ИИ - экземпляр класса ИИ(В котором описаны методы ИИ) которому передается доска, которая экземпляр класса доска. Класс доска содержит методы: Делать ход, Вывод изображения доски, Проверка доски после хода.
AlexxGorr
ну вот так совсем все ясно
m1r42
AlexxGorr
ну вот так совсем все ясно
В моем примере класс Board назван неправильно. Лучше его назвать Game, а доска пусть останется атрибутом, класса Game тогда все станет еще проще и понятней.
 class Game:
    def __init__(self):
        self.board = [['-', '-', '-'],
                      ['-', '-', '-'],
                      ['-', '-', '-'],
                      ]
    def make_move(self, x, y, symbol):
        """Делать ход"""
        if self.board[x][y] == '-':
            self.board[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:
    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
AlexxGorr
2 m1r42
спасиб
py.user.next
m1r42
ООП - это не страшно, это удобство к которому тоже привыкаешь.
  
class Board:
    def __init__(self):
        self.board = [['-', '-', '-'],
                      ['-', '-', '-'],
                      ['-', '-', '-'],
                      ]
    def make_move(self, x, y, symbol):
        """Делать ход"""
        if self.board[x][y] == '-':
            self.board[x][y] = symbol
        else:
            return False
        self.checking_the_board()
        return True
    def show(self):
        """Вывод доски в консоль"""
        for item in self.board:
            print(item)
    def checking_the_board(self):
        """Проверка доски"""
        pass
class AI:
    def __init__(self, board):
        self.board = board
    def step(self):
        stop = False
        for row in range(3):
            if not stop:
                for column in range(3):
                    if self.board.board[row][column] == '-':
                        self.board.make_move(row, column, '0')
                        stop = True
                        break
            else:
                break
b = Board()
a = AI(b)
while True:
    b.show()
    x = input('X >>> ')
    if x != 'q':
        y = input('Y >>> ')
        if y != 'q':
            if b.make_move(int(x), int(y), 'X'):
                print('ход сделан')
                a.step()
        else:
            break
    else:
        break
У тебя тоже ООП нет в коде. Есть ОП только. В ООП обязательно должна быть иерархия классов, у которой на вершине находится только один класс.

ООП - объектно-ориентированная парадигма.
ОП - объектная парадигма.

Понятие “объектно-ориентированная” означает не “ориентированность на объекты”, что типа просто объекты должны быть, как многие думают, потому что не знают просто точно, о чём речь идёт, а означает “объекты восходят к исходному объекту в определённом направлении”. Это направление заложено в иерархии классов, которая всегда есть и которая всегда приходит только к одному классу наверху.

В питоне, как в платформе такой для написания программ, например, все объекты являются объектами класса object. Соответственно, каждый объект в питоне является объектом класса object. Любой объект - это разновидность объекта класса object.
  
>>> x = 1
>>> 
>>> o = object()
>>> 
>>> x
1
>>> o
<object object at 0x7f7ab9b320e0>
>>> 
>>> isinstance(x, object)
True
>>>
>>> isinstance(o, object)
True
>>>
Соответственно, если в класс object в питоне добавить что-то, то оно сразу добавится во все-все-все объекты происходящих классов, которые происходят от класса object. Во все числа, во все строки, во все словари, во все списки, во все самодельные классы, во все экземпляры этих самодельных классов.
  
>>> int
<class 'int'>
>>> 
>>> isinstance(int, object)
True
>>>
Даже класс является объектом, а раз он является объектом, то это разновидность объекта, который является экземпляром класса object.

Вот что такое “ориентированность”.

Вот пример ООП
  
>>> class Object:
...     def print_name(self):
...         print('object of class <' + self.__class__.__name__ + '>')
... 
>>> class AI(Object):
...     pass
... 
>>> class Board(Object):
...     pass
... 
>>> board = Board()
>>> ai = AI()
>>> 
>>> board.print_name()
object of class <Board>
>>> ai.print_name()
object of class <AI>
>>>

По той же причине в Qt существует класс QObject. И в этом классе много всего находится, что в итоге по наследству переходит всем-всем-всем объектам, которые уже есть в Qt и которые ты делаешь в Qt. Там просто не может быть по-другому, потому что Qt сделана в ООП.

Говорить же о том, что в питоне всё становится ООПшным потому, что всё наследуется от класса object, тоже неверно, потому что ты никакого контроля над этим классом не имеешь и, соответственно, ничего в него не можешь добавить, чтобы оно потом разошлось по классам наследникам
  
>>> object.x = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'object'
>>>


tags: oop theory
m1r42
py.user.next
У тебя тоже ООП нет в коде. Есть ОП только
Ну это вы, батенька, хватили. Даже Гугл не знает ОП парадигмы. Есть ООП, а уж как я его использую это моё дело. Есть холст, кисти, краски, делай с ними то что хочешь. Если в итоге получится картина которая тебя радует, то это правильный результат. Но надо понимать, что каждый увидит в этой картине недочёты, от этого картина не станет лучше или хуже, ведь она есть. Каждый может нарисовать чёрный квадрат чернее чем Малевич, но такой же не нарисует ни кто. Если программа делает то что я от неё хочу значит это правильная программа. Да, это говнокод, но он помогает понять на начальном уровне основы ООП. С удовольствием посмотрю на ваш код игры в исконно ООП варианте. Даже очень любопытно на сколько можно усложнить эту элементарную задачу.
Если есть возможность использовать класс как контейнер то почему нет? Мне удобно описать методы игры в одном классе. Мне удобно передать экземпляр этого класса в экземпляр ИИ. Я могу пользоваться всеми методами игры, ИИ может пользоваться теми же методами, что ещё требуется от этого кода? Совершенно не понимаю ваших слов. Зачем мне в рабочем коде добавления в Object? Хотя, постойте ведь : Классы старого стиля упразднены в Python 3: теперь пользовательские типы, определённые без явного указания родителя, автоматически являются наследниками object. Переход на такую унифицированную объектную модель, помимо прочего, сделал возможным наследование от встроенных типов, применение дескрипторов, адекватное определение порядка разрешения методов при множественном наследовании.

py.user.next
m1r42
Ну это вы, батенька, хватили. Даже Гугл не знает ОП парадигмы.
https://en.wikipedia.org/wiki/Object-based_languages
The term object-based language may be used in a technical sense to describe any programming language that uses the idea of encapsulating state and operations inside objects. Object-based languages need not support inheritance or subtyping, but those that do are also termed object-oriented. Object-based languages that do not support inheritance or subtyping are usually not considered to be true object-oriented languages.

https://en.wikipedia.org/wiki/Object-oriented_programming
Object-oriented programming (OOP) is a programming paradigm based on the concept of “objects”, which can contain data and code. The data is in the form of fields (often known as attributes or properties), and the code is in the form of procedures (often known as methods).

A common feature of objects is that procedures (or methods) are attached to them and can access and modify the object's data fields. In this brand of OOP, there is usually a special name such as this or self used to refer to the current object. In OOP, computer programs are designed by making them out of objects that interact with one another. OOP languages are diverse, but the most popular ones are class-based, meaning that objects are instances of classes, which also determine their types.

Сам список парадигм не стандартизован. То есть сами парадигмы постоянно меняются, дополняются, уточняются. Поэтому что такое ОО-парадигма и что такое не ОО-парадигма, там точно не известно. Одни считают одно, другие считают другое. При этом слово “парадигма” тоже возникло не в программировании, оно было до программирования и означает какую-то концепцию, если не вдаваться в детали определения этого слова. Это слово не зарезервировано программированием. Одни говорят “это объектно-ориентированная модель”, другие говорят “это объектно-ориентированный подход”, третьи говорят “это объектно-ориентированный стиль”, ну и так далее.

Так что даже на Википедии они пишут приблизительно. “Это приблизительно что-то построенное на объектах - вот что такое объектно-ориентированная парадигма программирования”. Но при этом там же они пишут, что языки, в которых нет наследования, чаще всего объектно-ориентированными не считаются. А какими же они тогда считаются и к какой они парадигме тогда относятся?

А справа там вообще в колонке с парадигмами всеми Object-oriented входит в виде подпарадигмы в парадигму Imperative и входит в виде подпарадигмы в парадигму Structured. То есть у них вообще раздвоилась объектно-ориентированная парадигма на две разных объектно-ориентированных парадигмы. Ты это сам можешь наблюдать.

Поэтому мы и говорим, что есть ОП (объектная парадигма), а есть ООП (объектно-ориентированная парадигма). Где ОП - это та парадигма, в которой ты написал код, где есть объекты и эти объекты никак не связаны между собой. И где ООП - это та парадигма, в которой я написал набросок кода, где есть объекты и эти объекты все связаны между собой единой иерархией наследования классов.

m1r42
Я могу пользоваться всеми методами игры, ИИ может пользоваться теми же методами, что ещё требуется от этого кода? Совершенно не понимаю ваших слов. Зачем мне в рабочем коде добавления в Object? Хотя, постойте ведь : Классы старого стиля упразднены в Python 3: теперь пользовательские типы, определённые без явного указания родителя, автоматически являются наследниками object.
Например, тебе нужно ввести в свою программу такую особенность: любой объект может регистрировать свои действия в лог-файле. То есть это любой объект может просто любое своё действие записать в общий файл, сообщив своё имя, чтобы потом читатель лог-файла мог видеть, какие объекты как работали и какие объекты когда и в какое время что писали. Как ты это сделаешь, если ты пронаследовался от класса object питона только? Никак ты это не сделаешь, так как тебе придётся в каждый свой класс, который наследуется только от класса object, добавлять это логирование. Это особенность вот этой объектной парадигмы: объекты есть, но когда надо с ними всеми что-то сделать, то это надо с каждым из них это делать. А если их тысяча? В программе там десять тысяч строк или двадцать тысяч строк, а объектов в ней просто тысяча? Да ты не сможешь просто даже добавить туда логирование, просто физически не сможешь. Неделю будешь сидеть и добавлять одно и то же. Будешь сидеть, добавлять и думать при этом “о! у меня есть класс этого объекта, сейчас я добавлю в этот класс это логирование!” и так тысячу раз надо будет сделать. А вот я в своём коде что сделаю? Я просто зайду в класс Object и добавлю это логирование в него один раз. Оно сразу через наследование пойдёт по всем классам распространяться. Сколько это времени у меня займёт? Ну, три минуты. А почему я могу так сделать? Да потому, что я этот класс Object полностью контролирую. А контролирую я его потому, что я не поленился его создать и везде пропихать, чтобы он везде мог до каждого своего экземпляра достучаться. Вот это и есть объектно-ориентированная парадигма. Есть не только объекты, есть ещё то направление, куда они там все смотрят и слушаются, берут под козырёк и выполняют приказ.

Можешь, конечно, ссылаться там на стандартное определение с Википедии или Гугла, но ты с этим определением далеко не уедешь. Будешь всё так же пользоваться этим “ООП” и ходить с транспарантом или на футболке написать “я пользуюсь ООП!”, но при этом которое не даёт никаких преимуществ вообще. То есть у тебя ничего просто не меняется. Как ты не мог быстро изменения вносить в большие, в громадные куски кода, так ты это и не можешь делать и дальше. Но зато с транспарантом ходишь в ногу с такими же - молодец. А ты задайся вопросом “эти ООПшники что написали за свои двадцать лет?”. Ну, как правило, там ничего нет.

m1r42
Переход на такую унифицированную объектную модель, помимо прочего, сделал возможным наследование от встроенных типов, применение дескрипторов, адекватное определение порядка разрешения методов при множественном наследовании.
Ну, мой класс Object наследуется от него. Вся эта питоновская хрень никуда не девается, а остаётся доступной.

m1r42
С удовольствием посмотрю на ваш код игры в исконно ООП варианте.
Если бы у меня было время писать, я бы написал. Но у меня есть время только на набросок. У тебя программ никаких нет? ну, которые там надо в репозиторий выкладывать сидеть, абстрагировать их сначала, версии проставлять там все, копирайты, документацию писать? Ну, вот у тебя нет, потому что ты пока что маленький, поэтому у тебя есть время на эти вот крестики-нолики. А у меня вот всё, я уже вырос, мне надо свои проги несколько штук выкладывать, и я думаю “а когда я на это время найду?”. Я на свои проги время найти не могу, а ты мне предлагаешь сейчас хернёй заняться. Я не против крестиков-ноликов, я сам их писал лет пятнадцать назад как свою первую программу и мне сейчас тоже интересно вот, докуда я вырос с тех пор и насколько сейчас я могу их забабахать, насколько грациозно они могут войти в мой список достижений теперь и занять своё почётное место, но я ещё месяц назад планировал выложить свою прогу, ещё до Нового года, а воз и ныне там, ничего не сделано. Я только сижу и в игры играю. В I.G.I.-2: Covert Strike вот сейчас заклинило. Раньше, знаешь, просто играл, а сейчас смотрю на эти боты в игре и изучаю, как они сделаны, как вот они их сделали. Сейчас у меня ООПшный взгляд на все эти игры, которого у меня раньше не было вообще, и я у них тоже перенимаю приёмы. Потом в своих прогах буду использовать это всё.

m1r42
Каждый может нарисовать чёрный квадрат чернее чем Малевич, но такой же не нарисует ни кто.
Ты знаешь, этот квадрат просто находится в контексте. То есть он что-то закрасил этим чёрным квадратом. Это какое-то его сообщение остальным художникам, кто понимает все смыслы, все теории и так далее. Таким образом он вызвал размышления, что человек может просто стоять перед этим квадратом и думать, что мог закрасить Малевич и почему он это сделал. А что там было бы, если бы он не закрасил это? Понимаешь, вот в этом прикол. Не в картинке дело.


tags: oop theory
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