Avatar ·

Как сгенерировать случайное число в Swift? Подробное руководство для новичков

Привет всем! Я только начал изучать Swift и пишу простое приложение для iOS — игру "Угадай число". Мне нужно, чтобы программа загадывала случайное число от 1 до 100, а пользователь его угадывал. Но я никак не могу понять, как правильно сгенерировать случайное число. Я пробовал использовать функцию `random()`, но Xcode выдает ошибку: "Use of unresolved identifier 'random'". Вот мой код: ```swift let secretNumber = random() % 100 + 1 print("Загадано число: \(secretNumber)") ``` Я читал, что в старых версиях Swift использовали `arc4random_uniform()`, но в Swift 5.5+ это тоже не работает? Подскажите, как правильно генерировать случайные числа в современном Swift (я использую Xcode 14 и Swift 5.7). Нужны примеры для: 1. Целых чисел в заданном диапазоне 2. Чисел с плавающей точкой (Double, Float) 3. Булевых значений (true/false) Заранее спасибо за помощь! Бьюсь над этим уже второй час. <<>>

Правильный способ генерации случайных чисел в современном Swift

Начиная с Swift 4.2 (2018 год), в язык была добавлена встроенная поддержка случайных чисел через протокол RandomNumberGenerator и методы расширения для стандартных типов. Это намного удобнее и безопаснее, чем старые подходы с arc4random_uniform() или random().

1. Случайное целое число (Int)

Для генерации целого числа в заданном диапазоне используйте метод random(in:):

// Случайное число от 1 до 100 включительно
let secretNumber = Int.random(in: 1...100)
print("Загадано число: \(secretNumber)")

// Случайное число от 0 до 99 (полуинтервал)
let randomIndex = Int.random(in: 0..<100)
print("Индекс: \(randomIndex)")

// Случайное число от -50 до 50
let temperature = Int.random(in: -50...50)

2. Случайное число с плавающей точкой (Double, Float, CGFloat)

Для типов Double, Float и CGFloat работает точно такой же синтаксис:

// Double от 0.0 до 1.0
let randomDouble = Double.random(in: 0...1)
print("Случайное Double: \(randomDouble)")

// Float от -10.0 до 10.0
let randomFloat = Float.random(in: -10.0...10.0)

// CGFloat для UIKit/Core Graphics
let randomCGFloat = CGFloat.random(in: 0...100)

3. Случайное булево значение (Bool)

Для Bool также есть встроенный метод:

let isHeads = Bool.random()
print("Орёл? \(isHeads)") // true или false с вероятностью 50%

// Можно использовать в условных операторах
if Bool.random() {
    print("Повезло!")
} else {
    print("Не повезло :(")
}

4. Случайный элемент из коллекции

Часто нужно выбрать случайный элемент из массива — для этого есть метод randomElement():

let colors = ["red", "green", "blue", "yellow"]
if let randomColor = colors.randomElement() {
    print("Случайный цвет: \(randomColor)")
}

// Для массивов с опциональными значениями
let numbers = [1, 2, 3, 4, 5]
let randomNumber = numbers.randomElement() ?? 0

5. Перемешивание массива (shuffle)

Методы shuffle() (на месте) и shuffled() (возвращает новый массив) также используют тот же генератор:

var deck = [1, 2, 3, 4, 5, 6]
deck.shuffle() // перемешивает исходный массив
print(deck) // например: [3, 6, 1, 5, 2, 4]

let shuffledDeck = deck.shuffled() // возвращает новый массив

6. Свой генератор случайных чисел (продвинутый уровень)

Если нужно воспроизводимое поведение или криптографическая стойкость, можно использовать свой генератор:

// Воспроизводимая последовательность (для тестов)
var generator = SeededRandomGenerator(seed: 42)
let number1 = Int.random(in: 1...100, using: &generator)
let number2 = Int.random(in: 1...100, using: &generator)

// Криптографически стойкий генератор
import CryptoKit
let secureNumber = Int.random(in: 1...100, using: &SystemRandomNumberGenerator())

Почему старые методы не работают?

  • random() — это функция из C, недоступна в Swift без импорта Foundation и Darwin
  • arc4random_uniform() — работает, но неудобна: arc4random_uniform(100) + 1 (диапазон от 0 до 99)
  • Эти методы не поддерживают типы Double и Bool напрямую

Исправленный код для вашей игры

let secretNumber = Int.random(in: 1...100)
print("Я загадал число от 1 до 100. Попробуй угадать!")

// Далее можно добавить цикл для ввода пользователя
var guess: Int?
repeat {
    print("Введи число:")
    if let input = readLine(), let number = Int(input) {
        guess = number
        if number < secretNumber {
            print("Слишком мало!")
        } else if number > secretNumber {
            print("Слишком много!")
        }
    }
} while guess != secretNumber

print("Поздравляю! Ты угадал!")

Теперь ваша игра будет работать на любом современном Swift (4.2+). Удачи в разработке!

<<>>

Альтернативный подход: использование GameplayKit для случайных чисел

Если вы пишете игру или приложение, где нужны более сложные распределения случайных чисел (например, Гауссово распределение, равномерное распределение с настраиваемой вероятностью), стоит обратить внимание на фреймворк GameplayKit от Apple. Он предоставляет мощные инструменты для генерации случайных данных.

Пример использования GKRandomSource:

import GameplayKit

// Стандартный генератор
let randomSource = GKRandomSource()
let randomInt = randomSource.nextInt(upperBound: 100) // 0..<100
let randomIntInRange = randomSource.nextInt(in: 1...100)

// Воспроизводимый генератор (для тестирования)
let seededSource = GKLinearCongruentialRandomSource(seed: 42)
let sameValue1 = seededSource.nextInt(upperBound: 100) // всегда одинаково
let sameValue2 = seededSource.nextInt(upperBound: 100)

// Генератор с Гауссовым распределением (нормальное распределение)
let gaussianSource = GKGaussianDistribution(randomSource: GKRandomSource(), 
                                             mean: 50, 
                                             deviation: 10)
let gaussianValue = gaussianSource.nextInt() // значения около 50

Когда это полезно?

  • Для создания процедурно генерируемых уровней в играх
  • Для симуляции случайных событий с определённой вероятностью
  • Для тестирования, когда нужно воспроизводимое поведение

Однако для большинства повседневных задач (угадай число, случайный выбор цвета, генерация пароля) встроенных методов Int.random(in:) и Bool.random() более чем достаточно. GameplayKit — это решение для продвинутых сценариев.