<div id="OuterContainer">
<div id="BoardContainer">
<div class="Btn" id="green">
</div>
<div class="Btn" id="red">
</div>
<div class="Btn" id="yellow">
</div>
<div class="Btn" id="blue">
</div>
<div id="Controls">
<h2>Simon</h2>
<div id="Counter" class="Ctrl">
<div id="CounterScreen">
<p>--</p>
</div>
<h4 class="Label">Count</h4>
</div>
<div class="BtnWrp Ctrl" id="Start">
<div class="CtlBtn"></div>
<h4 class="Label">Start</h4>
</div>
<div class="BtnWrp Ctrl" id="Strict">
<div class="CtlBtn"></div>
<h4 class="Label">Strict</h4>
</div>
<div id="OnOff" class="Ctrl">
<h4 class="Label">Off</h4>
<div class="Switch">
<div class="SwitchTab"></div>
</div>
<h4 class="Label">On</h4></div>
</div>
</div>
</div>
@import url(https://fonts.googleapis.com/css?family=Merriweather\|VT323)
yellow = #CCA707
brightYellow = #FFFF00
red = #9F0F17
brightRed = #FC0102
blue = #094A8F
brightBlue = #3193DE
green = #008000
brightGreen = #32CD32
body
background url(http://cdn.backgroundhost.com/backgrounds/subtlepatterns/purty_wood.png)
background-repeat repeat
text-align center
font-family: 'Merriweather', 'helvetica';
#OuterContainer
width 98vw
height 98vh
margin auto
padding 0
border 0
#BoardContainer
position absolute
top 50%
left 50%
transform translate(-50%,-50%)
border-radius 50%
background #aaa
border 4vh solid #333
z-index 1
overflow hidden
.Btn
border 2vh solid #333
position absolute
#red
bottom 50%
left 50%
background red
#red.active
background brightRed
#blue
top 50%
left 50%
background blue
#blue.active
background brightBlue
#yellow
top 50%
right 50%
background yellow
#yellow.active
background brightYellow
#green
bottom 50%
right 50%
background green
#green.active
background brightGreen
@media (orientation:landscape)
#BoardContainer
height 80vh
width 80vh
.Btn
width: 40vh
height: 40vh
html
font-size 8vh
@media (orientation:portrait)
#BoardContainer
height 80vw
width 80vw
.Btn
width: 40vw
height: 40vw
html
font-size 8vw
/*** Central control panel ***/
#Controls
position absolute
top 50%
left 50%
transform translate(-50%, -50%)
background white
border-radius 50%
width 50%
height 50%
border 2vh solid #333
z-index 50
#Controls h2
font-size 1rem
margin 0.8rem 0 0 0
#Counter, .BtnWrp
display inline-block
width 27%
#CounterScreen
height 0.8rem
margin auto
overflow hidden
border 1vh solid #333
border-radius 8px
background #32050C
#CounterScreen p
margin 0rem
font-family: 'VT323'
font-size 0.8rem
color #430710
#Counter.On p
color #DC0D29
h4.Label
font-family 'helvetica','arial',
sans-serif
font-size 0.3rem
margin 0.2rem 0 0 0
text-transform uppercase
#Start
margin 0 -0.2rem 0 0
.CtlBtn
border 1vh solid #333
border-radius 50%
width 0.5rem
height 0.5rem
margin auto
#Start>.CtlBtn
background red
#Strict>.CtlBtn
background yellow
#OnOff
position: relative;
top: -0.4rem;
#Controls
cursor default
.Switch, .BtnWrp, .CtlBtn, .Btn
pointer-events all
cursor: pointer;
#OnOff .Label, #OnOff .Switch
display inline-block
vertical-align middle
.Switch
height 0.5rem
width 1rem
border-radius 3px
background #111
.SwitchTab
height 0.34rem
width 0.34rem
border-radius 3px
border 0.09rem solid #333
background blue
float left
#OnOff.On .SwitchTab
background brightBlue
float right
#Start.On .CtlBtn
background brightRed
#Strict.On .CtlBtn
background brightYellow
#Strict .CtlBtn.Active
background brightGreen
$(document).ready(function() {
/*** Global variables ***/
var seqLength;
var seq;
var userSeq;
var userTurn;
var userError;
var tempo;
var btnTime;
var lastPlayed;
// Change variable values here
function resetBoard() { // sets required values, called at start and anytime start btn is pushed.
seqLength = 20;
seq = [];
userSeq = [];
userTurnFunc(false);
lastPlayed = null;
tempo = 1000;
}
var sounds = {
red: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound1.mp3'),
blue: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound2.mp3'),
yellow: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound3.mp3'),
green: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound4.mp3')
}
/*** Functions ***/
function toggleOnOff() { // Turns game board on and off
if ($('#OnOff').hasClass('On')) {
$('.Ctrl').each(function() {
$(this).removeClass('On');
resetBoard();
});
} else {
$('.Ctrl').each(function() {
$(this).addClass('On');
});
}
}
function btnPress(btn) { // Function to highlight button and play sound when pressed
if (lastPlayed && lastPlayed.duration > 0) { // cuts off previous btn sound if user going too quick
lastPlayed.pause();
lastPlayed.load();
}
sounds[btn].play();
lastPlayed = sounds[btn];
clearTimeout(btnTime);
$('.Btn').each(function() {
$(this).removeClass('active');
});
$('#'+btn).addClass('active');
btnTime = setTimeout(function() {
$('#'+btn).removeClass('active');
}, tempo);
}
function sequencer() {
if (seq.length<seqLength) { // check game should continue
if (!userError) {
switch (Math.floor(Math.random()*4)) { // add new step to seq
case 0:
var temp = seq.push('red');
break;
case 1:
var temp = seq.push('blue');
break;
case 2:
var temp = seq.push('yellow');
break;
case 3:
var temp = seq.push('green');
break;
}
switch (seq.length) { // tempo increases as turns progress.
case 5:
tempo = 700;
break;
case 9:
tempo = 550;
break;
case 13:
tempo = 400;
break;
}
} else {
userError = false; // reset userError flag without new step in seq
}
if (seq.length<=9) {
var cntDisp = '0'+(seq.length);
} else {
var cntDisp = seq.length;
}
$('#CounterScreen p').text(cntDisp);
seq.forEach(function(btn,index) {
setTimeout(function() {
btnPress(btn);
if (index === seq.length-1) { // Return user control on final btnPress
userTurnFunc(true);
}
}, (tempo+100)*index); // delay each button by a factor of its index
});
console.log('Seq = '+seq);
} else { // User has completed whole 20 sequence
$('.Btn').each(function() {
$(this).addClass('active');
});
$('#Controls h2').text('Winner!');
setTimeout(function() {
$('.Btn').each(function() {
$(this).removeClass('active');
});
setTimeout(function() {
$('.Btn').each(function() {
$(this).addClass('active');
});
setTimeout(function() {
$('.Btn').each(function() {
$(this).removeClass('active');
$('#Controls h2').text('Simon');
});
},2400);
},400);
},400);
}
}
function seqCheck() {
for (i=0;i<userSeq.length;i++) {
if (userSeq[i] !== seq[i]) { // User made error in sequence, sets flag to true
$('#CounterScreen p').text('!!');
userError = true;
userSeq = [];
}
}
if (userError) {
userTurnFunc(false);
if ($('#Strict .CtlBtn').hasClass('Active')) { // Checks for strict mode and resets board if found
resetBoard();
}
setTimeout(function() {
sequencer();
}, tempo*2);
} else if (!userError && userSeq.length === seq.length) { // User completed seq
userTurnFunc(false);
userSeq = [];
setTimeout(function() {
sequencer();
},tempo*2);
}
}
function userTurnFunc(bool) { // turn off pointer cursor on coloured buttons to indicate to user that it's not their turn
if (bool) {
userTurn = true;
$('.Btn').map(function() {
$(this).css('cursor','pointer');
});
} else {
userTurn = false;
$('.Btn').map(function() {
$(this).css('cursor','auto');
});
}
}
/*** Buttons ***/
$('#OnOff .Switch').click(function() {
toggleOnOff();
});
$('#Start .CtlBtn').click(function() {
if ($('#OnOff').hasClass('On')) {
resetBoard();
sequencer();
}
});
$('#Strict .CtlBtn').click(function() {
if ($('#OnOff').hasClass('On')) {
if ($('#Strict .CtlBtn').hasClass('Active')) {
$('#Strict .CtlBtn').removeClass('Active');
} else {
$('#Strict .CtlBtn').addClass('Active');
}
}
});
$('.Btn').click(function() {
if (userTurn) {
var btn = $(this).attr('id')
btnPress(btn);
var temp = userSeq.push(btn);
seqCheck();
}
});
resetBoard();
});
Also see: Tab Triggers