Created
May 6, 2016 06:52
-
-
Save Zyst/0dcf43ffd31624bb793b4e75d5be36e6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var StarsFrame = React.createClass({ | |
render: function() { | |
let stars = []; | |
for (let i = 0; i < this.props.numberOfStars; i++) { | |
stars.push( | |
<span key={i} className="glyphicon glyphicon-star"></span> | |
); | |
} | |
return ( | |
<div id="stars-frame"> | |
<div className="well"> | |
{stars} | |
</div> | |
</div> | |
); | |
} | |
}); | |
var ButtonFrame = React.createClass({ | |
render: function() { | |
let correct = this.props.correct; | |
let button; | |
let disabled = this.props.selectedNumbers.length === 0; | |
if (correct === true) { | |
button = ( | |
<button | |
className="btn btn-success btn-lg" | |
onClick={this.props.acceptAnswer} | |
> | |
<span className="glyphicon glyphicon-ok"></span> | |
</button> | |
); | |
} else if (correct === false) { | |
button = ( | |
<button | |
className="btn btn-danger btn-lg" | |
> | |
<span className="glyphicon glyphicon-remove"></span> | |
</button> | |
); | |
} else { | |
button = ( | |
<button | |
className="btn btn-primary btn-lg" | |
disabled={disabled} | |
onClick={this.props.checkAnswer} | |
> | |
= | |
</button> | |
); | |
} | |
return ( | |
<div id="button-frame"> | |
{button} | |
<hr /> | |
<button | |
className="btn btn-warning btn-xs" | |
onClick={this.props.redraw} | |
disabled={this.props.redraws === 0} | |
> | |
<span className="glyphicon glyphicon-refresh"></span> | |
{' '} | |
{this.props.redraws} | |
</button> | |
</div> | |
); | |
} | |
}); | |
var AnswerFrame = React.createClass({ | |
render: function() { | |
let numbers = this.props.selectedNumbers; | |
let props = this.props; | |
let display = numbers.map(function(number, index) { | |
return ( | |
<span | |
key={index} | |
onClick={props.unselectNumber.bind(null, number)} | |
> | |
{number} | |
</span> | |
); | |
}); | |
return ( | |
<div id="answer-frame"> | |
<div className="well"> | |
{display} | |
</div> | |
</div> | |
); | |
} | |
}); | |
var NumbersFrame = React.createClass({ | |
render: function() { | |
let numbers = []; | |
for (let i = 1; i <= 9; i++) { | |
// If it's true class is 'numbers selected-true', or 'numbers selected-false' otherwise | |
let className = "number selected-" + (this.props.selectedNumbers.indexOf(i) >= 0); | |
className += " used-" + (this.props.usedNumbers.indexOf(i) >= 0); | |
numbers.push( | |
<div | |
className={className} | |
key={i} | |
onClick={this.props.clickNumber.bind(null, i)} | |
> | |
{i} | |
</div> | |
); | |
} | |
return ( | |
<div id="numbers-frame"> | |
<div className="well"> | |
{numbers} | |
</div> | |
</div> | |
); | |
} | |
}); | |
var DoneFrame = React.createClass({ | |
render: function() { | |
return ( | |
<div className="well text-center"> | |
<h2>{this.props.doneStatus}</h2> | |
<button | |
className="btn btn-default" | |
onClick={this.props.resetGame} | |
> | |
Play again | |
</button> | |
</div> | |
); | |
} | |
}); | |
var Game = React.createClass({ | |
getInitialState: function() { | |
return { | |
selectedNumbers: [], | |
usedNumbers: [], | |
correct: null, | |
redraws: 5, | |
doneStatus: null, | |
numberOfStars: Math.floor(Math.random() * 9) + 1 | |
}; | |
}, | |
resetGame: function() { | |
this.replaceState(this.getInitialState()); | |
}, | |
clickNumber: function(clickedNumber) { | |
if (this.state.selectedNumbers.indexOf(clickedNumber) < 0) { | |
this.setState( | |
{ | |
selectedNumbers: this.state.selectedNumbers.concat(clickedNumber) , | |
correct: null | |
} | |
); | |
} | |
}, | |
unselectNumber: function(clickedNumber) { | |
let selectedNumbers = this.state.selectedNumbers; | |
let indexOfNumber = selectedNumbers.indexOf(clickedNumber); | |
selectedNumbers.splice(indexOfNumber, 1); | |
this.setState({ selectedNumbers: selectedNumbers, correct: null }); | |
}, | |
sumOfSelectedNumbers: function() { | |
return this.state.selectedNumbers.reduce(function(p, n) { | |
return p + n; | |
}, 0); | |
}, | |
checkAnswer: function() { | |
let correct = this.state.numberOfStars === this.sumOfSelectedNumbers(); | |
this.setState({ correct: correct }); | |
}, | |
acceptAnswer: function() { | |
let usedNumbers = this.state.usedNumbers.concat(this.state.selectedNumbers); | |
this.setState({ | |
selectedNumbers: [], | |
usedNumbers: usedNumbers, | |
correct: null, | |
numberOfStars: Math.floor(Math.random() * 9) + 1 | |
}, function() { | |
this.updateDoneStatus(); | |
}); | |
}, | |
redraw: function() { | |
if (this.state.redraws > 0) { | |
this.setState({ | |
numberOfStars: Math.floor(Math.random() * 9) + 1, | |
current: null, | |
selectedNumbers: [], | |
redraws: this.state.redraws - 1 | |
}, function() { | |
this.updateDoneStatus(); | |
}); | |
} | |
}, | |
possibleCombinationSum: function(arr, n) { | |
if (arr.indexOf(n) >= 0) { return true; } | |
if (arr[0] > n) { return false; } | |
if (arr[arr.length - 1] > n) { | |
arr.pop(); | |
return possibleCombinationSum(arr, n); | |
} | |
var listSize = arr.length, combinationsCount = (1 << listSize) | |
for (var i = 1; i < combinationsCount ; i++ ) { | |
var combinationSum = 0; | |
for (var j=0 ; j < listSize ; j++) { | |
if (i & (1 << j)) { combinationSum += arr[j]; } | |
} | |
if (n === combinationSum) { return true; } | |
} | |
return false; | |
}, | |
possibleSolutions: function() { | |
let numberOfStars = this.state.numberOfStars; | |
let possibleNumbers = []; | |
let usedNumbers = this.state.usedNumbers; | |
for (let i = 1; i <= 9; i++) { | |
if (usedNumbers.indexOf(i) < 0) { | |
possibleNumbers.push(i); | |
} | |
} | |
return this.possibleCombinationSum(possibleNumbers, numberOfStars); | |
}, | |
updateDoneStatus: function() { | |
if (this.state.usedNumbers.length === 9) { | |
this.setState({ doneStatus: '♕ Victory! ♕' }); | |
} | |
if (this.state.redraws === 0 && !this.possibleSolutions()) { | |
this.setState({ doneStatus: 'Game Over!' }); | |
} | |
}, | |
render: function() { | |
let bottomFrame; | |
if (this.state.doneStatus) { | |
bottomFrame = <DoneFrame | |
doneStatus={this.state.doneStatus} | |
resetGame={this.resetGame} | |
/>; | |
} else { | |
bottomFrame = <NumbersFrame | |
selectedNumbers={this.state.selectedNumbers} | |
usedNumbers={this.state.usedNumbers} | |
clickNumber={this.clickNumber} | |
/>; | |
} | |
return ( | |
<div id="game"> | |
<h2>Play Nine</h2> | |
<hr /> | |
<div className="clearfix"> | |
<StarsFrame numberOfStars={this.state.numberOfStars} /> | |
<ButtonFrame selectedNumbers={this.state.selectedNumbers} | |
correct={this.state.correct} | |
checkAnswer={this.checkAnswer} | |
acceptAnswer={this.acceptAnswer} | |
redraw={this.redraw} | |
redraws={this.state.redraws} /> | |
<AnswerFrame selectedNumbers={this.state.selectedNumbers} | |
unselectNumber={this.unselectNumber} /> | |
</div> | |
{bottomFrame} | |
</div> | |
); | |
} | |
}); | |
ReactDOM.render( | |
<Game />, | |
document.getElementById('core') | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment