В этом уроке я создам 2D-матрицу из массива случайных значений. Кроме того, значения будут генерироваться для каждой плитки матрицы из предопределенного массива объектов.

Начнем с определения модели данных, которая будет плиткой 2D-матрицы. И переменная, определяющая строки и столбцы 2D-матрицы.

const tileData = [
    {
        chance: .1,
        label: 'crab',
        img: './png/023-crab.png'
    },
    {
        chance: .3,
        label: 'croc',
        img: './png/039-crocodile.png'
    },
    {
        chance: .4,
        label: 'chic',
        img: './png/028-chicken.png'
    },
    {
        chance: .2,
        label: 'lion',
        img: './png/048-lion.png'
    },
];
const MATRIX_SIZE = [4, 4];

Далее нам нужна функция, которая будет случайным образом выбирать одно из значений массива. Не забудьте включить вероятность (шанс) броска этого элемента массива.

chooseWeighted = (items, chances) => {
var sum = chances.reduce((acc, el) => acc + el, 0);
var acc = 0;
chances = chances.map(el => (acc = el + acc));
var rand = Math.random() * sum;
return items[chances.filter(el => el <= rand).length];
};

Кроме того, нам нужна функция, которая генерирует матрицу со случайно сгенерированными значениями.

const allChances = tileData.map((a => a.chance));
generateMatrix = (allChances) => {
    var result = [];
    for (var i = 0; i < MATRIX_SIZE[0]; i++) {
        result[i] = [];
        for (var j = 0; j < MATRIX_SIZE[1]; j++) {
            result[i][j] = chooseWeighted(tileData, allChances);        }
    }
};

Вот и все — теперь мы генерируем матрицу со случайными значениями. Логический бит готов. Но всегда приятно иметь еще и пользовательский интерфейс — для этого мне нужна только еще одна функция, addGameTile:

addGameTile = (tileImg, tileLabel, tileSize) => {
    let gameTile = document.createElement('div');
    gameTile.style.backgroundImage = 'url(' + tileImg + ')';
    gameEl.appendChild(gameTile);
    gameTile.style.width = tileSize;
};

Теперь просто подключите эту функцию к generateMatrix:

//...
result[i][j] = chooseWeighted(tileData, allChances);
addGameTile(result[i][j].img, result[i][j].label, 1 / MATRIX_SIZE[0] * 100 + '%')
//...

И вот как я генерирую случайную 2D-матрицу из взвешенного массива;

Вы можете найти стильный код на моем github: https://github.com/mksolemn/random-2d-matrix-from-weighted-array

Первоначально опубликовано на https://freelancedeveloper.io 3 января 2021 г.