简体   繁体   English

iOS Swift:范围数组

[英]iOS Swift: Array of Range

I have a Player class that stores a rating property of type Int : 我有一个Player类,用于存储Int类型的rating属性:

class Player {
    typealias Rating: Int
    var rating: Rating = 0
}

I then have various Range instances that specify the level that a given player is at: 然后,我有各种Range实例,用于指定给定player所处的level

private let level1Range = 0 ..< 100
private let level2Range = 100 ..< 500

I can then switch on the player rating property to obtain the level that the player is at: 然后,我可以switch player rating属性以获得player所在的级别:

switch rating {
case level1Range:
    print("On Level 1")
case level2Range:
    print("On Level 2")
default:
    break
} 

I want to be able to say what the next level is and how far away the player is from that next level. 我希望能够说出下一关是什么,以及player离下一关有多远。

I'm not sure of the best way to go out this problem. 我不确定解决此问题的最佳方法。 I started by making an array: 我首先创建一个数组:

private var ratingRanges: [Range] {
    return [level1Range, level2Range]
}

But I get the error: 但是我得到了错误:

Reference to generic type 'Range' requires arguments in <...> Insert '<<#Bound: Comparable#>>' 引用通用类型'Range'时需要在<...>中插入参数'<<#Bound:Comparable#>>'

If this worked, I guess I could then find the first non-zero value: 如果这行得通,我想我可以找到第一个非零值:

ratingRanges.first(where: { $0.min() - self.rating > 0 })

in order to locate the next range. 为了找到下一个范围。

Or is there a more efficient method to achieve this? 还是有一种更有效的方法来实现这一目标?

Thanks for any help 谢谢你的帮助

You need to provide the generic placeholder type of the Range : 您需要提供Range的通用占位符类型:

private var ratingRanges: [Range<Rating>] {
    return [level1Range, level2Range]
}

Or simpler, with automatic type inference, as a (lazy) stored property: 或更简单的是,具有自动类型推断的(惰性)存储属性:

private lazy var ratingRanges = [level1Range, level2Range]

Determining the next range can then be done as 然后可以确定下一个范围

func nextRange() -> Range<Rating>? {
    return ratingRanges.first(where: { $0.lowerBound > rating})
}

My solution is to create Level enum: 我的解决方案是创建Level枚举:

    enum Level: Int {
    case level1 = 1
    case level2

    init?(rating: Int) {
        switch rating {
        case Level.level1.range:
            self = .level1
        case Level.level2.range:
            self = .level2
        default:
            return nil
        }
    }

    var range: CountableRange<Int> {
        switch self {
        case .level1:
            return level1Range
        case .level2:
            return level2Range
        }
    }
}

And then all you need to do is to add following methods to your Player class: 然后,您需要做的就是向Player类添加以下方法:

func nextLevel() -> Level? {
    guard let currentLevel = Level(rating: rating) else {
        return nil
    }
    guard let nextLevel = Level(rawValue: currentLevel.rawValue + 1) else {
        return nil
    }
    return nextLevel
}

func distanceTo(level: Level) -> Int {
    let levelLowerBound = level.range.lowerBound
    return levelLowerBound - rating
}

May you should to keep the maximum value of range only. 可能您应该只保留范围的最大值。 For example, instead of 例如,代替

private let level1Range = 0 ..< 100
private let level2Range = 100 ..< 500

you can use 您可以使用

private let level1MaxRating = 100
private let level2MaxRating = 500

and compare with 并与

switch rating {
case 0...level1MaxRating:
    print("level 1")
case (level1MaxRating+1)...level2MaxRating:
    print("level 2")
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM