Как сгенерировать случайные "визуально приятные" 2D-матрицы из набора блоков? - PullRequest
0 голосов
/ 14 июля 2020

Мне интересно, как сгенерировать случайные дизайны аватаров пользователей, вроде как аватары пользователей по умолчанию в StackOverflow, за исключением того, что я бы имел дело только с квадратами. Диапазон может составлять от 21 до 137 возможных квадратов в дизайне, и дизайн не может быть длиннее 13 и не тоньше 3 квадратов, количество квадратов должно быть нечетным в каждой строке, и не может быть пробелов в середина рядов. То есть каждая строка - это solid строка из 3-13 блоков.

Как лучше всего случайным образом сгенерировать группу дизайнов? Есть ли способ как-то сделать их "визуально приятными" без жесткого кодирования каждого из них? Как бы вы go это сделали, чтобы не приходилось вручную помещать каждый блок в сетке в нужное положение?

Например, это одна идея:

        池池池
      池池池池池
        池池池
  池池池池池池池池池池
    池池池池池池池池
        池池池

Это еще одна идея:

    池池池池池
    池池池池池
    池池池池池
    池池池池池

Допустим, существует 100 возможных наборов блоков длиной от 21 до 137. Так что я думаю, вы могли бы сгенерировать все дизайны заранее (может быть, несколько тысяч), а затем просто выбрать из списка по мере go, чтобы больше никогда не повторять.

Может быть, возможно, это волновые модели. может быть разработан даже после ...

function generateSquare(size) {
  
}

function generateTree(size) {
  
}

function generateBow() {
  return [
    [1, 1, 1],
    [1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1],
    [1, 1, 1],
  ]
}

function generateHourglass(size) {
  
}

function generate(size) {
  
}

В принципе, как я могу сгенерировать их, кроме как вручную?

function generateBowA() {
  return [
    [1, 1, 1],
    [1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1],
    [1, 1, 1],
  ]
}

function generateBowA() {
  return [
    [1, 1, 1],
    [1, 1, 1],
    [1, 1, 1],
    [1, 1, 1, 1, 1],
    [1, 1, 1],
    [1, 1, 1],
    [1, 1, 1],
  ]
}

function generateBowB() {
  return [
    [1, 1, 1],
    [1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1],
    [1, 1, 1],
  ]
}

...

Или как-то вроде:

var set = [
  [3, 5, 7, 5, 3],
  [3, 3, 3, 5, 3, 3, 3],
  [3, 5, 7, 5, 3, 5, 7, 5, 3],
]

Является есть способ лучше, чем этот?

var sizes = [61, 88, 67, 42, 45, 25, 49, 50, 39, 72, 49, 49, 81, 94, 95, 67, 44 , 26, 46, 134, 69, 78, 86, 48, 85, 47, 88, 86, 59, 77, 120, 69, 38, 62, 42, 57, 48, 131, 137, 21, 92, 75 , 40, 39, 40, 42, 36, 43, 66, 80, 72, 72, 52, 91, 80, 65, 89, 69, 64, 48, 83, 81, 78, 123, 67, 103, 75 , 43, 54, 47, 28, 44, 64, 58, 53, 57, 80, 65, 40, 76, 57]

var nums = [3, 5, 7]

var designs = []
var i = sizes.length
while (i--) {
  designs.push(make())
}

console.log(designs)

function make() {
  var size = sizes.shift()
  return size % 2 === 0
    ? makeEven(size)
    : makeOdd(size)
}

function makeEven(total) {
  var start = []
  var end = []
  var half = total / 2
  while (half) {
    var num = nums[rand(0, 2)]
    var res = half - num
    if (res < 0) return makeEven(total)
    half = half - num
    start.push(num)
    end.unshift(num)
  }
  var result = start.concat(end)
  return result
}

function makeOdd(total) {
  var middle = nums[rand(0, 2)]
  var start = []
  var end = []
  var half = (total - middle) / 2
  while (half) {
    var num = nums[rand(0, 2)]
    var res = half - num
    if (res < 0) return makeOdd(total)
    half = half - num
    start.push(num)
    end.unshift(num)
  }
  var result = start.concat([ middle ]).concat(end)
  return result
}

function rand(min, max) { // min and max included
  return Math.floor(Math.random() * (max - min + 1) + min);
}
...