+ tz 5.6_01
This commit is contained in:
parent
c22ef9e724
commit
48f083afaf
172
mod_oop/5.6_01_sea_battle.py
Normal file
172
mod_oop/5.6_01_sea_battle.py
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
"""
|
||||||
|
https://stepik.org/lesson/727588/step/1?unit=728924
|
||||||
|
|
||||||
|
Посвящение в ООП
|
||||||
|
|
||||||
|
Вы прошли серию испытаний и совершили множество подвигов, чтобы лицом к лицу столкнуться с настоящим вызовом, достойным лишь избранных!
|
||||||
|
Для подтверждения своих знаний и навыков вам предлагается пройти этап посвящения в объектно-ориентированное программирование.
|
||||||
|
И вот задание, которое выпало на вашу долю.
|
||||||
|
|
||||||
|
Руководство компании целыми днями не знает куда себя деть. Поэтому они решили дать задание своим программистам написать программу игры "Морской бой".
|
||||||
|
Но эта игра будет немного отличаться от классической. Для тех, кто не знаком с этой древней, как мир, игрой, напомню ее краткое описание.
|
||||||
|
|
||||||
|
Каждый игрок у себя на бумаге рисует игровое поле 10 х 10 клеток и расставляет на нем десять кораблей: однопалубных - 4; двухпалубных - 3; трехпалубных - 2; четырехпалубный - 1.
|
||||||
|
Корабли расставляются случайным образом, но так, чтобы не выходили за пределы игрового поля и не соприкасались друг с другом (в том числе и по диагонали).
|
||||||
|
|
||||||
|
Затем, игроки по очереди называют клетки, куда производят выстрелы.
|
||||||
|
И отмечают эти выстрелы на другом таком же поле в 10 х 10 клеток, которое представляет поле соперника.
|
||||||
|
Соперник при этом должен честно отвечать: "промах", если ни один корабль не был задет и "попал", если произошло попадание.
|
||||||
|
Выигрывает тот игрок, который первым поразит все корабли соперника.
|
||||||
|
|
||||||
|
Но это была игра из глубокого прошлого.
|
||||||
|
Теперь же, в компьютерную эру, корабли на игровом поле могут перемещаться в направлении своей ориентации на одну клетку после каждого хода соперника, если в них не было ни одного попадания.
|
||||||
|
|
||||||
|
Итак, лично вам поручается сделать важный фрагмент этой игры - расстановку и управление кораблями в этой игре. А само задание звучит так.
|
||||||
|
|
||||||
|
Техническое задание
|
||||||
|
|
||||||
|
В программе необходимо объявить два класса:
|
||||||
|
Ship - для представления кораблей;
|
||||||
|
GamePole - для описания игрового поля.
|
||||||
|
|
||||||
|
Класс Ship
|
||||||
|
Класс Ship должен описывать корабли набором следующих параметров:
|
||||||
|
x, y - координаты начала расположения корабля (целые числа);
|
||||||
|
length - длина корабля (число палуб: целое значение: 1, 2, 3 или 4);
|
||||||
|
tp - ориентация корабля (1 - горизонтальная; 2 - вертикальная).
|
||||||
|
|
||||||
|
Объекты класса Ship должны создаваться командами:
|
||||||
|
ship = Ship(length)
|
||||||
|
ship = Ship(length, tp)
|
||||||
|
ship = Ship(length, tp, x, y)
|
||||||
|
|
||||||
|
По умолчанию (если не указывается) параметр tp = 1, а координаты x, y равны None.
|
||||||
|
|
||||||
|
В каждом объекте класса Ship должны формироваться следующие локальные атрибуты:
|
||||||
|
_x, _y - координаты корабля (целые значения в диапазоне [0; size), где size - размер игрового поля);
|
||||||
|
_length - длина корабля (число палуб);
|
||||||
|
_tp - ориентация корабля;
|
||||||
|
_is_move - возможно ли перемещение корабля (изначально равно True);
|
||||||
|
_cells - изначально список длиной length, состоящий из единиц (например, при length=3, _cells = [1, 1, 1]).
|
||||||
|
|
||||||
|
Список _cells будет сигнализировать о попадании соперником в какую-либо палубу корабля. Если стоит 1, то попадания не было, а если стоит значение 2, то произошло попадание в соответствующую палубу.
|
||||||
|
|
||||||
|
При попадании в корабль (хотя бы одну его палубу), флаг _is_move устанавливается в False и перемещение корабля по игровому полю прекращается.
|
||||||
|
|
||||||
|
В самом классе Ship должны быть реализованы следующие методы (конечно, возможны и другие, дополнительные):
|
||||||
|
set_start_coords(x, y) - установка начальных координат (запись значений в локальные атрибуты _x, _y);
|
||||||
|
get_start_coords() - получение начальных координат корабля в виде кортежа x, y;
|
||||||
|
move(go) - перемещение корабля в направлении его ориентации на go клеток (go = 1 - движение в одну сторону на клетку; go = -1 - движение в другую сторону на одну клетку); движение возможно только если флаг _is_move = True;
|
||||||
|
is_collide(ship) - проверка на столкновение с другим кораблем ship (столкновением считается, если другой корабль или пересекается с текущим или просто соприкасается, в том числе и по диагонали); метод возвращает True, если столкновение есть и False - в противном случае;
|
||||||
|
is_out_pole(size) - проверка на выход корабля за пределы игрового поля (size - размер игрового поля, обычно, size = 10); возвращается булево значение True, если корабль вышел из игрового поля и False - в противном случае;
|
||||||
|
|
||||||
|
С помощью магических методов __getitem__() и __setitem__() обеспечить доступ к коллекции _cells следующим образом:
|
||||||
|
value = ship[indx] # считывание значения из _cells по индексу indx (индекс отсчитывается от 0)
|
||||||
|
ship[indx] = value # запись нового значения в коллекцию _cells
|
||||||
|
Класс GamePole
|
||||||
|
Следующий класс GamePole должен обеспечивать работу с игровым полем. Объекты этого класса создаются командой:
|
||||||
|
|
||||||
|
pole = GamePole(size)
|
||||||
|
где size - размеры игрового поля (обычно, size = 10).
|
||||||
|
|
||||||
|
В каждом объекте этого класса должны формироваться локальные атрибуты:
|
||||||
|
_size - размер игрового поля (целое положительное число);
|
||||||
|
_ships - список из кораблей (объектов класса Ship); изначально пустой список.
|
||||||
|
|
||||||
|
В самом классе GamePole должны быть реализованы следующие методы (возможны и другие, дополнительные методы):
|
||||||
|
init() - начальная инициализация игрового поля; здесь создается список из кораблей (объектов класса Ship): однопалубных - 4; двухпалубных - 3; трехпалубных - 2; четырехпалубный - 1 (ориентация этих кораблей должна быть случайной).
|
||||||
|
|
||||||
|
Корабли формируются в коллекции _ships следующим образом: однопалубных - 4; двухпалубных - 3; трехпалубных - 2; четырехпалубный - 1. Ориентация этих кораблей должна быть случайной. Для этого можно воспользоваться функцией randint следующим образом:
|
||||||
|
[Ship(4, tp=randint(1, 2)), Ship(3, tp=randint(1, 2)), Ship(3, tp=randint(1, 2)), ...]
|
||||||
|
Начальные координаты x, y не расставленных кораблей равны None.
|
||||||
|
|
||||||
|
После этого, выполняется их расстановка на игровом поле со случайными координатами так, чтобы корабли не пересекались между собой.
|
||||||
|
|
||||||
|
get_ships() - возвращает коллекцию _ships;
|
||||||
|
move_ships() - перемещает каждый корабль из коллекции _ships на одну клетку (случайным образом вперед или назад) в направлении ориентации корабля; если перемещение в выбранную сторону невозможно (другой корабль или пределы игрового поля), то попытаться переместиться в противоположную сторону, иначе (если перемещения невозможны), оставаться на месте;
|
||||||
|
show() - отображение игрового поля в консоли (корабли должны отображаться значениями из коллекции _cells каждого корабля, вода - значением 0);
|
||||||
|
|
||||||
|
get_pole() - получение текущего игрового поля в виде двумерного (вложенного) кортежа размерами size x size элементов.
|
||||||
|
|
||||||
|
Пример отображения игрового поля:
|
||||||
|
0 0 1 0 1 1 1 0 0 0
|
||||||
|
1 0 0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 1 0 0 1
|
||||||
|
0 0 0 0 1 0 1 0 0 1
|
||||||
|
0 0 0 0 0 0 1 0 0 0
|
||||||
|
1 1 0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 1 0 0 0
|
||||||
|
0 1 1 1 1 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 1 1 0
|
||||||
|
|
||||||
|
Пример использования классов (эти строчки в программе не писать):
|
||||||
|
|
||||||
|
SIZE_GAME_POLE = 10
|
||||||
|
|
||||||
|
pole = GamePole(SIZE_GAME_POLE)
|
||||||
|
pole.init()
|
||||||
|
pole.show()
|
||||||
|
|
||||||
|
pole.move_ships()
|
||||||
|
print()
|
||||||
|
pole.show()
|
||||||
|
|
||||||
|
В программе требуется только объявить классы Ship и GamePole с соответствующим функционалом. На экран выводить ничего не нужно.
|
||||||
|
|
||||||
|
P.S. Для самых преданных поклонников программирования и ООП. Завершите эту программу, добавив еще один класс SeaBattle для управления игровым процессом в целом.
|
||||||
|
Игра должна осуществляться между человеком и компьютером. Выстрелы со стороны компьютера можно реализовать случайным образом в свободные клетки.
|
||||||
|
Сыграйте в эту игру и выиграйте у компьютера.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def tests():
|
||||||
|
code = (
|
||||||
|
b"b7*OBAUz;cXlZaLGARmkXlZaDJs?wPX>ceqEFdu{3Ug>_a3DP(Q)p>$C^IY|GAtl4EFdr`3JPI"
|
||||||
|
+ b"!b7gXLAaiJGa4uhLWo~D5Xdpd3ATuCgZe$>HXlZaRUvzLFJv|^YAYpD~AaiJGa4uhXAU!=GFd$)W"
|
||||||
|
+ b"WFT{BX>cxIc_2MKATTT-BGA3iwa~KAwb6jkz0r%%wII;9(7n*G(TC8r(7n*O(T^a|u+f6ifY7+mv"
|
||||||
|
+ b"C)Ikg3!LuvLMjD(6P~q(6!LI(Sp#hAkezdyU?)Ffzg4`upm=tX>cM6VRLh3a&#bbXlZaRUt?u#Y;"
|
||||||
|
+ b"zzzJs?{#EFdu~ATeDmAR^Gc(6!LA(6!Nk(7n-%(77PdfzZFuxY2>ozR<cLUt?u#Y;z(CVRLh3a&#"
|
||||||
|
+ b"bbXlZaRUukn+ZEtpEEFdD#z0kGLve32BfY80rzR<NG(6`XN(6G^m(6!LL(74dGAkeVUg3*A`xX`i"
|
||||||
|
+ b"DgVBP}upnP)b6;(5c4Z<83Ug>_a4vIYbYF9HVRCd|V{dPAWOFDnEFdx|3So0|WpZ>Nb7*OBE?;;c"
|
||||||
|
+ b"Jv|^XAYpD~AaiJGa4uhYAU!=GGAtk>(7n*L(6Z3A(SXps(7qthzR`lwfY7kevCzKJg3z$gyCBfK("
|
||||||
|
+ b"6!Nm(7w>LAaiAOUvqR}a&%u~Z*OvBb0{ey3So0|WpZ>Nb7*OBE@x$QUvqR}a&%u~Z*OvBb0{ewJv"
|
||||||
|
+ b"|^OF)Sc5DJ&o&(7n*L(6Z3A(SXps(7qthzR`lwfY7kevCzKJg3z$gyCBfK(6!Nm(7w>LAZKNCUvq"
|
||||||
|
+ b"R}a&%u~Z*OvBb0{ey3JP;*X>cxWZ+2xUF)0djF(5r4Q)p>$C^Re}F)Sc3EFdr`3Ue|bJs?wPX>ce"
|
||||||
|
+ b"rEFdy0ATTT-FewUiGax-6Q)p>$C^IY|GAtl4EFdx|3JPI!b7gXLAagM;X>(s=Z)|L7WMwFGGAS$|"
|
||||||
|
+ b"BGA3iwa~KAwb6jkz0kfO(SXpf(6P|I(Sp#h(6!NmAke(fwb6pmzR<KFX>(s=Z)|L7WMwERAkehXy"
|
||||||
|
+ b"U~vz(7MpR(SXpf(6P|F(6!LHAX8{*a40k^ATcZ;Ff1T2DIn0eAX8{*a40h@ATlf<Ff1T2DIyACb8"
|
||||||
|
+ b"}^KbRcsvE@^XLV{dG1X=G(6b2BL*Jv|^sVQh0{EFdD#z0kGLve32BfY80rz97+n(6G?4(7w@v(6G"
|
||||||
|
+ b"?8(Sjh*ywJ7Lg3!Luv><77Ut@1<Y-wa=C@CP&w9vcJk08*x(7w@t(6G?4(7VvJ(77N}XlZaLG%O%"
|
||||||
|
+ b"7EFdr}ATTK)(6}H|XlZaLGb|u7EFdr}ATlW;3JP;FAUz;cXlZaLGb|u7EFdu~ATcQlVRLh3a&#bb"
|
||||||
|
+ b"F)nFyUt@1<Y-wa=D04C?EFdD#z0kGLve32BfY80rz97+n(6G?4(7w@v(6G?8(Sjh*ywJ7Lg3!Luv"
|
||||||
|
+ b"><77Ut@1<Y-wa=C@CP&w9vcJk08*x(7w@t(6G?4(7VvJ(77N}XlZaLG%O%7EFdr}ATTK)(6}H|Xl"
|
||||||
|
+ b"ZaLGb|u7EFdu~ATcQ-3JP;FAUz;cXlZaLGb|u6EFd^6ATcQlVRLh3a&#bbGA?OzUvG7EUvO`1Whg"
|
||||||
|
+ b"N)DJ&o&(7n*L(6Z3A(SXps(7qtifY7kevCzKJg3z$gwb6ng(7e#K(Sp#v(6k_Fb6;<DbYF09Y-K1"
|
||||||
|
+ b"ZAkehXyU~vz(7MpR(SXpf(6P|F(T^ZgXlZaLGb|u6EFd^6ATcQ-3JP;FAUz;cXlZaLGb|u7EFdu~"
|
||||||
|
+ b"AT=opVRLh3a&#bbGA?OzUvG7EUvO`1WhgN)DIh&PAVy(qb7d?bBGA3iwa~KAwb6jkz0kfO(SXpf("
|
||||||
|
+ b"6P|I(Sp#h(6!NmAke(fwb6pmzR<KFX>(t1b#z~FZ){~KF)%40(6rFI(T^a|y3oGSfY7kevCzBGk0"
|
||||||
|
+ b"4WMX>cerEFdy0ATcZ;H7Ozr3Ue}BFkK)$ATkPJb8}^KbRcswTQFT9Jv|^YEFdD#z0kGLve32BfY8"
|
||||||
|
+ b"0rz97+n(6G?4(7w@v(6G?8(Sjh*zR<DJfY7kfiO{vsz0kPOwIFk7X>eO<Ze(~}A_@v{AUz;QVQpn"
|
||||||
|
+ b"lZ){~KF)%3#a4u<XX>=$l3TAI|AZ~6TX>K5LVQyz-C^acM3LqdLAZBlJAafvTZXj?jUvp?_aC15e"
|
||||||
|
+ b"ARr(hARr(hVRLh3a&#bbE@^XLZ*_EEaBpm7C^0Z8AU!=GMqzAoWh@{f(7MpR(SXpf(6P|F(6}Jbv"
|
||||||
|
+ b"eApth0wmxw9${zf*{bh(6AuTztMouwa~QCwa~lKiy+Xr(6iBi(7w>J(7w>K(7qthztFzWyU~v#3J"
|
||||||
|
+ b"M?~ARr(hARuOMav*bPX>cHEZXj?jXJvF>b7*OBb0{e~3LqdLARr(hARr(hAZcbGb08r-AaiJGa5@"
|
||||||
|
+ b"SgARr(hARr(hARr(hARr)Nb8}^KbRcssX>(s=Z)|L7WMwFGXlZaMAU!=GMqzAoWh@{f(7MpR(SXp"
|
||||||
|
+ b"f(6P|F(6}Jbz0j~A(74dE(SXpt(6Z3J(7YhfztFzWyU?{D(Sgvu(7(}u(74dL(6G^g(6G^t(Sp%|"
|
||||||
|
+ b"(T^euARr(ha4v0cc4c34XlZbBC@BgcARr(LXK)}rAaE{cWprO~Z){~KDGFh8b7gXLAar?fWhiHGD"
|
||||||
|
+ b"Ih&PAar$bY-J!}Ze$>Id2nSYXK-6ET`3?vJs@;-aBO8PAR^Gb(6!Nm(7w>LAZKNCUvO`1WgyVB(7"
|
||||||
|
+ b"w>S(6-RE(7hngve3TJx6rcDfY7kfiO{gog3*j1(6rF9(Sy*u(6!Nk(7n-%(77Pcy3oGSfYE}`wa~"
|
||||||
|
+ b"UA3So0|WpZ>NY-MgJXK*PXJv|^XFd$)WWFTy1ZYXDPTQFTIAU!=GF)%D3BGA3iwa~KAwb6jkz0r%"
|
||||||
|
+ b"%wII=e(6G?A(7e#K(SXs5Aketbv(bRizR<GJzR<JKz97)Q(7w>S(T^-3(7MpR(Sp#v(SXpt(6u1Y"
|
||||||
|
+ b"ve32BfY80sgV4Jm(7e#K(Sp#v(6k_DWprO~Z){~E3JP#<Y-L|_X?kT}I3PVBM`3McP;YEyC^#t!a"
|
||||||
|
+ b"Bpm7Uvp`CWnVZhX>MtBC@B"
|
||||||
|
)
|
||||||
|
exec(__import__("base64").b85decode(code))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
tests()
|
Loading…
Reference in New Issue
Block a user