Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/163: Рейтинг темы: голосов - 163, средняя оценка - 4.76
0 / 0 / 0
Регистрация: 29.05.2019
Сообщений: 9
1

ООП. Написать игру крестики-нолики.

25.06.2019, 11:47. Показов 29602. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть вот такое вот задание
Написать игру крестики-нолики, используя как можно больше ООП.
Общие указания.
Все этапы независимы, вы можете реализовывать их в любом порядке.
Создавайте вспомогательные методы по необходимости.
Не забывайте про конструкторы и __str__
Этап 1.
Напишите класс Field - игровое поле. По умолчанию оно имеет размер 3х3.

Игровое поле должно иметь метод для заполнения клетки с указанными координатами указанным символом. Нулевой считается клетка в верхнем левом углу, она имеет координаты (0, 0).
Игровое поле должно иметь метод для проверки, занята ли клетка с указанными координатами, который возвращает True или False.
Игровое поле должно иметь метод для вывода себя на экран. Вместе с полем выводите значения координат, например:

0 1 2
0 o | x | o
-----------
1 | x |
-----------
2 | o | x
Этап 2.
Напишите класс Player - игрок.

При создании игрок получает символ, которым ходит.
У игрока должен быть метод, который возвращает координаты клетки, куда выполняется ход. Для игрока-человека координаты вводит пользователь. Если клетка уже занята, нужно вывести сообщение об этом и попросить ввести другую клетку. Метод принимает объект Field в аргументах.
Этап 3.
Напишите класс Brain - бот.

Бот наследуется от игрока.
Бот должен переопределять метод для совершения хода и самостоятельно выбирать клетку, куда будет ходить. Используйте любой алгоритм для выбора клетки, например, случайный выбор пустой клетки на поле. Бот должен выводить сообщение, куда он ходит.
Этап 4.
Напишите класс Checker - проверщик.

Проверщик должен содержать метод для определения, что один из игроков победил - построил на поле линию из одинаковых символов по вертикали, горизонтали или диагонали. Метод принимает объект Field для проверки в аргументах.
Этап 5.
Напишите класс Game - игра. Кроме конструктора, класс игры должен содержать один метод - главный цикл игры:

Выбор типа игры: 1 игрок или 2 игрока
Выбор первого игрока случайным образом
Пока поле не заполнилось или один из игроков не победил:



Ход первого игрока, проверка на победу, вывод игрового поля на экран


Ход второго игрока, проверка на победу, вывод игрового поля на экран




Вывод сообщения о победе.
Вывод "Сыграть ещё?", выход, если игрок отказался.
Должна быть возможность выхода из игры командой exit.
Вот что имеется на данный момент
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
class Field:
    EMPTY_CELL = ' '
 
    def __init__(self, size=3):
        self.size = size
        self.count = size * size
        self.cells = []
        for i in range(size):
            self.cells.append([Field.EMPTY_CELL] * size)
        # print(self.cells)
 
    def is_cell_empty(self, x, y):
        return self.cells[x][y] == Field.EMPTY_CELL
 
    def set_cell(self, x, y, value):
        self.cells[x][y] = value
        self.count -= 1
 
    def __str__(self):
        result = " " * 5
        for i in range(self.size):
            result += f"{i:^4}"
        line = "\n" + " " * 4 + "-" * (self.size * 4 + 1)
        result += line
        for i in range(self.size):
            row = f"{i:^4}" + "|"
            for j in range(self.size):
                row += f"{self.cells[i][j]:^3}" + "|"
            result += "\n" + row + line
        return result
 
 
 
 
class Player():
    def __init__(self, name, symbol, initial_score=0):
        self.name= name
        self.symbol= symbol
        self.score= initial_score
 
    def won_match(self):
        self.score+= 100
 
    def lost_match(self):
        self.score-= 50
 
    def show_score(self):
        print('Игрок {}: {} очки'.format(self.name, self.score))
 
 
 
class Game():
    def __init__(self, board, player1, player2):
        self.board = board
        self.players = [player1, player2]
        self.turn = 0
 
    def greet_user(self, currplayer):
        print ("Очередь игрока " + currplayer.symbol)
 
    def play(self):
        flag = False
 
        while flag == False:
            
            currplayer = self.players[self.turn]
          
            self.board.print_board()
          
            self.greet_user(currplayer)
            
            move = Move(self.board, currplayer)
            player_move = move.ask_for_move()
            
            self.board.tiles[player_move] = currplayer.symbol
            
            winner = self.check_win(currplayer.symbol)
           
            if winner != False:
                self.game_over(winner)
                flag = True
            
            else:
                self.turn = 1 - self.turn
 
    def check_win(self, player_symbol):
        tiles = self.board.tiles
 
        for i in range(3):
            if tiles[i] == player_symbol and tiles[i+3] == player_symbol and tiles[i+6] == player_symbol: #check for vertical win
                return player_symbol
            elif tiles[(i*3)] == player_symbol and tiles[(i*3) + 1] == player_symbol and tiles[(i*3) + 2] == player_symbol: #check for horizontal win
                return player_symbol
 
            
            if tiles[0] == player_symbol and tiles[4] == player_symbol and tiles[8] == player_symbol:
                return player_symbol
            elif tiles[2] == player_symbol and tiles[4] == player_symbol and tiles[6] == player_symbol:
                return player_symbol
 
        return False
 
    def game_over(self, player_symbol):
            print ("Игра закончена! Игрок " + player_symbol + "выиграл")
 
 
 
class Checker:
    def __init__(self):
        self.field = None
 
    def check(self, field):
        self.field = field.cells
        for i in range(3):
            result = self.check_horizontal_line(i)
            if result:
                return result
        for i in range(3):
            result = self.check_vertical_line(i)
            if result:
                return result
        result = self.check_diagonal_line()
        if result:
            return result
        result = self.check_back_diagonal_line()
        if result:
            return result
        return None
 
    def check_horizontal_line(self, line_id):
        counts = {
            'x': 0,
            'o': 0,
            Field.EMPTY_CELL: 0
        }
        for j in range(3):
            key = self.field[line_id][j]
            counts[key] += 1
        if counts['x'] == 3:
            return 'x'
        if counts['o'] == 3:
            return 'o'
        return None
 
    def check_vertical_line(self, line_id):
        counts = {
            'x': 0,
            'o': 0,
            Field.EMPTY_CELL: 0
        }
        for j in range(3):
            key = self.field[j][line_id] 
            counts[key] += 1
        if counts['x'] == 3:
            return 'x'
        if counts['o'] == 3:
            return 'o'
        return 0
 
    def check_diagonal_line(self):
        counts = {
            'x': 0,
            'o': 0,
            Field.EMPTY_CELL: 0
        }
        for i in range(3):
            key = self.field[i][i]
            counts[key] += 1
        if counts['x'] == 3:
            return 'x'
        if counts['o'] == 3:
            return 'o'
        return None
 
    def check_back_diagonal_line(self):
        counts = {
            'x': 0,
            'o': 0,
            Field.EMPTY_CELL: 0
        }
        for i in range(3):
            key = self.field[i][2 - i]  
            counts[key] += 1
        if counts['x'] == 3:
            return 'x'
        if counts['o'] == 3:
            return 'o'
        return None
 
 
class Player():
 
 
 
f = Field(3)
print(f)
p = Player()
f.set_cell(1, 0, 'x')
print(f)
f.set_cell(0, 2, 'x')
f.set_cell(1, 1, 'o')
f.set_cell(2, 0, 'o')
f.set_cell(1, 2, 'x')
f.set_cell(2, 2, 'o')
f.set_cell(0, 0, 'x')
print(f)
print(f.is_cell_empty(1, 0))
print(f.is_cell_empty(1, 1))
 
checker = Checker()
print(checker.check(f))
Добавлено через 4 минуты
Окончательно запутался в том что написал.Помогите кто может выполнить задание. c классом Player и с классом Brain
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.06.2019, 11:47
Ответы с готовыми решениями:

Написать консольную вариацию игры крестики-нолики
Написать консольную вариацию игры крестики-нолики. python 3.7

Крестики-нолики
Напишите класс TicTacToeBoard для игры в крестики-нолики, который должен иметь следующие методы: ...

Крестики-нолики
Напишите функцию tic_tac_toe(field), которая принимает на вход список списков 3х3 — поле игры в...

Нолики-крестики
Напишите программу, которая определяет, кто выиграл в крестики-нолики на увеличенном квадратном...

6
1728 / 968 / 199
Регистрация: 22.02.2018
Сообщений: 2,694
Записей в блоге: 6
25.06.2019, 13:28 2
K312, Основная ошибка, которую делают используя ООП, это применяют средства ООП чисто механически. Однако, так как ООП моделирует мыслительные образы человека, такие как классы, например класс Игра, класс ИгрокЧеловек, класс ИгрокРобот, класс ПолеИгры, класс ЯчейкаПоля. Нужно мысленно представить игру, представить эти классы, продумать какие свойства и методы у экземпляров этих классов, то есть у конкретных объектов принадлежащих этим классам. У Вас слишком емкая задача, задается слишком много классов. В мышлении человека любой объект является экземпляром класса и как правило не одного. Реализовать все классы, к которым принадлежит объект мышления, это не реально, поэтому при программировании нужно ограничиваться только основным классом для этого объекта. Работать со всем огромным разнообразием классов, которым принадлежит объект, способен только мозг человека, но не программа компьютера.
Не понятно кто Вам дал такое емкое задание. Или Вы сами придумали для себя задание?
Итак на пример рассмотрим класс ПолеИгры. Небольшое замечание. В базах данных field обычно называют поля(названия столбцов) таблицы. Поэтому для меня название класса Field немного режет слух. Да и вообще понятие Поле является более общим, например пшеничное поле или футбольное поле. Поэтому логичнее было бы назвать ПолеИгры (FieldGame).
Итак представим себе поле игры в крестики нолики. Какие у него свойства и методы.
Основное свойство, это размеры ширина m и высота n.
Второе свойство, игровое поле содержит m*n количество экземпляров класса ЯчейкаПоля. Так как это упорядоченное множество объектов, имеет смысл разместить их в списке, и назвать свойство СписокЯчеек (listCell).
И дальше в том же духе.
Работы много, если делать основательно.
Но может кто то сделает Вам по быстрому, чисто механически как бы используя ООП.

Добавлено через 3 минуты
Я уже не помню, если поле в крестиках-ноликах всегда квадратное, тогда первое свойство это размер стороны n .
0
Эксперт Python
4632 / 2050 / 361
Регистрация: 17.03.2012
Сообщений: 10,133
Записей в блоге: 6
25.06.2019, 13:34 3
Viktorrus, нормальное задание, классов тут немного.
Кстати, если уж придираться к слову Field, то его следует заменить на Board.

K312, в целом норм для новичка. В check_win, видимо, надо использовать Checker? Или я чего-то не заметил?
"Сделать ход" - сомнительное решение, что этим должен заниматься класс Field (доска), это же игровой процесс, должно быть в классе Game.
И проверять выигрыш надо после каждого хода.
Заюзайте numpy, если можно, проще будет проверять состояние.
0
0 / 0 / 0
Регистрация: 29.05.2019
Сообщений: 9
25.06.2019, 13:46  [ТС] 4
numpy как я понял использовать нельзя нужно все сделать по ТЗ. А я что то запутался в конец ни чего не выходит
0
Эксперт Python
4632 / 2050 / 361
Регистрация: 17.03.2012
Сообщений: 10,133
Записей в блоге: 6
25.06.2019, 14:10 5
K312, в ТЗ я не увидел ничего, что запрещало бы использование numpy. Его, конечно, не стоит использовать, если проверка автоматизирована и выполняется на стороннем компьютере, а так - - -

По заданию. Разбираться подробно в вашем коде я не хочу. Просто дам советы. Как верно заметил Victorrus, объекты программы должны отражать привычные нам объекты реального мира и их действия.
Пусть будет класс Game, который отвечает за игровой процесс. Именно процесс, то есть - выполнение ходов по очереди.
Класс Board - норм. Возможно, в него и засунуть проверку, что кто-то выиграл. Класс Player - основное занятие - придумать, куда сделать следующий ход, и выдать это наружу. Для начала игрок-компьютер может выбирать клетку случайно, чтобы вам не заморачиваться с логикой игры. Спрашивать клетку будет Game. Поскольку игроку нужна информация о поле, ему передать Board.

Желаю удачи.

Добавлено через 5 минут
По поводу numpy. Нужные вам срезы берутся в одно действие:

Python
1
2
3
4
5
6
7
8
9
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
a[[0,1,2], [0,1,2]]  # главная диагональ
Out[6]: array([0, 4, 8])
a[:,0]  # вертикаль
Out[7]: array([0, 3, 6])
a[[2,1,0], [0,1,2]]  # побочная диагональ
Out[8]: array([6, 4, 2])
Думаю, оно того стоит.
1
1728 / 968 / 199
Регистрация: 22.02.2018
Сообщений: 2,694
Записей в блоге: 6
25.06.2019, 16:46 6
K312, Кстати Ваш код, как Вы его выложили, не запускается, и отладчик ругается, потому что недопустима запись
Python
1
2
3
4
5
class Player():
 
 
 
f = Field(3)
Для того, что бы тестировать, пока не написан класс Player, вставте в него pass
Python
1
2
3
4
5
6
class Player():
    pass
 
 
 
f = Field(3)
0
0 / 0 / 0
Регистрация: 24.03.2023
Сообщений: 5
26.03.2023, 11:35 7
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class TicTacToeBoard:
    def __init__(self):
        self.field = [['-' for _ in range(3)] for _ in range(3)]
        self.variations = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]
        self.isPlaying = True
        self.step = 0
 
    def new_game(self):
        self.field = [['-' for _ in range(3)] for _ in range(3)]
        self.step = 0
        self.isPlaying = True
 
    def get_field(self):
        return self.field
 
    def check_field(self):
        if any({not set(v) - {i for i, s in enumerate([i for x in self.field for i in x]) if s == 'X'} for v in self.variations}):
            return 'X'
        if any({not set(v) - {i for i, s in enumerate([i for x in self.field for i in x]) if s == '0'} for v in self.variations}):
            return 'D'
        return None
 
    def make_move(self, row, col):
        if self.isPlaying:
            if self.field[row - 1][col - 1] == '-':
                self.field[row - 1][col - 1] = 'X' if self.step % 2 == 0 else '0'
                self.step += 1
                if self.check_field() == 'D':
                    self.isPlaying = False
                    return "Победил игрок 0"
                if self.check_field() == 'X':
                    self.isPlaying = False
                    return "Победил игрок X"
                return "Продолжаем играть"
            if self.step == 9:
                return "Ничья"
            return f"Клетка {row}, {col} уже занята"
        return "Игра уже завершена"
0
26.03.2023, 11:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.03.2023, 11:35
Помогаю со студенческими работами здесь

Крестики-нолики
Мне надо сделать игру крестики-нолики, как бы... игра простая, в интернете бесконечное количество...

Крестики-нолики
Два игрока играют в крестики-нолики. Напишите программу, которая после каждого хода игрока...

Крестики-нолики
Напишите класс TicTacToeBoard для игры в крестики-нолики, который должен иметь следующие методы: ...

Крестики-нолики
Напишите функцию tic_tac_toe(field), которая принимает на вход список списков 3х3 — поле игры в...

Крестики-нолики
Добрый день! Подскажите, как из строки построить матрицу 3*3 Enter cells: "O OXXO XX" ---------...

Крестики - нолики
Здравствуйте! Можете пожалуйста помочь решить с использованием функции def без return) Напишите...

Крестики-нолики
Напишите функцию Tic_tac_toe(field), которая принимает на вход список списков 3х3 - поле игры в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru