Розробка гри Keno на блокчейні

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка гри Keno на блокчейні
Середній
~3-5 днів
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1288
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    902
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1122
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    859

Розробка блокчейн-гри Keno

Keno — лотерейна гра: гравець вибирає числа з діапазону (зазвичай 1–80), випадково витягуються 20 чисел, виграш залежить від збігів. Проста механіка, але реалізація на блокчейні вимагає вирішення кількох нетривіальних задач: верифіковану випадковість для витягування 20 чисел, gas-ефективну перевірку збігів, правильну таблицю виплат.

На відміну від Crash, Keno — гра з фіксованим результатом до кешау: числа витягнуті, результат одразу відомий. Це спрощує деякі аспекти, але вимагає особливої уваги до якості RNG.

RNG: вибір 20 унікальних чисел з 80

Основна технічна задача: з одного VRF random seed отримати 20 унікальних чисел у діапазоні 1–80. Наївний підхід (rand % 80 повторити 20 разів) створює колізії — одне число може випасти двічі.

Fisher-Yates Перетасування для On-Chain Keno

function drawNumbers(uint256 seed) public pure returns (uint8[20] memory drawn) {
    // Ініціалізуємо масив 1..80
    uint8[80] memory pool;
    for (uint8 i = 0; i < 80; i++) {
        pool[i] = i + 1;
    }
    
    // Fisher-Yates: тасуємо перші 20 позицій
    for (uint8 i = 0; i < 20; i++) {
        // Отримуємо pseudo-random індекс з seed
        uint256 j = uint256(keccak256(abi.encodePacked(seed, i))) % (80 - i);
        
        // Swap pool[i] та pool[i + j]
        uint8 temp = pool[i];
        pool[i] = pool[i + j];
        pool[i + j] = temp;
        
        drawn[i] = pool[i];
    }
}

Fisher-Yates гарантує унікальні числа без reject-sampling. Для on-chain виконання: 20 ітерацій × keccak256 ≈ 80,000–100,000 газу. На Arbitrum ~$0.01. Прийнятно.

Альтернатива — bitmap підхід:

function drawNumbersBitmap(uint256 seed) public pure returns (uint8[20] memory drawn) {
    uint256 bitmap = 0; // кожен біт = число 1-80
    uint8 count = 0;
    uint256 nonce = 0;
    
    while (count < 20) {
        uint8 num = uint8(uint256(keccak256(abi.encodePacked(seed, nonce))) % 80) + 1;
        nonce++;
        
        if (bitmap & (1 << (num - 1)) == 0) {
            bitmap |= (1 << (num - 1));
            drawn[count] = num;
            count++;
        }
    }
}

Bitmap підхід простіший, але reject-sampling може потребувати більше keccak256 викликів у гіршому випадку (колізії частіші при виборі останніх чисел). Fisher-Yates preferable для передбачуваного газу.

Перевірка совпадений: Gas-Ефективна реалізація

Гравець вибрав M чисел (1–10), потрібно підрахувати збіги з 20 витягнутих чисел.

Наївний підхід: вкладені цикли O(M×20) — прийнятно для малого M.

Bitmap підхід для ефективності:

function countMatches(
    uint8[] memory playerPicks,  // числа гравця
    uint8[20] memory drawnNumbers
) public pure returns (uint8 matches) {
    // Будуємо bitmap витягнутих чисел
    uint256 drawnBitmap = 0;
    for (uint8 i = 0; i < 20; i++) {
        drawnBitmap |= (1 << (drawnNumbers[i] - 1));
    }
    
    // Перевіряємо picks гравця проти bitmap
    for (uint8 i = 0; i < playerPicks.length; i++) {
        if (drawnBitmap & (1 << (playerPicks[i] - 1)) != 0) {
            matches++;
        }
    }
}

Бітові операції швидше ніж вкладені цикли. Для типових 1–10 picks: ≈ 3,000–5,000 додатково газу.

Таблиця виплат

Keno виплати — найважливіша економічна частина. Потрібно балансувати house edge (зазвичай 20–35% у Keno) при різних кількостях picks.

// Виплати як множник ставки (basis points: 100 = 1x)
// [picks][matches] → множник
uint256[11][11] public payoutTable;

constructor() {
    // 1 pick
    payoutTable[1][0] = 0;
    payoutTable[1][1] = 360; // 3.6x

    // 3 picks
    payoutTable[3][0] = 0;
    payoutTable[3][1] = 0;
    payoutTable[3][2] = 200;  // 2x
    payoutTable[3][3] = 4600; // 46x

    // 5 picks
    payoutTable[5][0] = 0;
    payoutTable[5][1] = 0;
    payoutTable[5][2] = 0;
    payoutTable[5][3] = 300;   // 3x
    payoutTable[5][4] = 1200;  // 12x
    payoutTable[5][5] = 50000; // 500x

    // 10 picks  
    payoutTable[10][0] = 0;
    payoutTable[10][5] = 200;    // 2x
    payoutTable[10][6] = 1800;   // 18x
    payoutTable[10][7] = 17000;  // 170x
    payoutTable[10][8] = 100000; // 1000x
    payoutTable[10][9] = 250000; // 2500x
    payoutTable[10][10] = 1000000; // 10000x (jackpot)
}

House edge верифікується математично: для кожного варіанту picks розрахуйте Expected Value:

EV(5 picks) = Σ P(k matches) × payout(5, k) для k = 0..5
P(k matches) = C(20,k) × C(60, 5-k) / C(80, 5)

EV повинен бути ≈ 0.70–0.80 (70–80% RTP, 20–30% house edge)

Стек та терміни

Chain: Polygon PoS або Arbitrum для низької гази. Chainlink VRF V2 Plus. Solidity + Foundry. Frontend: React + wagmi. WebSocket для реалтайм draw анімації.

Фаза Термін
Контракти (single player, VRF, payout table) 3–4 тижні
Multi-player shared draw 2 тижні
Frontend + draw анімація 2–3 тижні
Bankroll + admin panel 1–2 тижні
Audit + testnet 3–4 тижні

MVP (single player Keno): 5–7 тижнів. Повна платформа з multi-player draw: 9–12 тижнів.