我要初始化一个数组,如下所示:
func initRoundsArray(playersArray: [String]) -> [String] {
let rounds: [String] = [
"ROUND 1: First player: \(String(playersArray.randomElement()!)), Second player: \(String(playersArray.randomElement()!))",
"ROUND 2: First player: \(String(playersArray.randomElement()!)), Second player: \(String(playersArray.randomElement()!))",
"ROUND 3: First player: \(String(playersArray.randomElement()!)), Second player: \(String(playersArray.randomElement()!))"
]
return rounds
}
在我的视图控制器中使用以下代码:
let playersArrayInput: [String] = ["Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8", "Player 9"]
var arrayOfRounds: [String]?
// Called like so in viewDidLoad:
arrayOfRounds = initRoundsArray(playersArray: playersArrayInput)
但是我正在努力弄清楚如何为每个回合选择2个随机且唯一的元素。例如,arrayOfRounds[0]
当前可能是"ROUND 1: First player: Player 6, Second player: Player 6"
。
由于initRoundsArray
仅被调用一次(arrayOfRounds
随后被突变),所以我认为不宜仅将数组改组并选择前2个元素,因为在这种情况下,每一轮都会与相同的2个玩家在一起。
我不确定如何实现这一目标(或者甚至有可能实现)。理想情况下,所需要做的就是在第一轮选择两名球员时,例如,检查他们是否彼此不同。
答案 0 :(得分:3)
基本上,您需要从数组中生成n个随机元素,您可以使用以下算法进行操作:
func pick<T>(_ n: Int, from array: [T]) -> [T] {
var copy = array // make a copy so we can make changes
var result = [T]()
for _ in 0..<n {
let randomElementIndex = Int.random(in: 0..<copy.count) // generate random index
let randomElement = copy[randomElementIndex]
copy.remove(at: randomElementIndex) // remove the generated element
result.append(randomElement) // add it to the result
}
return result
}
要生成3个回合的玩家,请用n=6
调用。
答案 1 :(得分:1)
您可以创建第二个数组,而不是将值复制到新数组中,而是将元素弹出到新数组中,因此确定要弹出的第二个项肯定是另一个。
例如。
func initRoundsArray(playersArray: [String]) -> [String] {
var playersArrayCoppy = playersArray
let round1Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
let round2Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
let round3Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
let rounds: [String] = [
"ROUND 1: First player: \(round1Item), Second player: \(round1Item)",
"ROUND 2: First player: \(round2Item), Second player: \(round2Item)",
"ROUND 3: First player: \(round3Item), Second player: \(round3Item)"
]
return rounds
}
当然,如果不确定数组计数是否> = 3,则需要添加一些检查,以确保数组中有项目
编辑 根据注释,您可能想要的是此功能
func initRoundsArray(roundsNumber: Int, playersArray: [String]) -> [String] {
var roundsArray:[String] = []
for i in 1...roundsNumber {
var playersArrayCoppy = playersArray
let player1Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
let player2Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
let round: String = "ROUND \(i): First player: \(player1Item), Second player: \(player2Item)"
roundsArray.append(round)
}
return roundsArray
}
您用initRoundsArray(roundsNumber: 3, playersArray: ["?","?",..."])
答案 2 :(得分:1)
我会选择以下内容:
func extractRandomElementsFromArray<Generic>(_ array: [Generic], numberOfElements: Int) -> [Generic]? {
guard array.count >= numberOfElements else { return nil }
var toDeplete = array
var toReturn = [Generic]()
while toReturn.count < numberOfElements {
toReturn.append(toDeplete.remove(at: Int.random(in: 0..<toDeplete.count)))
}
return toReturn
}
这应该对任何数量的元素在任何数组上有效。基本上,我们从一个数组中删除随机元素,然后将它们填充到另一个数组中,直到第二个数组中有足够的元素为止。
在您的情况下,可以用作:
let playersArrayInput: [String] = ["Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8", "Player 9"]
let pairArray = extractRandomElementsFromArray(playersArrayInput, numberOfElements: 2)!
let player1 = pairArray[0]
let player2 = pairArray[1]
答案 3 :(得分:0)
我最终使用了以下代码(<ACTION>
只是一个占位符):
func initRoundsArray(playersArray: [String]) -> [String] {
let round1Players = twoRandomPlayers(playersArray: playersArray)
let round2Players = twoRandomPlayers(playersArray: playersArray)
let rounds: [String] = [
"ROUND 1: \(round1players[0]), do <ACTION> to \(round1players[1])",
"ROUND 2: \(round2players[0]), do <ACTION> to \(round2players[1])",
"ROUND 3: \(String(playersArray.randomElement()!)), do <ACTION>"
]
return rounds
}
func twoRandomPlayers(playersArray: [String]) -> [String] {
let shuffledPlayersArray = playersArray.shuffled()
return Array(shuffledPlayersArray.prefix(2))
}
我每次都会调用一个单独的函数,该函数返回一个数组,其中包含2个playersArray
中随机挑选(且唯一)的玩家,并将其用于需要2个玩家的回合中。
我知道这可能不是最好的方法,但是在我的最终实现中,绝大多数回合可能只涉及一名玩家,因此.randomElement()
是合适的。
对于原始问题中的措词令人困惑,我深表歉意,但我希望这可以澄清问题,并非常感谢大家的建议/回答:)
答案 4 :(得分:0)
首先,让我们假设playersArrayInput
没有任何重复项。
let playersArrayInput: [String] = ["Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8", "Player 9"]
有效的实现方式是仅对索引进行混洗:
func initRoundsArray(playersArray: [String]) -> [String] {
var shuffledIndices = playersArray.indices.shuffled()
let count = playersArray.count - 1
var rounds = [String]()
var i = 0
while i <= count {
let round = String(rounds.count + 1)
if i <= count - 1 {
switch Bool.random() {
case true:
rounds.append("ROUND " +
round +
": " +
playersArray[shuffledIndices[i]] +
", do <ACTION>")
i += 1
default:
rounds.append("ROUND " +
round +
": " +
playersArray[shuffledIndices[i]] +
", do <ACTION> to " +
playersArray[shuffledIndices[i + 1]])
i += 2
}
} else {
rounds.append("ROUND " +
round +
": " +
playersArray[shuffledIndices[count]] +
", do <ACTION>")
break
}
}
return rounds
}
我们可以这样打印呼叫结果:
initRoundsArray(playersArray: playersArrayInput).forEach { print($0) }
例如:
ROUND 1: Player 7, do <ACTION> to Player 1
ROUND 2: Player 8, do <ACTION>
ROUND 3: Player 5, do <ACTION>
ROUND 4: Player 9, do <ACTION> to Player 2
ROUND 5: Player 3, do <ACTION> to Player 6
ROUND 6: Player 4, do <ACTION>