• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Obiektowość i zależności w projekcie- Gra Statki w Pythonie

VPS Starter Arubacloud
0 głosów
1,302 wizyt
pytanie zadane 16 listopada 2019 w C i C++ przez zanstaszek9 Obywatel (1,930 p.)

Dzień dobry,
W ramach treningu Pythona, Gita i myślenia postanowiłem napisać prostą grę w statki używając Pythona, gra jest rozgrywana w oknie konsoli. Mój problem jest bardziej z tematu planowania klas, interakcji i ich czytelności.

Na ten moment mam trzy klasy: Users, Board i Battleship. Jestem w trakcie pisania metody do umieszczenia statku na planszy, i tutaj pojawiają się wątpliwości. Stworzyłem w klasie Board metodę put_ship która na ten moment sprawdza czy wprowadzone wartości są poprawne.

Chciałem dodać kolejny warunek, mianowicie czy statek o danym rozmiarze umieszczony na danym polu w danym kierunku zmieści się na planszy. W tym momencie zacząłem myśleć czy moje podejście jest właściwe, czy obiekt Board powinien faktycznie to sprawdzać, umieszczać i obliczać, czy nie lepiej byłoby to rozdzielić na coś dodatkowego? Z jednej strony, widzę planszę jako coś co może się wyświetlać pod różnymi postaciami i ewentualnie zmieniać dane na danym polu, ale chyba niezbyt czytelne i poprawne jest to żeby plansza obliczała czy Statek o rozmiarze 4 może zostać umieszczony na polu A2 w kierunku W czy już "wychodzi" z ram. Umieszczając tą logikę w tej klasie sprawiam że wtedy obiekt Plansza nie wykonuje tylko jednej rzeczy, wyświetlanie stanu gry, tylko ma dodatkowe zadania, a przez to więcej powodów aby ją zmodyfikować.

Umieszczam kod poniżej, znajduję się również na moim GitHubie wraz z klasą z testami poszczególnych funkcji: 

import numpy as np
import Battleship as bs


class Board:
    def __init__(self):
        self.grid = np.array([['.' for i in range(10)] for j in range(10)])

    def __str__(self):
        return "Gameboard"

    def show_board(self):
        for i in range(10):
            print(" {} ".format(chr(i+65)), end="")
        print(' /')
        for i in range(10):
            for j in range(10):
                print("[{}]".format(self.grid[i][j]), sep="", end="")
            print('', i + 1, end="")
            print()
        print()

    def check_field(self, x, y):
        if x is not str:
            return False;
        return self.grid[ord(x.upper())-65][int(y)]

    def put_ship(self, x: bs, field: str, direction: str = "E"):
        alert = "";
        if field[0].upper() not in "ABCDEFGHIJ":
            alert += "\nInvalid column letter. Enter letter from \"A\" to \"J\"."

        if not 0 < int(field[1]) < 11:
            alert += "\nInvalid row number. Enter number from \"1\" to \"10\"."

        if not alert and self.check_field(field[0], field[1]) != ".":
            alert += "\nField {} is not empty.".format(field)

        if direction not in ("N", "E", "S", "W"):
            alert += "\nWrong direction. Enter one of: {}.".format(("N", "E", "S", "W"))

        if alert is "":
            return True

        else:
            print(alert)
            return False

import Board as b
import Battleship as bs
import numpy as np


class User:
    def __init__(self, name = ""):
        self.name = "User"
        self.boards = {b.Board(), b.Board()}
        self.battleships = np.array([])

    def __str__(self):
        return self.name


    def create_ships(self):
        sizes = {4, 3, 3, 2, 2, 2, 1, 1, 1, 1}
        for size in sizes:
            bs.Battleship(size)

class Battleship:
    def __init__(self, size, place):
        self.size = size
        self.place = place  # Ex. A3A4A5A6
        self.swims = True

1 odpowiedź

+1 głos
odpowiedź 16 listopada 2019 przez adrian17 Ekspert (349,240 p.)
wybrane 17 listopada 2019 przez zanstaszek9
 
Najlepsza

czy obiekt Board powinien faktycznie to sprawdzać, umieszczać i obliczać

Dla mnie to brzmi jak jego podstawowe zadanie, więc tak.

Jak chcesz mieć to rozdzielone, to idealnie byłoby tak, gdyby klasy typu Board w ogóle nie wiedziały zupełnie nic o rysowaniu i żeby inne kawałki kodu przejmowały się jak to narysować w konsoli albo jak to pokazać w GUI. Na przykład put_ship() nie powinien działać na stringowych koordynatach i kierunkach, tylko już na "wewnętrznych" ładnych reprezentacjach. No i na pewno nie powinien print()ować jakiś komunikatów na konsolę - powinien po prostu rzucić wyjątek.

Natomiast na początek nie ma nic złego żeby klasa Board też zajmowała się rysowaniem siebie w konsoli - jednak wypada rozdzielić przynajmniej na osobne funkcje kawałki kodu odpowiadające za analizę stringowego wejścia z konsoli i pokazujące komunikaty, od kawałków kodu wykonujących faktyczną logikę gry.

A z bocznych tematów... użycie numpy.array wydaje się strasznie przekombinowane? Wystarczą zwykłe listy.

Podobne pytania

0 głosów
2 odpowiedzi 1,478 wizyt
pytanie zadane 16 stycznia 2019 w Nasze projekty przez Mavannkas Bywalec (2,290 p.)
0 głosów
3 odpowiedzi 1,920 wizyt
pytanie zadane 20 maja 2016 w C i C++ przez mat07 Nowicjusz (160 p.)
+7 głosów
5 odpowiedzi 7,733 wizyt
pytanie zadane 14 października 2015 w Nasze projekty przez emSon Stary wyjadacz (10,480 p.)

92,963 zapytań

141,928 odpowiedzi

321,161 komentarzy

62,297 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...