|
import streamlit as st |
|
import streamlit.components.v1 as components |
|
|
|
|
|
st.set_page_config( |
|
page_title="Slot Machine Game", |
|
page_icon="π°", |
|
layout="wide", |
|
initial_sidebar_state="collapsed" |
|
) |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
.main > div { |
|
padding-top: 1rem; |
|
} |
|
#root > div:nth-child(1) > div > div > div > div > section > div { |
|
padding-top: 0rem; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
st.title("π° Slot Machine") |
|
|
|
|
|
slot_machine_html = """ |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>40-Card Slot Machine</title> |
|
<style> |
|
body { margin: 0; background: #1a1a1a; color: #fff; font-family: Arial, sans-serif; } |
|
.game-container { |
|
width: 1024px; |
|
height: 768px; |
|
margin: 0 auto; |
|
position: relative; |
|
background: #2a2a2a; |
|
padding: 20px; |
|
border-radius: 10px; |
|
border: 2px solid gold; |
|
box-sizing: border-box; |
|
} |
|
.grid-container { |
|
display: grid; |
|
grid-template-columns: repeat(5, 1fr); |
|
gap: 5px; |
|
margin: 20px 0; |
|
height: calc(100% - 120px); |
|
} |
|
.reel { |
|
aspect-ratio: 1; |
|
background: #333; |
|
border: 2px solid gold; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
font-size: 32px; |
|
position: relative; |
|
transition: transform 0.3s; |
|
} |
|
.controls { |
|
text-align: center; |
|
margin-top: 20px; |
|
position: absolute; |
|
bottom: 20px; |
|
width: calc(100% - 40px); |
|
} |
|
.button { |
|
background: linear-gradient(45deg, #FFD700, #FFA500); |
|
color: #000; |
|
padding: 15px 30px; |
|
border: none; |
|
border-radius: 25px; |
|
cursor: pointer; |
|
font-size: 18px; |
|
font-weight: bold; |
|
transition: all 0.3s ease; |
|
} |
|
.button:hover { transform: scale(1.1); } |
|
.button:disabled { |
|
background: #666; |
|
cursor: not-allowed; |
|
} |
|
#balance, #timer { |
|
position: absolute; |
|
top: 10px; |
|
font-size: 24px; |
|
background: #FFD700; |
|
color: #000; |
|
padding: 10px; |
|
border-radius: 5px; |
|
z-index: 10; |
|
} |
|
#balance { left: 10px; } |
|
#timer { right: 10px; } |
|
@keyframes spin { |
|
0% { transform: rotateY(0deg); } |
|
100% { transform: rotateY(360deg); } |
|
} |
|
.spinning { |
|
animation: spin 0.5s linear infinite; |
|
} |
|
.win-line { |
|
position: absolute; |
|
background: rgba(255, 215, 0, 0.5); |
|
z-index: 1; |
|
pointer-events: none; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="game-container"> |
|
<div id="balance">$100.00</div> |
|
<div id="timer">10</div> |
|
<div class="grid-container"> |
|
<!-- 40 reels will be created by JavaScript --> |
|
</div> |
|
<div class="controls"> |
|
<button class="button" onclick="spin()">SPIN ($1)</button> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
// Previous JavaScript code remains exactly the same |
|
let balance = 100; |
|
let timer = 10; |
|
let timerInterval; |
|
let spinning = false; |
|
let spinTimeouts = []; |
|
const symbols = ['π°', 'π', '7οΈβ£', 'π²', 'π', 'π', 'π', 'π']; |
|
let currentState = Array(40).fill(''); |
|
const ROWS = 8; |
|
const COLS = 5; |
|
|
|
// Initialize grid |
|
function initializeGrid() { |
|
const grid = document.querySelector('.grid-container'); |
|
grid.innerHTML = ''; |
|
for (let i = 0; i < ROWS * COLS; i++) { |
|
const reel = document.createElement('div'); |
|
reel.className = 'reel'; |
|
reel.id = `reel-${i}`; |
|
reel.textContent = symbols[Math.floor(Math.random() * symbols.length)]; |
|
grid.appendChild(reel); |
|
} |
|
} |
|
|
|
function updateBalance(amount) { |
|
balance += amount; |
|
document.getElementById('balance').textContent = `$${balance.toFixed(2)}`; |
|
} |
|
|
|
function spin() { |
|
if (spinning || balance < 1) return; |
|
|
|
updateBalance(-1); |
|
|
|
spinning = true; |
|
resetTimer(); |
|
|
|
document.querySelectorAll('.win-line').forEach(line => line.remove()); |
|
|
|
for (let i = 0; i < ROWS * COLS; i++) { |
|
const reel = document.getElementById(`reel-${i}`); |
|
reel.classList.add('spinning'); |
|
|
|
const delay = 2000 + Math.random() * 2000; |
|
spinTimeouts.push(setTimeout(() => stopReel(i), delay)); |
|
} |
|
} |
|
|
|
function stopReel(index) { |
|
const reel = document.getElementById(`reel-${index}`); |
|
const symbol = symbols[Math.floor(Math.random() * symbols.length)]; |
|
reel.textContent = symbol; |
|
reel.classList.remove('spinning'); |
|
currentState[index] = symbol; |
|
|
|
const stillSpinning = document.querySelectorAll('.spinning').length; |
|
if (stillSpinning === 0) { |
|
spinning = false; |
|
checkWins(); |
|
} |
|
} |
|
|
|
function checkWins() { |
|
let winningLines = []; |
|
|
|
for (let row = 0; row < ROWS; row++) { |
|
let startIdx = row * COLS; |
|
let currentSymbol = currentState[startIdx]; |
|
let count = 1; |
|
|
|
for (let col = 1; col < COLS; col++) { |
|
if (currentState[startIdx + col] === currentSymbol) { |
|
count++; |
|
} else { |
|
if (count >= 3) { |
|
winningLines.push({ |
|
start: startIdx + col - count, |
|
count: count, |
|
direction: 'horizontal', |
|
row: row |
|
}); |
|
} |
|
currentSymbol = currentState[startIdx + col]; |
|
count = 1; |
|
} |
|
} |
|
if (count >= 3) { |
|
winningLines.push({ |
|
start: startIdx + COLS - count, |
|
count: count, |
|
direction: 'horizontal', |
|
row: row |
|
}); |
|
} |
|
} |
|
|
|
let totalWin = 0; |
|
winningLines.forEach(line => { |
|
const multiplier = line.count - 2; |
|
const baseWin = Math.min(multiplier * 10, 100); |
|
totalWin += baseWin; |
|
|
|
showWinLine(line); |
|
}); |
|
|
|
if (totalWin > 0) { |
|
updateBalance(totalWin); |
|
setTimeout(() => { |
|
document.querySelectorAll('.win-line').forEach(line => line.remove()); |
|
}, 3000); |
|
} |
|
} |
|
|
|
function showWinLine(line) { |
|
const winLine = document.createElement('div'); |
|
winLine.className = 'win-line'; |
|
|
|
const firstReel = document.getElementById(`reel-${line.start}`); |
|
const reelWidth = firstReel.offsetWidth; |
|
const reelHeight = firstReel.offsetHeight; |
|
|
|
winLine.style.width = `${reelWidth * line.count}px`; |
|
winLine.style.height = '4px'; |
|
winLine.style.top = `${(line.row * reelHeight) + (reelHeight / 2)}px`; |
|
winLine.style.left = `${(line.start % COLS) * reelWidth}px`; |
|
|
|
document.querySelector('.grid-container').appendChild(winLine); |
|
} |
|
|
|
function resetTimer() { |
|
clearInterval(timerInterval); |
|
timer = 10; |
|
document.getElementById('timer').textContent = timer; |
|
timerInterval = setInterval(() => { |
|
timer--; |
|
document.getElementById('timer').textContent = timer; |
|
if (timer <= 0) { |
|
resetGame(); |
|
} |
|
}, 1000); |
|
} |
|
|
|
function resetGame() { |
|
spinning = false; |
|
clearInterval(timerInterval); |
|
spinTimeouts.forEach(timeout => clearTimeout(timeout)); |
|
spinTimeouts = []; |
|
document.querySelectorAll('.spinning').forEach(reel => reel.classList.remove('spinning')); |
|
document.querySelectorAll('.win-line').forEach(line => line.remove()); |
|
resetTimer(); |
|
} |
|
|
|
// Initialize the game |
|
initializeGrid(); |
|
resetTimer(); |
|
</script> |
|
</body> |
|
</html> |
|
""" |
|
|
|
|
|
components.html( |
|
slot_machine_html, |
|
height=800, |
|
width=1050, |
|
) |