HTML
JavaScript
音声認識

イカサマルーレットを作った話


何を作ったか?

イカサマ用のルーレットを作りました。

デモ (スマホ推奨)

github


やりかた


①友達と何か賭けをする

ジュース1本おごりレベルの軽い賭けにすることをお勧めします


②ルーレットを回して、友達に色を選んでもらう

ここで「声を出して色を言う」事がポイント


③ルーレットを止めてもらう

イカサマを疑われないため、止めるタイミングは友達に決めてもらいます


④結果を見る

あら不思議、何回やっても友達が言ってない方の色が当たってます。


種明かし

音声認識で友達の選んだ色を特定し、友達が選んでない側の色が当たるように調節します。


ソースコード


Javascript

col = null

isMatch=location.href.split('?')[1]=="a"// URLの末尾に ?aを入れると「言った通りの色が出る」になります

flag = true
start_btn.addEventListener('click', () => {//スタートボタンを押したら
if (flag) {//2重押し防止
recognition.start()//音声認識開始
flag=false
start_btn.style.backgroundColor="#1d4293"
start_btn.innerText="STOP"
deg=0
speed=5
rotating=setInterval(()=>{//ルーレットを回す
deg+=speed
roulette.style.transform="rotate("+deg+"deg)"
},10)
} else {//2回目はストップボタンとして機能
start_btn.style.opacity="0"
speed=4
setTimeout(()=>{
speed=3
},1000)
setTimeout(()=>{
Stop(col)
},2000)
}
})

recognition = new webkitSpeechRecognition();//音声認識
recognition.onresult = function(event) {
if (event.results.length > 0) {
spoken = event.results[0][0].transcript//言った内容
console.log(spoken)
ch1=spoken.split('緑').length - 1 + spoken.split('ミド').length-1 + spoken.split('みど').length-1 //緑 っぽいことを言った回数
ch2=spoken.split('紫').length - 1 + spoken.split('ムラ').length-1 + spoken.split('むら').length-1 //紫 っぽいことを言った回数
if (ch1 || ch2) {//どちらも0だったらもう1度
if (ch1>ch2){
col = "green"
}else{
col = "purple"
}
}else{
recognition.start()
}
}
}

function Stop(col){
if(!isMatch){//初めの値がFalse→「言ってない色が当たる」モードの時は、緑⇔紫を入れ替える
if(col=="green"){
col="purple"
}else if(col=="purple"){
col="green"
}
}
if (col=="green"){
if (deg%360<180){
clearInterval(rotating)
restart.style.opacity="1"
}else{
setTimeout(()=>{
clearInterval(rotating)
restart.style.opacity="1"
},600)
}
}
else if(col=="purple"){
if (deg%360>180){
clearInterval(rotating)
restart.style.opacity="1"
}else{
setTimeout(()=>{
clearInterval(rotating)
restart.style.opacity="1"
},600)
}
} else {//認識できなかった時は、普通にランダムに回す
setTimeout(() => {
clearInterval(rotating)
restart.style.opacity="1"
}, Math.round(Math.random() * 1200))
}
}

restart.addEventListener('click',()=>{
location.reload();
})


html

別に工夫はしてないです

<!DOCTYPE html>

<html lang='ja'>
<head>
<meta charset="UTF-8">
<title>Roulette</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="content">
<div id="pointer"></div>
<div id="roulette"></div>
<div id="start_btn">START</div>
</div>
<div id="restart">
もう1度
</div>
<script type="text/javascript" src="main.js"></script>
</body>
</html>


CSS

::beforeとoverflow:hiddenで円を2分割しています

body{

position: absolute;
width:100vw;
height:100vh;
overflow: hidden;
margin: 0;
padding: 0;
box-sizing: border-box;
}
#content{
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
#start_btn{
position: absolute;
width: 30vmin;
height:30vmin;
border-radius: 50%;
background-color: #c60019;
display: flex;
justify-content:center;
align-items: center;
font-size:6vw;
color: white;
}
#roulette{
position: absolute;
width: 60vmin;
height: 60vmin;
background-color:#7d0f80;
border-radius: 50%;
overflow: hidden;
display: flex;
}
#roulette::before{
content:"";
position: absolute;
top:0;
left:0;
width:50%;
height:100%;
background-color:#00984b;
transform-origin: right center;
}
#pointer{
content:"";
position: absolute;
transform: translateY(-33vmin);
width: 0;
height: 0;
border-style: solid;
border-width: 7vmin 4vmin 0 4vmin;
border-color: #007bff transparent transparent transparent;
}
#restart{
position: absolute;
bottom:10%;
left:30%;
width: 40%;
text-align: center;
padding: 5%;
box-sizing: border-box;
font-size: 8vmin;
background-color: #019fe6;
border-radius: 20%;
box-shadow: 2px 2px 2px 2px rgba(0,0,0,0.3);
opacity: 0;

}


注意

・これはジョークアプリです。

・使用によって発生したいかなる損害についても責任は負いません。

・音声認識はたまに機能しません

・バレる可能性は十分にあります