Skip to Content
🎲 欢迎使用 RandBox - 功能强大的 JavaScript 随机数据生成库! 了解详情

CoinFlip - 抛硬币

CoinFlip 是一个基于Canvas的3D硬币抛掷游戏组件,提供真实的硬币翻转动画和统计功能。

📦 导入

import { CoinFlip } from '@randbox/react'; import type { CoinFlipProps, CoinFlipResult, CoinFlipStats } from '@randbox/react';

🎯 类型定义

CoinFlipProps

interface CoinFlipProps { // 可选属性 animationDuration?: number; // 动画时长(毫秒),默认2000 showStats?: boolean; // 是否显示统计,默认true // 基础属性(继承自BaseGameProps) className?: string; // CSS类名 style?: React.CSSProperties; // 内联样式 disabled?: boolean; // 是否禁用 // 回调函数 onGameStart?: () => void; // 游戏开始回调 onGameEnd?: (result: CoinFlipResult) => void; // 游戏结束回调 onResult?: (result: CoinFlipResult) => void; // 结果回调 }

CoinFlipResult

interface CoinFlipResult { result: 'heads' | 'tails'; // 硬币结果:正面或反面 round: number; // 回合数 timestamp: number; // 时间戳 }

CoinFlipStats

interface CoinFlipStats { totalFlips: number; // 总抛掷次数 heads: number; // 正面次数 tails: number; // 反面次数 headsRate: string; // 正面概率(百分比) tailsRate: string; // 反面概率(百分比) }

📋 API参考

CoinFlipProps

属性类型默认值描述
animationDurationnumber2000动画持续时间(毫秒)
showStatsbooleantrue是否显示统计信息
classNamestring''CSS类名
styleReact.CSSProperties{}内联样式
disabledbooleanfalse是否禁用
onGameStart() => voidundefined游戏开始回调
onGameEnd(result) => voidundefined游戏结束回调
onResult(result) => voidundefined结果回调

CoinFlipResult 结构

{ result: "heads", // "heads" 或 "tails" round: 1, // 当前回合数 timestamp: 1234567890 // 时间戳 }

CoinFlipStats 结构

{ totalFlips: 10, // 总抛掷次数 heads: 6, // 正面次数 tails: 4, // 反面次数 headsRate: "60.0", // 正面概率(百分比) tailsRate: "40.0" // 反面概率(百分比) }

🚀 基础用法

import React from 'react'; import { CoinFlip } from '@randbox/react'; function BasicCoinFlip() { const handleResult = (result) => { console.log('抛币结果:', result); alert(`结果是:${result.result === 'heads' ? '正面' : '反面'}`); }; return ( <CoinFlip onResult={handleResult} /> ); }

🎨 高级用法

自定义动画时长

function FastCoinFlip() { return ( <div> <h3>快速模式(1秒)</h3> <CoinFlip animationDuration={1000} /> <h3>慢速模式(3秒)</h3> <CoinFlip animationDuration={3000} /> </div> ); }

隐藏统计信息

function SimpleCoinFlip() { return ( <CoinFlip showStats={false} animationDuration={1500} onResult={(result) => { console.log('结果:', result.result); }} /> ); }

完整配置示例

function FullConfigCoinFlip() { const [isFlipping, setIsFlipping] = useState(false); const [history, setHistory] = useState<CoinFlipResult[]>([]); const [stats, setStats] = useState<CoinFlipStats>({ totalFlips: 0, heads: 0, tails: 0, headsRate: '0', tailsRate: '0' }); const handleGameStart = () => { setIsFlipping(true); console.log('开始抛硬币...'); }; const handleGameEnd = (result: CoinFlipResult) => { setIsFlipping(false); setHistory(prev => [result, ...prev.slice(0, 9)]); // 更新统计 const newStats = { totalFlips: stats.totalFlips + 1, heads: stats.heads + (result.result === 'heads' ? 1 : 0), tails: stats.tails + (result.result === 'tails' ? 1 : 0), headsRate: '0', tailsRate: '0' }; newStats.headsRate = ((newStats.heads / newStats.totalFlips) * 100).toFixed(1); newStats.tailsRate = ((newStats.tails / newStats.totalFlips) * 100).toFixed(1); setStats(newStats); }; return ( <div style={{ padding: '20px' }}> <CoinFlip animationDuration={2000} showStats={true} className="my-coin-flip" disabled={isFlipping} onGameStart={handleGameStart} onGameEnd={handleGameEnd} onResult={(result) => { console.log('实时结果:', result); }} /> {/* 抛币历史 */} {history.length > 0 && ( <div style={{ marginTop: '20px' }}> <h3>最近10次记录:</h3> <div style={{ display: 'flex', gap: '5px', flexWrap: 'wrap' }}> {history.map((result, index) => ( <span key={index} style={{ padding: '5px 10px', backgroundColor: result.result === 'heads' ? '#2ecc71' : '#e74c3c', color: 'white', borderRadius: '5px', fontSize: '12px' }} > {result.result === 'heads' ? '正面' : '反面'} </span> ))} </div> </div> )} {/* 统计汇总 */} <div style={{ marginTop: '20px', padding: '15px', backgroundColor: '#f5f5f5' }}> <h3>统计汇总</h3> <p>总次数:{stats.totalFlips}</p> <p>正面:{stats.heads} ({stats.headsRate}%)</p> <p>反面:{stats.tails} ({stats.tailsRate}%)</p> </div> </div> ); }

📋 API参考

属性说明

属性类型默认值描述
animationDurationnumber2000动画持续时间(毫秒)
showStatsbooleantrue是否显示统计信息
classNamestring''CSS类名
styleReact.CSSProperties{}内联样式
disabledbooleanfalse是否禁用
onGameStart() => voidundefined游戏开始回调
onGameEnd(result) => voidundefined游戏结束回调
onResult(result) => voidundefined结果回调

CoinFlipResult 结构

{ result: "heads", // "heads" 或 "tails" round: 1, // 当前回合数 timestamp: 1234567890 // 时间戳 }

🎨 样式定制

容器样式

.my-coin-flip { border: 3px solid #f39c12; border-radius: '20px'; padding: '20px'; box-shadow: 0 10px 30px rgba(0,0,0,0.3); }

🔧 高级功能

猜硬币游戏

function GuessCoinGame() { const [guess, setGuess] = useState<'heads' | 'tails' | null>(null); const [score, setScore] = useState({ wins: 0, losses: 0 }); const handleResult = (result: CoinFlipResult) => { if (guess === result.result) { setScore(prev => ({ ...prev, wins: prev.wins + 1 })); alert('猜对了!🎉'); } else { setScore(prev => ({ ...prev, losses: prev.losses + 1 })); alert('猜错了!😢'); } setGuess(null); }; return ( <div> <h3>猜硬币游戏</h3> <p>战绩 - 赢:{score.wins} 输:{score.losses}</p> <div style={{ marginBottom: '20px' }}> <button onClick={() => setGuess('heads')} disabled={guess !== null}> 猜正面 </button> <button onClick={() => setGuess('tails')} disabled={guess !== null}> 猜反面 </button> </div> <CoinFlip disabled={guess === null} onResult={handleResult} /> {guess && <p>你的选择:{guess === 'heads' ? '正面' : '反面'}</p>} </div> ); }

🎯 最佳实践

1. 概率验证

// 大量实验验证随机性 function ProbabilityTest() { const [trials, setTrials] = useState(0); const [heads, setHeads] = useState(0); const runTrials = (n: number) => { for (let i = 0; i < n; i++) { // 模拟抛币... } }; return ( <div> <button onClick={() => runTrials(1000)}>运行1000次</button> <p>总次数:{trials}</p> <p>正面率:{(heads / trials * 100).toFixed(2)}%</p> <p>理论值:50%</p> </div> ); }

🐛 常见问题

Q: 结果真的是随机的吗?

A: 是的,使用RandBox的Mersenne Twister算法,确保高质量的随机性。

Q: 可以预测结果吗?

A: 不可以,每次抛币都是独立事件,无法预测。

Q: 为什么连续出现多次相同结果?

A: 这是正常的随机现象,类似现实中的连续正面或反面。

🔗 相关链接

最后更新于: