dub
dub

Reputation: 491

How To Use Int in enum

I want to create a list of levels with a score required to reach that level. But I'm not sure how best to do it.

For example I tried an enum like this:

    enum xpLevels {
    case 1 = 0...50
    case 2 = 51...100
    case 3 = 101...200
}

But this gives me errors saying: "Consecutive declarations on a line must be separated by ';'"

And I'm quite sure I haven't structured this right. Is an enum even the right thing to be using for this? I'd appreciate any help to point me in the right direction.

Upvotes: 0

Views: 123

Answers (3)

Leo Dabus
Leo Dabus

Reputation: 236360

You can create an enumeration with the maximum score for each level as suggested by paulsm4 and declare your enumeration as CaseIterable. Then you can create an initializer to get the corresponding case for the score:

enum Level: Int, CaseIterable {
    case one = 50, two = 100, three = 200
}

extension Level {
    init(rawValue: Int) {
        self = Level.allCases.first { 0...$0.rawValue ~= rawValue } ?? .one
    }
}

extension Int {
    var level: Level { .init(rawValue: self) }
}

let score = 165
let level = score.level  // three


You can also create a custom enumeration of closed ranges. You just need to create a computed property to return each case range:

enum Level: CaseIterable {
    case one, two, three, four
}

extension Level: RawRepresentable {
    typealias RawValue = ClosedRange<Int>
    var rawValue: RawValue {
        let range: RawValue
        switch self {
        case .one:   range =   0 ... 50
        case .two:   range =  51 ... 100
        case .three: range = 101 ... 200
        case .four:  range = 201 ... .max
        }
        return range
    }
    init?(rawValue: RawValue) {
        guard let level = Level.allCases.first(where: { $0.rawValue == rawValue }) else { return nil }
        self = level
    }
    init(score: Int) {
        self = Level.allCases.first { $0.rawValue ~= score } ?? .one
    }
}


extension Int {
    var level: Level { .init(score: self) }
}

let score = 76
let level = score.level // two

Upvotes: 0

Sweeper
Sweeper

Reputation: 271575

Enums are very unsuitable for this. Try an array instead. For example, you can store:

let levelXps = [0, 50, 100, 200]

Or if you want to write out the level numbers as well:

let levelXps = [0:0, 1:50, 2:100, 3:200].values.sorted()

Then you can have a function that tells you what level it is, given a score:

func level(forScore score: Int) -> Int? {
    levelXps.lastIndex(where: { score > $0 })?.advanced(by: 1)
}

This finds the index of the last item in the array that is smaller than the given score, then adds 1 to it. If the score is negative, the function returns nil.

Upvotes: 0

paulsm4
paulsm4

Reputation: 121649

If you really wanted enums, you might do something like this:

enum xpLevels {
    case low = 50
    case medium = 100
    case high = 200
}

Then, in your code, check if the value is <= low, else <= medium, else it must be "high" ;)

Upvotes: 1

Related Questions