Vue 3 Slot Machine Component
This challenge focuses on building a reusable Vue 3 component that simulates a slot machine's spinning reels. This is a common UI pattern that can be used in games, promotional tools, or interactive demonstrations, requiring careful management of state, animation, and user interaction.
Problem Description
You are tasked with creating a Vue 3 component named SlotMachine that simulates the behavior of a slot machine. The component should accept an array of possible symbols (e.g., fruits, numbers) and, when triggered, randomly spin through these symbols on multiple reels, eventually landing on a final combination.
Key Requirements:
- Configurable Reels: The component should allow the user to specify the number of reels.
- Customizable Symbols: Users should be able to provide an array of symbols (strings or objects) that can appear on the reels.
- Spin Functionality: A method to initiate the spinning of the reels.
- Random Selection: Each reel should randomly select a final symbol from the provided symbol set.
- Visual Animation: A smooth visual animation should simulate the reels spinning.
- Reel Synchronization: All reels should start and stop spinning in a synchronized manner, even if their individual random stopping points differ.
- Result Display: The final landed symbols should be clearly displayed.
- State Management: The component needs to manage its internal state, including whether it's currently spinning and the current symbols being displayed on each reel.
Expected Behavior:
- The
SlotMachinecomponent is initialized with a list of symbols and a desired number of reels. - When a "Spin" action is triggered (e.g., by a button click), all reels begin to spin rapidly.
- During the spin, each reel displays a sequence of symbols from the provided set, cycling through them.
- After a predetermined duration or animation sequence, each reel settles on a randomly chosen final symbol.
- The spinning animation should be visually appealing and clearly indicate the change between symbols.
Edge Cases:
- Empty Symbol List: What happens if no symbols are provided?
- Zero Reels: What if the user requests zero reels?
- Very Fast Spinning: The animation should be noticeable and not just instantaneous.
- Multiple Spins: The component should handle multiple spin requests correctly.
Examples
Example 1: Basic Setup
<template>
<div>
<SlotMachine :symbols="['🍎', '🍊', '🍋', '🍒']" :numReels="3" />
</div>
</template>
<script setup lang="ts">
import SlotMachine from './components/SlotMachine.vue';
</script>
Output:
(Visually, a slot machine with 3 reels. When the spin button is clicked, the reels spin and land on a combination like '🍎', '🍊', '🍒', or any other combination from the provided symbols.)
Explanation:
This example shows how to use the SlotMachine component with a simple array of fruit emojis as symbols and requests three reels.
Example 2: With Custom Symbols and Spin Trigger
<template>
<div>
<div class="reel-container">
<div v-for="(reel, index) in currentSymbols" :key="index" class="reel">
{{ reel }}
</div>
</div>
<button @click="spin">Spin</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import SlotMachine from './components/SlotMachine.vue'; // Assuming SlotMachine component is defined elsewhere
const symbols = ['⭐', '✨', '💎', '💰'];
const numReels = 4;
const currentSymbols = ref<string[]>(Array(numReels).fill(symbols[0])); // Initial state
const spin = () => {
// This is a simplified representation. The actual SlotMachine component
// would handle the spinning logic internally and emit results.
// For demonstration, let's assume it returns a winning combination.
// In a real scenario, you'd call a method on the SlotMachine component.
console.log("Spinning reels...");
// Assume the SlotMachine component emits a 'results' event with the landed symbols
// For this example, we'll just simulate a random outcome.
const landedSymbols = Array.from({ length: numReels }, () => symbols[Math.floor(Math.random() * symbols.length)]);
currentSymbols.value = landedSymbols;
console.log("Landed on:", landedSymbols);
};
</script>
<style>
.reel-container {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.reel {
width: 50px;
height: 50px;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
font-size: 2em;
}
</style>
Output:
(When the "Spin" button is clicked, the reels visually spin and then display a new random combination of stars, sparkles, diamonds, or coins.)
Explanation:
This example demonstrates how a parent component might interact with the SlotMachine. The parent would typically emit a spin event or call a spin method on the SlotMachine component. The SlotMachine would then internally manage the animation and emit an event with the final landed symbols, which the parent could then display or use to determine a win.
Example 3: Handling Different Symbol Types
<template>
<div>
<SlotMachine :symbols="[
{ id: 1, icon: '🔴' },
{ id: 2, icon: '🔵' },
{ id: 3, icon: '🟢' }
]" :numReels="2" />
</div>
</template>
<script setup lang="ts">
import SlotMachine from './components/SlotMachine.vue';
</script>
Output:
(A slot machine with 2 reels, displaying combinations of red, blue, and green circles. The component should be able to handle objects as symbols and display the icon property.)
Explanation:
This example shows that the symbols prop can accept an array of objects, allowing for richer symbol data. The component should be able to render these symbols correctly, likely by accessing a specific property like icon.
Constraints
- Number of Reels: The
numReelsprop will be an integer between 1 and 10, inclusive. - Symbols: The
symbolsprop will be an array containing at least one element. Each element in the array can be a string or an object. If an object, it must have aniconproperty (string) that will be used for display. - Spin Duration: The spinning animation for each reel should last between 1.5 and 3 seconds.
- Rendering Performance: The component should render smoothly without noticeable lag, even with the maximum number of reels and a moderate number of symbols.
- Vue Version: The solution must be implemented using Vue 3 and TypeScript.
Notes
- Consider using Vue's composition API (
setupscript) for state management and logic. - For animation, you can explore CSS transitions,
requestAnimationFrame, or a dedicated animation library. - Think about how to generate the visual sequence of symbols that will be displayed during the spin before landing on the final result.
- The component should expose a
spinmethod that the parent can call. - Consider emitting an event (e.g.,
spin-end) from theSlotMachinecomponent that includes the final landed symbols, allowing parent components to react to the results. - How will you handle the case where a symbol is an object? The component should be flexible enough to display the relevant part of the object (e.g., an
iconproperty).