Как избежать повторения с помощью arc4random в Swift

У меня есть следующий код для создания случайно заполненной сетки в Swift:

import Foundation

var tile = [String](count: 900, repeatedValue: ".")

// Randomly populate the grid with hashes
for i in 0...400 {
    tile[Int(arc4random_uniform(899))] = "#"
}

// Print the grid to console
for y in 0...(29) {
    for x in 0...(29) {
        print("\(tile[y * 10 + x])")
    }
    println("")
}

Запуск этого кода создает сетку, которая выглядит следующим образом:

..##..#.#...#..#..#.#.####.#..
..#..#..#.#.####.#....###.#.#.
#.####.#....###.#.#.#####.....
..###.#.#.#####.....#...#....#
#####.....#...#....###.##.###.
#...#....###.##.###..#.....#..
##.##.###..#.....#...##..#.##.
.#.....#...##..#.##...#.####..
.##..#.##...#.####..###..#.#.#
..#.####..###..#.#.#.#..#.....
###..#.#.#.#..#.........#...##
.#..#.........#...##.##.......
....#...##.##............#...#
.##............#...####....##.
.....#...####....##..#.#.....#
###....##..#.#.....#........#.
.#.#.....#........#...#.#..#..
........#...#.#..#......#....#
..#.#..#......#....#.##.#...##
....#....#.##.#...###...#..#..
.##.#...###...#..#..#.#..#...#
#...#..#..#.#..#...#####...##.
#.#..#...#####...##..#.......#
####...##..#.......#.#.#.....#
.#.......#.#.#.....##.........
.#.#.....##..........##.#..#.#
#..........##.#..#.##.#.#.....
.##.#..#.##.#.#.....##...#....
#.#.#.....##...#......#.##....
##...#......#.##.....#.######.

Вы можете ясно видеть, что картина повторяется. Есть ли способ "выкинуть" функцию, чтобы генерация была более убедительной?


person Alex Laing    schedule 15.07.2015    source источник
comment
Это случайный эксперимент?   -  person Kutyel    schedule 15.07.2015
comment
В этом проблема случайности, вы не можете знать, закономерность это или нет, люди обычно плохо распознают случайность.   -  person Kametrixom    schedule 15.07.2015


Ответы (2)


Ваша функция печати неверна: tile[y*10 + x] должно быть tile[y*30 + x].


Что касается генерации сеток: что именно вы хотите?

Если ответ «случайный выбор из равномерного распределения по пространству всех возможных сеток 30x30, где каждая ячейка равна # или .», то вам следует просто выбрать каждую ячейку с равной вероятностью # и .:

for i in 0..<900 {
    // arc4random_uniform(2) is either 0 or 1, with equal probability
    tile.append(arc4random_uniform(2) == 0 ? "." : "#")
}

Если ответ «случайный выбор из равномерного распределения по сеткам 30x30, в котором ровно 400 ячеек имеют значение #», то вам следует заранее выбрать 400 уникальных индексов, прежде чем преобразовывать их в #.

В нынешнем виде ваш код может создавать сетки только с одним # (хотя это очень маловероятно). И он никогда не создаст сетки с более чем 400 #s.

person jtbandes    schedule 15.07.2015
comment
Я написал программу так, как собирался; это был неправильный tile[y * 10 + x], который вы идентифицировали, который вызывал повторение в шаблоне. - person Alex Laing; 15.07.2015

  1. Вы только конвертируете 400 из 900 в #
  2. У вас будет много дубликатов (перезапись # на #), поэтому я ожидаю много '.' осталось.

Образец, который вы показываете, довольно хорош, я думаю.

Сложите все свои товары в сумку/массив, случайным образом отсортируйте их и вытащите по одному.

person Bart    schedule 15.07.2015
comment
Предполагалось ограничение в 400, но я мог заставить программу выполнять итерацию только более . символы, а не все плитки. - person Alex Laing; 15.07.2015