@K-VKO

Как научиться правильно использовать классы?

Я учу Свифт и все вроде бы ок, но я никак не могу понять как использовать классы и структуры.

Прочитав оф. документацию я понимаю что класс может хранить это и это, у него могут быть методы и бла бла бла....
Но когда доходит до: "написать простенькую игру" у меня проблемы "версткой" кода.

Должен быть 1 глобальный класс Game, который хранит все свойства и методы всего что есть в игре ?
Должен быть класс Game, внутри вложенные классы ?
Классы должны быть разделены, например: класс Game, класс Person, класс Board(поле) и т.д. ?
Другой вариант?

Коротко об игре(для примера):
Рисуется поле, добавляется игрок, коробка и портал. (все в консоли)
Нужно сдвинуть коробку в портал чтобы победить.
61a09e5333c3b421009568.jpeg

Пример моего кода

import Foundation


class Game {
    var height: Int
    var width: Int
    private lazy var board: [[String]] = {
            var gameBoard: [[String]] = []
             for i in 0...height - 1 {
                 if i == 0 || i == height - 1 {
                     gameBoard.append(Array(repeating: "", count: width))
                 } else {
                     var basicLine = Array(repeating: "⬜", count: width)
                     basicLine[0] = ""
                     basicLine[basicLine.count - 1] = ""
                     gameBoard.append(basicLine)
                 }
             }
            return gameBoard
   } ()
    private var alienPosition = (1, 1) {
        willSet {
            board[alienPosition.0][alienPosition.1] = "⬜"
        } didSet {
            if boxPosition == (board.count - 2, board.count - 2) {
                clearConsole()
                    print("YOU WIN!!! ")
            } else {
                clearConsole()
                addBoxOnBoard()
                addAlienOnBoard()
                print(self.board.forEach { print($0.joined(separator: "")) })
            }
        }
    }
    private lazy var boxPosition = (board.count / 2, board.count / 2)
    
    init(height: Int, width: Int) {
        self.height = height
        self.width = width
        loading()
        clearConsole()
        addBoxOnBoard()
        addAlienOnBoard()
        addPortalOnBoard()
        print(self.board.forEach { print($0.joined(separator: "")) })
    }
    private func loading() {
        var loadingPercent = 0
        let size = 10
        var squares = Array(repeating: "□", count: size)
        for (i, _) in squares.enumerated() {
           clearConsole()
           squares[i] = "■"
           loadingPercent += 10
           print("\(squares.joined(separator: " ")) \(loadingPercent) %")
            usleep(5)
        }
    }
    private func clearConsole() {
        for _ in 1...30 {
            print("")
        }
    }
    private func addAlienOnBoard() {
        board[alienPosition.0][alienPosition.1] = ""
    }
    private func addBoxOnBoard() {
        board[boxPosition.0][boxPosition.1] = ""
    }
    private func addPortalOnBoard() {
        board[board.count - 2][board.count - 2] = ""
    }
   
    enum Move {
        case up
        case down
        case right
        case left
    }
    func moveAlien(direction: Move) {
        switch direction {
        case .up:
            if (alienPosition.0 - 1, alienPosition.1) != boxPosition && board[alienPosition.0 - 1][alienPosition.1] != " " {
                alienPosition.0 -= 1
            } else if (alienPosition.0 + 1, alienPosition.1) == boxPosition && board[boxPosition.0 - 1][boxPosition.1] != " "{
                boxPosition.0 -= 1
                alienPosition.0 -= 1
            }
        case .down:
            if (alienPosition.0 + 1, alienPosition.1) != boxPosition && board[alienPosition.0 + 1][alienPosition.1] != "" {
                alienPosition.0 += 1
            } else if (alienPosition.0 + 1, alienPosition.1) == boxPosition && board[boxPosition.0 + 1][boxPosition.1] != ""{
                boxPosition.0 += 1
                alienPosition.0 += 1
            }
        case .right:
            if (alienPosition.0, alienPosition.1 + 1) != boxPosition && board[alienPosition.0][alienPosition.1 + 1] != "" {
                alienPosition.1 += 1
            } else if (alienPosition.0, alienPosition.1 + 1) == boxPosition && board[boxPosition.0][boxPosition.1 + 1] != ""{
                boxPosition.1 += 1
                alienPosition.1 += 1
            }
        case .left:
            if (alienPosition.0, alienPosition.1 - 1) != boxPosition && board[alienPosition.0][alienPosition.1 - 1] != "" {
                alienPosition.1 -= 1
            } else if (alienPosition.0, alienPosition.1 - 1) == boxPosition && board[boxPosition.0][boxPosition.1 - 1] != " "{
                boxPosition.1 -= 1
                alienPosition.1 -= 1
            }
        }
    }
    
}


let myGame8 = Game(height: 6, width: 6)

  • Вопрос задан
  • 265 просмотров
Пригласить эксперта
Ответы на вопрос 3
briahas
@briahas
ObjC, Swift, Python
Ваш вопрос относится к архитектуре приложения, а не к "как правильно использовать классы".

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

Мой ответ - пишите как хотите (это в себе подразумевает и "как нравится" и " как легче" и "как левая пятка захочет"). Вы только учитесь, и если вы не гений, то, полюбому, сначала напишите не правильно. Так что - тренируйтесь, и , как следствие, учитесь.
Ответ написан
Alexandroppolus
@Alexandroppolus
кодир
Курить принципы SOLID, GRASP, DI, и т.д. Паттерны, опять же. Во время сочинения кода проверять, соответствуют ли твои идеи этим принципам. Конечная цель - "сильная связность и слабая зацепленность", тогда твой код сможет быть простым и понятным.
Но всё в меру.
Ответ написан
Комментировать
На самом деле в изучении swift лучше всего тренироваться не на играх или подобных историях, а уже в xcode, создать новый проект и писать, потому что потом может получиться ситуация, что понять то поняли, а как это преобразовать в реальность - понимания нет.

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

class Test {
    var number: Int?
}


Потом мы соответственно создаем объекты класса, повторюсь, это просто ссылки на класс, а сам класс - это один объект в памяти

class Test {
    var number = 10
}

var objectOne = Test()
var objectTwo = Test()


Теперь мы в первом объекте изменим переменную "number" дадим ей число 10

class Test {
    var number = 10
}

var objectOne = Test()
var objectTwo = Test()

objectOne.number = 10


Тем самым мы с помощью ссылки на класс, изменили эту переменную в самом классе, то есть теперь сам класс содержит в переменной number число 10, и если мы напечатаем эту переменную уже через второй объект, мы получим число 10, хотя во втором объекте мы ничего не меняли.

class Test {
    var number = 10
}

var objectOne = Test()
var objectTwo = Test()

objectOne.number = 10

print(objectTwo.number) // - будет 10


То есть когда мы попытались напечатать number нашего объекта, мы просто посмотрели класс по ссылке, посмотрели что у нас там в number и напечатали это число, ранее мы в него положили число 10, поэтому и получим число 10.

По итогу имеем следующее: Класс - это единичный объект в памяти, он один, а объектов класса может быть сколько угодно, это ссылки на сам класс, мы можем менять наш класс в любом месте по разному, сначала мы в нашем файле получим ссылку на класс, изменим ее как нам угодно, в другом месте мы снова можем получить
ссылку на класс, изменить ее уже по другому, но объект останется один, не важно сколько ссылок мы создали.

______
Что касается разработки, по факту, почти всегда даже неопытные программисты как Я, создают много разных классов, а потом отдельно оперируют ими, работать в одном классе удобно только в самом начале, но стоит хоть немного начать углубляться в понимание языка, мы столкнемся с тем, что наш класс будет содержать в себе по 2000 строк кода, и нужно будет каждый раз разбираться в том, за что он отвечает и что делает, поэтому и разрабатываются архитектуры и подходы, чтобы разделять обязанности. То есть каждый отдельный класс будет отвечать только за свою часть работы. Класс "person" будет отвечать только за то, что будет содержать наш пользователь, как его можно изменить, и полностью его реализовывать. Класс "sword" будет содержать все характеристики нашего меча, а enum "weapons" будет содержать в себе все классы со всеми видами оружия, и тем самым у нас каждое оружие описывается своим классом, enum содержит в себе все возможные виды оружия, а Person содержит конкретное оружие, получаемое через enum.

На самом деле каждый программист напишет по своему, но подходы к разделению будут одинаковые, и зависеть от выбранной архитектуры, то есть если 2 программиста выберут одну архитектуру, у них будет одно количество классов, но каждый класс будет реализован по разному, тут уже чисто как вижу так и реализую, главное писать так, чтоб другие тоже смогли понять, что вообще происходит. (Пример грубый, в реальности все сложнее, но для общего понимания подойдет)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы