Решил отойти от темы ботов для ВК и сделать небольшой лохотрон (рулетку типа). Принцип работы простой и понятый - после запуска пользователю выпадает один из призов, однако у каждого приза будет свой шанс выпадения. Чем выше шанс - тем вероятнее и чаще он будет попадаться.
Шаг 1: Подготовка и осознание
С чего стоит начать - так это с обдумывания механизма, который будет регулировать вероятности. И, безусловно, вариантов реализации таких штуковин может быть множество, но поскольку в этот раз я не буду делать никаких дополнительных фильтров, шансов, алгоритмов, подборов и т.д. и т.п., то процентную вероятность будем высчитывать для каждого приза в зависимости от его ценности по следующей формуле:
Коэффициент приза - это обратная дробь стоимости приза. При умножении стоимости на коэффициент всегда будет получаться единица.
В качестве призов, а также их стоимости, я буду использовать просто деньги. Для примера сравним шансы выпадения 10.000 рублей, 5.000 рублей и 2.000 рублей:
Если все эти проценты сложить, то в сумме получится 100% (12,5 + 25 + 62,5).
Сейчас все расчёты я сделал вручную для демонстрации принципа работы скрипта, который в дальнейшем будет всё это делать за нас в автоматическом режиме.
Шаг 2: Написание скрипта
Всего в моём тестовом проекте будет два файла: index.php (главная) и func.php (скрипт):
Пришло время писать код. Открываем файл func.php и создаём массив с призами. Я сделаю 7 элементов с разными суммами:
<?php
const PRIZES = array (
array (
'name' => '1.000.000 рублей',
'price' => 1000000
),
array (
'name' => '750.000 рублей',
'price' => 750000
),
array (
'name' => '600.000 рублей',
'price' => 600000
),
array (
'name' => '400.000 рублей',
'price' => 400000
),
array (
'name' => '250.000 рублей',
'price' => 250000
),
array (
'name' => '150.000 рублей',
'price' => 150000
),
array (
'name' => '100.000 рублей',
'price' => 100000
),
);
Далее нам понадобятся две функции. Первая будет считать сумму коэффициентов всех призов, а вторая запустит рулетку и вернёт позицию выигранного приза в массиве.
Начинаем писать первую:
function totalChance( array $prizes )
{
$result = 0;
foreach ( $prizes as $key => $params )
{
$result += ( 1 / $params['price'] );
}
return $result;
}
На вход функция получает массив всех призов (который мы запихали в константу PRIZES), далее перебирает все призы, суммирует их коэффициенты и возвращает полученное значение.
Переходим к функции №2. Создаём рандомное число от 1 до 100 и записываем его в переменную:
function startLottery( array $prizes )
{
$rand = mt_rand( 1, 100 );
// Тут продолжим писать код
}
Далее в функцию мы вставим цикл, который будет перебирать всё тот же массив с призами. На каждой итерации будет подсчитываться шанс текущего приза и предыдущего (на первой итерации для "предыдущего шанса" ставим 0). И если рандомное число попадает в промежуток этих двух высчитанных шансов (ранд > пред.шанс И ранд <= текущ.шанс) - значит прерываем цикл и возвращаем приз пользователю.
Конечный облик функции:
function startLottery( array $prizes )
{
$rand = mt_rand( 1, 100 ); // Рандомное число
$current_chance = $prev_chance = 0; // Вероятность выпадения текущего и предыдущего призов. Пока что приравниваем к нулю.
foreach ( PRIZES as $key => $params )
{
$current_coefficient = 1 / $prizes[$key]['price']; // Коэффициент текущего приза
$current_chance += $current_coefficient / totalChance( $prizes ) * 100; // Вероятность выпадения текущего приза в процентах
if ( $key != 0 ) // Проверяем, на какой итерации находится цикл по индексу массива (0 - первый индекс)
{
$prev_coefficient = 1 / $prizes[$key - 1]['price']; // Коэффициент предыдущего приза
$prev_chance += $prev_coefficient / totalChance( $prizes ) * 100; // Вероятность выпадения предыдущего приза в процентах
}
if ( $rand > $prev_chance and $rand <= $current_chance ) // Если $rand находится в промежутке двух высчитанных шансов, то возращаем индекс текущего приза в массиве
return $key;
}
return -1;
}
Шаг 3: Тесты
Для тестов рулетки добавил цикл в код, который 1000 раз вызовет вышенаписанную функцию, а также посчитает количество выпадений для каждого приза:
$a = 0;
$b = 0;
$c = 0;
$d = 0;
$e = 0;
$f = 0;
$g = 0;
for ( $i = 0; $i < 1000; $i++ )
{
$x = startLottery( PRIZES );
echo PRIZES[$x]['name'] . '<br>';
switch ( PRIZES[$x]['price'] )
{
case 1000000: { $a++; break; }
case 750000: { $b++; break; }
case 600000: { $c++; break; }
case 400000: { $d++; break; }
case 250000: { $e++; break; }
case 150000: { $f++; break; }
case 100000: { $g++; break; }
}
}
echo '<br>';
echo $a . ' (' . 1 / PRIZES[0]['price'] / totalChance( PRIZES ) * 100 . '%)' . '<br>';
echo $b . ' (' . 1 / PRIZES[1]['price'] / totalChance( PRIZES ) * 100 . '%)' . '<br>';
echo $c . ' (' . 1 / PRIZES[2]['price'] / totalChance( PRIZES ) * 100 . '%)' . '<br>';
echo $d . ' (' . 1 / PRIZES[3]['price'] / totalChance( PRIZES ) * 100 . '%)' . '<br>';
echo $e . ' (' . 1 / PRIZES[4]['price'] / totalChance( PRIZES ) * 100 . '%)' . '<br>';
echo $f . ' (' . 1 / PRIZES[5]['price'] / totalChance( PRIZES ) * 100 . '%)' . '<br>';
echo $g . ' (' . 1 / PRIZES[6]['price'] / totalChance( PRIZES ) * 100 . '%)' . '<br>';
В итоге получаем вот такую картину:
Как можно заметить - количество выпадений очень близко к процентной вероятности (та, что в скобках), а значит больше ничего дорабатывать не придётся.
Код для тестов теперь можно убирать, дабы он не мешал.
Шаг 4: Оформление
Переходим в файл index.php, в котором делаем простую форму с кнопкой. После каждого нажатия будет отправляться ajax-запрос и инициироваться новый запуск рулетки:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>Рулетка</title>
<style>
.game{width:500px;height:150px;margin:0 auto;padding:15px;border-radius:10px;background-color:aliceblue }
.prize{padding:15px 30px;border-radius:10px;background-color:#e3e3e3;text-align:center }
#text{font-size:22px;font-weight:700 } form{padding:10px;text-align:center }
button{cursor:pointer;width:200px;height:60px;border:none;border-radius:30px;font-size:16px;font-weight:700;background-color:teal;color:white }
</style>
</head>
<body>
<div class="game">
<div class="prize"></div>
<form method="POST" id="form" action="jаvascript:void(null);" onsubmit="call()">
<input type="hidden" name="type" value="lot">
<button>Сюда надо тыкать</button>
</form>
</div>
</body>
</html>
<script>
function call() {
var msg = $('#form').serialize();
$.ajax({
type: 'POST',
url: '/func.php',
dаta: msg,
success: function(data) {
var obj = jQuery.parseJSON(data);
if (obj.success == 'success') {
$('.prize').html('<span id="text">Твой выигрыш: ' + obj.prize + '</span>');
} else {
$('.prize').html('<span id="text">Ошибка</span>');
}
}
});
}
</script>
В func.php добавляем обработку формы:
if ( $_POST['type'] == 'lot' )
{
$i = startLottery( PRIZES ); // Запуск рулетки, получение индекса приза в массиве
$result = array (
'success' => 'success',
'prize' => PRIZES[$i]['name'] // Название массива, которое будет выведено пользователю
);
echo json_encode( $result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); // Конвертируем массив $result в JSON и распечатываем
}
Теперь можно потыкать, поиграться, посмотреть как все замечательно работает :)
На этом все работы можно считать завершёнными. Архив с исходниками, как всегда, прикрепляю:
Перед публикацией, советую ознакомится с правилами!
Нашли ошибку?
Вы можете сообщить об этом администрации.
Выделив текст нажмите CTRL+Enter