Created
April 27, 2016 23:29
-
-
Save anonymous/bc781cb6cdf23cb8dffb30bbb2d3bf2c to your computer and use it in GitHub Desktop.
JS Bin // source http://jsbin.com/jolaceg
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="https://code.jquery.com/jquery.min.js"></script> | |
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> | |
<script src="https://fb.me/react-with-addons-0.14.7.min.js"></script> | |
<script src="https://fb.me/react-dom-0.14.7.min.js"></script> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>JS Bin</title> | |
<style id="jsbin-css"> | |
#stars-frame, #answer-frame { | |
width: 40%; | |
float: left; | |
} | |
#stars-frame .glyphicon { | |
margin: 0.3em; | |
font-size: 1.74em; | |
} | |
#button-frame { | |
width: 20%; | |
float: left; | |
text-align: center; | |
margin-top: 50px; | |
} | |
#stars-frame .well, #answer-frame .well { | |
height: 150px; | |
} | |
#numbers-frame .number, #answer-frame .well span { | |
display: inline-block; | |
margin: 0.5em; | |
background-color: #bbb; | |
width: 30px; | |
text-align: center; | |
font-size: 22px; | |
border-radius: 50%; | |
cursor: pointer; | |
} | |
#numbers-frame .selected-true { | |
background-color: #e8e8e8; | |
color: #ddd; | |
cursor: not-allowed; | |
} | |
#numbers-frame .used-true { | |
background-color: #aaddaa; | |
color: #33aa33; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="root" class="container"></div> | |
<script id="jsbin-javascript"> | |
var StarsFrame = React.createClass({displayName: 'StarsFrame', | |
render: function(){ | |
var stars = []; | |
for ( var i = 0; i < this.props.numberOfStars; i++ ) { | |
stars.push( | |
React.createElement("span", {className: "glyphicon glyphicon-star"}) | |
); | |
} | |
return ( | |
React.createElement("div", {id: "stars-frame"}, | |
React.createElement("div", {className: "well"}, | |
stars | |
) | |
) | |
); | |
} | |
}); | |
var ButtonFrame = React.createClass({displayName: 'ButtonFrame', | |
render: function(){ | |
var e = "=", | |
correct = this.props.correct, | |
button, | |
redrawDisabled = (this.props.redraws === 0), | |
disabled; | |
switch(correct) { | |
case true: | |
button = ( | |
React.createElement("button", {className: "btn btn-success btn-lg", onClick: this.props.acceptAnswer}, | |
React.createElement("span", {className: "glyphicon glyphicon-ok"}) | |
) | |
); | |
break; | |
case false: | |
button = ( | |
React.createElement("button", {className: "btn btn-danger btn-lg"}, | |
React.createElement("span", {className: "glyphicon glyphicon-remove"}) | |
) | |
); | |
break; | |
default: | |
disabled = (this.props.selectedNumbers.length === 0), | |
button = ( | |
React.createElement("button", {className: "btn btn-primary btn-lg", disabled: disabled, | |
onClick: this.props.checkAnswer}, | |
e | |
) | |
); | |
} | |
return ( | |
React.createElement("div", {id: "button-frame"}, | |
button, | |
React.createElement("br", null), React.createElement("br", null), | |
React.createElement("button", {className: "btn btn-warning btn-xs", onClick: this.props.redraw, disabled: redrawDisabled}, | |
React.createElement("span", {className: "glyphicon glyphicon-refresh"}), | |
" ", | |
this.props.redraws | |
) | |
) | |
); | |
} | |
}); | |
var AnswerFrame = React.createClass({displayName: 'AnswerFrame', | |
render: function(){ | |
var props = this.props; | |
var selectedNumbers = props.selectedNumbers.map(function(i){ | |
return ( | |
React.createElement("span", {onClick: props.unselectedNumber.bind(null, i)}, | |
i | |
) | |
) | |
}); | |
return ( | |
React.createElement("div", {id: "answer-frame"}, | |
React.createElement("div", {className: "well"}, | |
selectedNumbers | |
) | |
) | |
); | |
} | |
}); | |
var NumbersFrame = React.createClass({displayName: 'NumbersFrame', | |
render: function () { | |
var numbers = [], | |
className, | |
selectedNumber = this.props.selectedNumber, | |
selectedNumbers = this.props.selectedNumbers, | |
usedNumbers = this.props.usedNumbers; | |
for (var i = 1; i<=9; i++) { | |
className = "number selected-" + (selectedNumbers.indexOf(i) >= 0); | |
className += " used-" + (usedNumbers.indexOf(i) >= 0); | |
numbers.push( | |
React.createElement("div", {className: className, onClick: selectedNumber.bind(null, i)}, i) | |
); | |
} | |
return ( | |
React.createElement("div", {id: "numbers-frame"}, | |
React.createElement("div", {className: "well"}, | |
numbers | |
) | |
) | |
); | |
} | |
}); | |
var DoneFrame = React.createClass({displayName: 'DoneFrame', | |
render: function() { | |
return ( | |
React.createElement("div", {className: "well text-center"}, | |
React.createElement("h2", null, this.props.doneStatus), | |
React.createElement("button", {className: "btn btn-primary", onClick: this.props.restartGame}, | |
"Play again" | |
) | |
) | |
); | |
} | |
}); | |
var Game = React.createClass({displayName: 'Game', | |
getInitialState: function() { | |
return { | |
selectedNumbers: [], | |
numberOfStars: this.randomNumber(), | |
correct: null, | |
redraws: 5, | |
usedNumbers: [], | |
doneStatus: null | |
}; | |
}, | |
randomNumber: function() { | |
return Math.floor(Math.random() * 9) + 1; | |
}, | |
selectedNumber: function(clickedNumber) { | |
var selectedNumbers = this.state.selectedNumbers.concat(clickedNumber); | |
if(this.state.selectedNumbers.indexOf(clickedNumber) < 0) { | |
this.setState({ | |
selectedNumbers: selectedNumbers, | |
correct: null | |
}); | |
} | |
}, | |
unselectedNumber: function(clickedNumber) { | |
var selectedNumbers = this.state.selectedNumbers; | |
var indexOfNumber = selectedNumbers.indexOf(clickedNumber); | |
selectedNumbers.splice(indexOfNumber, 1); | |
this.setState({ | |
selectedNumbers: selectedNumbers, | |
correct: null | |
}); | |
}, | |
restartGame: function() { | |
this.replaceState(this.getInitialState()); | |
}, | |
sumOfSelectedNumbers: function() { | |
return this.state.selectedNumbers.reduce(function(p,n){ | |
return p+n; | |
}, 0); | |
}, | |
checkAnswer: function() { | |
var correct = (this.state.numberOfStars === this.sumOfSelectedNumbers()); | |
this.setState({ | |
correct: correct | |
}); | |
}, | |
acceptAnswer: function() { | |
// Build this out | |
var usedNumbers = this.state.usedNumbers.concat(this.state.selectedNumbers); | |
this.setState({ | |
selectedNumbers: [], | |
usedNumbers: usedNumbers, | |
correct: null, | |
numberOfStars: this.randomNumber() | |
}, function() { | |
this.updateDoneStatus(); | |
}); | |
}, | |
redraw: function() { | |
if(this.state.redraws > 0) { | |
this.setState({ | |
numberOfStars: this.randomNumber(), | |
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() { | |
var usedNumbers = this.state.usedNumbers, | |
possibleNumbers = [], | |
numberOfStars = this.state.numberOfStars; | |
for (var i = 1; i < 9; i++) { | |
if(usedNumbers.indexOf(i) < 0) { | |
possibleNumbers.push(i); | |
} | |
} | |
return this.possibleCombinationSum(possibleNumbers, numberOfStars); | |
}, | |
updateDoneStatus: function() { | |
var usedNumbers = this.state.usedNumbers; | |
if(usedNumbers.length === 9) { | |
this.setState({ | |
doneStatus: "Nice! you win." | |
}); | |
return; | |
} | |
if(this.state.redraws === 0 && !this.possibleSolutions()) { | |
this.setState({ | |
doneStatus: "Game Over!" | |
}); | |
} | |
}, | |
render: function() { | |
var selectedNumbers = this.state.selectedNumbers, | |
numberOfStars = this.state.numberOfStars, | |
correct = this.state.correct, | |
redraws = this.state.redraws, | |
doneStatus = this.state.doneStatus, | |
usedNumbers = this.state.usedNumbers, | |
bottomFrame; | |
if(doneStatus) { | |
bottomFrame = React.createElement(DoneFrame, {doneStatus: doneStatus, | |
restartGame: this.restartGame}) | |
} else { | |
bottomFrame = React.createElement(NumbersFrame, {selectedNumbers: selectedNumbers, | |
selectedNumber: this.selectedNumber, | |
usedNumbers: usedNumbers}) | |
} | |
return ( | |
React.createElement("div", {id: "game"}, | |
React.createElement("h1", null, "Play Nine"), | |
React.createElement("hr", null), | |
React.createElement("div", {className: "clearfix"}, | |
React.createElement(StarsFrame, {numberOfStars: numberOfStars}), | |
React.createElement(ButtonFrame, {selectedNumbers: selectedNumbers, | |
correct: correct, | |
checkAnswer: this.checkAnswer, | |
acceptAnswer: this.acceptAnswer, | |
redraw: this.redraw, | |
redraws: redraws} | |
), | |
React.createElement(AnswerFrame, {selectedNumbers: selectedNumbers, | |
unselectedNumber: this.unselectedNumber}) | |
), | |
bottomFrame | |
) | |
) | |
} | |
}); | |
React.render(React.createElement(Game, null), | |
document.getElementById("root") | |
); | |
</script> | |
<script id="jsbin-source-css" type="text/css">#stars-frame, #answer-frame { | |
width: 40%; | |
float: left; | |
} | |
#stars-frame .glyphicon { | |
margin: 0.3em; | |
font-size: 1.74em; | |
} | |
#button-frame { | |
width: 20%; | |
float: left; | |
text-align: center; | |
margin-top: 50px; | |
} | |
#stars-frame .well, #answer-frame .well { | |
height: 150px; | |
} | |
#numbers-frame .number, #answer-frame .well span { | |
display: inline-block; | |
margin: 0.5em; | |
background-color: #bbb; | |
width: 30px; | |
text-align: center; | |
font-size: 22px; | |
border-radius: 50%; | |
cursor: pointer; | |
} | |
#numbers-frame .selected-true { | |
background-color: #e8e8e8; | |
color: #ddd; | |
cursor: not-allowed; | |
} | |
#numbers-frame .used-true { | |
background-color: #aaddaa; | |
color: #33aa33; | |
}</script> | |
<script id="jsbin-source-javascript" type="text/javascript">var StarsFrame = React.createClass({ | |
render: function(){ | |
var stars = []; | |
for ( var i = 0; i < this.props.numberOfStars; i++ ) { | |
stars.push( | |
<span className="glyphicon glyphicon-star"></span> | |
); | |
} | |
return ( | |
<div id="stars-frame"> | |
<div className="well"> | |
{stars} | |
</div> | |
</div> | |
); | |
} | |
}); | |
var ButtonFrame = React.createClass({ | |
render: function(){ | |
var e = "=", | |
correct = this.props.correct, | |
button, | |
redrawDisabled = (this.props.redraws === 0), | |
disabled; | |
switch(correct) { | |
case true: | |
button = ( | |
<button className="btn btn-success btn-lg" onClick={this.props.acceptAnswer}> | |
<span className="glyphicon glyphicon-ok"></span> | |
</button> | |
); | |
break; | |
case false: | |
button = ( | |
<button className="btn btn-danger btn-lg"> | |
<span className="glyphicon glyphicon-remove"></span> | |
</button> | |
); | |
break; | |
default: | |
disabled = (this.props.selectedNumbers.length === 0), | |
button = ( | |
<button className="btn btn-primary btn-lg" disabled={disabled} | |
onClick={this.props.checkAnswer}> | |
{e} | |
</button> | |
); | |
} | |
return ( | |
<div id="button-frame"> | |
{button} | |
<br/><br/> | |
<button className="btn btn-warning btn-xs" onClick={this.props.redraw} disabled={redrawDisabled}> | |
<span className="glyphicon glyphicon-refresh"></span> | |
| |
{this.props.redraws} | |
</button> | |
</div> | |
); | |
} | |
}); | |
var AnswerFrame = React.createClass({ | |
render: function(){ | |
var props = this.props; | |
var selectedNumbers = props.selectedNumbers.map(function(i){ | |
return ( | |
<span onClick={props.unselectedNumber.bind(null, i)}> | |
{i} | |
</span> | |
) | |
}); | |
return ( | |
<div id="answer-frame"> | |
<div className="well"> | |
{selectedNumbers} | |
</div> | |
</div> | |
); | |
} | |
}); | |
var NumbersFrame = React.createClass({ | |
render: function () { | |
var numbers = [], | |
className, | |
selectedNumber = this.props.selectedNumber, | |
selectedNumbers = this.props.selectedNumbers, | |
usedNumbers = this.props.usedNumbers; | |
for (var i = 1; i<=9; i++) { | |
className = "number selected-" + (selectedNumbers.indexOf(i) >= 0); | |
className += " used-" + (usedNumbers.indexOf(i) >= 0); | |
numbers.push( | |
<div className={className} onClick={selectedNumber.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-primary" onClick={this.props.restartGame}> | |
Play again | |
</button> | |
</div> | |
); | |
} | |
}); | |
var Game = React.createClass({ | |
getInitialState: function() { | |
return { | |
selectedNumbers: [], | |
numberOfStars: this.randomNumber(), | |
correct: null, | |
redraws: 5, | |
usedNumbers: [], | |
doneStatus: null | |
}; | |
}, | |
randomNumber: function() { | |
return Math.floor(Math.random() * 9) + 1; | |
}, | |
selectedNumber: function(clickedNumber) { | |
var selectedNumbers = this.state.selectedNumbers.concat(clickedNumber); | |
if(this.state.selectedNumbers.indexOf(clickedNumber) < 0) { | |
this.setState({ | |
selectedNumbers: selectedNumbers, | |
correct: null | |
}); | |
} | |
}, | |
unselectedNumber: function(clickedNumber) { | |
var selectedNumbers = this.state.selectedNumbers; | |
var indexOfNumber = selectedNumbers.indexOf(clickedNumber); | |
selectedNumbers.splice(indexOfNumber, 1); | |
this.setState({ | |
selectedNumbers: selectedNumbers, | |
correct: null | |
}); | |
}, | |
restartGame: function() { | |
this.replaceState(this.getInitialState()); | |
}, | |
sumOfSelectedNumbers: function() { | |
return this.state.selectedNumbers.reduce(function(p,n){ | |
return p+n; | |
}, 0); | |
}, | |
checkAnswer: function() { | |
var correct = (this.state.numberOfStars === this.sumOfSelectedNumbers()); | |
this.setState({ | |
correct: correct | |
}); | |
}, | |
acceptAnswer: function() { | |
// Build this out | |
var usedNumbers = this.state.usedNumbers.concat(this.state.selectedNumbers); | |
this.setState({ | |
selectedNumbers: [], | |
usedNumbers: usedNumbers, | |
correct: null, | |
numberOfStars: this.randomNumber() | |
}, function() { | |
this.updateDoneStatus(); | |
}); | |
}, | |
redraw: function() { | |
if(this.state.redraws > 0) { | |
this.setState({ | |
numberOfStars: this.randomNumber(), | |
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() { | |
var usedNumbers = this.state.usedNumbers, | |
possibleNumbers = [], | |
numberOfStars = this.state.numberOfStars; | |
for (var i = 1; i < 9; i++) { | |
if(usedNumbers.indexOf(i) < 0) { | |
possibleNumbers.push(i); | |
} | |
} | |
return this.possibleCombinationSum(possibleNumbers, numberOfStars); | |
}, | |
updateDoneStatus: function() { | |
var usedNumbers = this.state.usedNumbers; | |
if(usedNumbers.length === 9) { | |
this.setState({ | |
doneStatus: "Nice! you win." | |
}); | |
return; | |
} | |
if(this.state.redraws === 0 && !this.possibleSolutions()) { | |
this.setState({ | |
doneStatus: "Game Over!" | |
}); | |
} | |
}, | |
render: function() { | |
var selectedNumbers = this.state.selectedNumbers, | |
numberOfStars = this.state.numberOfStars, | |
correct = this.state.correct, | |
redraws = this.state.redraws, | |
doneStatus = this.state.doneStatus, | |
usedNumbers = this.state.usedNumbers, | |
bottomFrame; | |
if(doneStatus) { | |
bottomFrame = <DoneFrame doneStatus={doneStatus} | |
restartGame={this.restartGame}/> | |
} else { | |
bottomFrame = <NumbersFrame selectedNumbers={selectedNumbers} | |
selectedNumber={this.selectedNumber} | |
usedNumbers={usedNumbers}/> | |
} | |
return ( | |
<div id="game"> | |
<h1>Play Nine</h1> | |
<hr/> | |
<div className="clearfix"> | |
<StarsFrame numberOfStars={numberOfStars} /> | |
<ButtonFrame selectedNumbers={selectedNumbers} | |
correct={correct} | |
checkAnswer={this.checkAnswer} | |
acceptAnswer={this.acceptAnswer} | |
redraw={this.redraw} | |
redraws={redraws} | |
/> | |
<AnswerFrame selectedNumbers={selectedNumbers} | |
unselectedNumber={this.unselectedNumber} /> | |
</div> | |
{bottomFrame} | |
</div> | |
) | |
} | |
}); | |
React.render(<Game />, | |
document.getElementById("root") | |
);</script></body> | |
</html> |
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
#stars-frame, #answer-frame { | |
width: 40%; | |
float: left; | |
} | |
#stars-frame .glyphicon { | |
margin: 0.3em; | |
font-size: 1.74em; | |
} | |
#button-frame { | |
width: 20%; | |
float: left; | |
text-align: center; | |
margin-top: 50px; | |
} | |
#stars-frame .well, #answer-frame .well { | |
height: 150px; | |
} | |
#numbers-frame .number, #answer-frame .well span { | |
display: inline-block; | |
margin: 0.5em; | |
background-color: #bbb; | |
width: 30px; | |
text-align: center; | |
font-size: 22px; | |
border-radius: 50%; | |
cursor: pointer; | |
} | |
#numbers-frame .selected-true { | |
background-color: #e8e8e8; | |
color: #ddd; | |
cursor: not-allowed; | |
} | |
#numbers-frame .used-true { | |
background-color: #aaddaa; | |
color: #33aa33; | |
} |
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({displayName: 'StarsFrame', | |
render: function(){ | |
var stars = []; | |
for ( var i = 0; i < this.props.numberOfStars; i++ ) { | |
stars.push( | |
React.createElement("span", {className: "glyphicon glyphicon-star"}) | |
); | |
} | |
return ( | |
React.createElement("div", {id: "stars-frame"}, | |
React.createElement("div", {className: "well"}, | |
stars | |
) | |
) | |
); | |
} | |
}); | |
var ButtonFrame = React.createClass({displayName: 'ButtonFrame', | |
render: function(){ | |
var e = "=", | |
correct = this.props.correct, | |
button, | |
redrawDisabled = (this.props.redraws === 0), | |
disabled; | |
switch(correct) { | |
case true: | |
button = ( | |
React.createElement("button", {className: "btn btn-success btn-lg", onClick: this.props.acceptAnswer}, | |
React.createElement("span", {className: "glyphicon glyphicon-ok"}) | |
) | |
); | |
break; | |
case false: | |
button = ( | |
React.createElement("button", {className: "btn btn-danger btn-lg"}, | |
React.createElement("span", {className: "glyphicon glyphicon-remove"}) | |
) | |
); | |
break; | |
default: | |
disabled = (this.props.selectedNumbers.length === 0), | |
button = ( | |
React.createElement("button", {className: "btn btn-primary btn-lg", disabled: disabled, | |
onClick: this.props.checkAnswer}, | |
e | |
) | |
); | |
} | |
return ( | |
React.createElement("div", {id: "button-frame"}, | |
button, | |
React.createElement("br", null), React.createElement("br", null), | |
React.createElement("button", {className: "btn btn-warning btn-xs", onClick: this.props.redraw, disabled: redrawDisabled}, | |
React.createElement("span", {className: "glyphicon glyphicon-refresh"}), | |
" ", | |
this.props.redraws | |
) | |
) | |
); | |
} | |
}); | |
var AnswerFrame = React.createClass({displayName: 'AnswerFrame', | |
render: function(){ | |
var props = this.props; | |
var selectedNumbers = props.selectedNumbers.map(function(i){ | |
return ( | |
React.createElement("span", {onClick: props.unselectedNumber.bind(null, i)}, | |
i | |
) | |
) | |
}); | |
return ( | |
React.createElement("div", {id: "answer-frame"}, | |
React.createElement("div", {className: "well"}, | |
selectedNumbers | |
) | |
) | |
); | |
} | |
}); | |
var NumbersFrame = React.createClass({displayName: 'NumbersFrame', | |
render: function () { | |
var numbers = [], | |
className, | |
selectedNumber = this.props.selectedNumber, | |
selectedNumbers = this.props.selectedNumbers, | |
usedNumbers = this.props.usedNumbers; | |
for (var i = 1; i<=9; i++) { | |
className = "number selected-" + (selectedNumbers.indexOf(i) >= 0); | |
className += " used-" + (usedNumbers.indexOf(i) >= 0); | |
numbers.push( | |
React.createElement("div", {className: className, onClick: selectedNumber.bind(null, i)}, i) | |
); | |
} | |
return ( | |
React.createElement("div", {id: "numbers-frame"}, | |
React.createElement("div", {className: "well"}, | |
numbers | |
) | |
) | |
); | |
} | |
}); | |
var DoneFrame = React.createClass({displayName: 'DoneFrame', | |
render: function() { | |
return ( | |
React.createElement("div", {className: "well text-center"}, | |
React.createElement("h2", null, this.props.doneStatus), | |
React.createElement("button", {className: "btn btn-primary", onClick: this.props.restartGame}, | |
"Play again" | |
) | |
) | |
); | |
} | |
}); | |
var Game = React.createClass({displayName: 'Game', | |
getInitialState: function() { | |
return { | |
selectedNumbers: [], | |
numberOfStars: this.randomNumber(), | |
correct: null, | |
redraws: 5, | |
usedNumbers: [], | |
doneStatus: null | |
}; | |
}, | |
randomNumber: function() { | |
return Math.floor(Math.random() * 9) + 1; | |
}, | |
selectedNumber: function(clickedNumber) { | |
var selectedNumbers = this.state.selectedNumbers.concat(clickedNumber); | |
if(this.state.selectedNumbers.indexOf(clickedNumber) < 0) { | |
this.setState({ | |
selectedNumbers: selectedNumbers, | |
correct: null | |
}); | |
} | |
}, | |
unselectedNumber: function(clickedNumber) { | |
var selectedNumbers = this.state.selectedNumbers; | |
var indexOfNumber = selectedNumbers.indexOf(clickedNumber); | |
selectedNumbers.splice(indexOfNumber, 1); | |
this.setState({ | |
selectedNumbers: selectedNumbers, | |
correct: null | |
}); | |
}, | |
restartGame: function() { | |
this.replaceState(this.getInitialState()); | |
}, | |
sumOfSelectedNumbers: function() { | |
return this.state.selectedNumbers.reduce(function(p,n){ | |
return p+n; | |
}, 0); | |
}, | |
checkAnswer: function() { | |
var correct = (this.state.numberOfStars === this.sumOfSelectedNumbers()); | |
this.setState({ | |
correct: correct | |
}); | |
}, | |
acceptAnswer: function() { | |
// Build this out | |
var usedNumbers = this.state.usedNumbers.concat(this.state.selectedNumbers); | |
this.setState({ | |
selectedNumbers: [], | |
usedNumbers: usedNumbers, | |
correct: null, | |
numberOfStars: this.randomNumber() | |
}, function() { | |
this.updateDoneStatus(); | |
}); | |
}, | |
redraw: function() { | |
if(this.state.redraws > 0) { | |
this.setState({ | |
numberOfStars: this.randomNumber(), | |
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() { | |
var usedNumbers = this.state.usedNumbers, | |
possibleNumbers = [], | |
numberOfStars = this.state.numberOfStars; | |
for (var i = 1; i < 9; i++) { | |
if(usedNumbers.indexOf(i) < 0) { | |
possibleNumbers.push(i); | |
} | |
} | |
return this.possibleCombinationSum(possibleNumbers, numberOfStars); | |
}, | |
updateDoneStatus: function() { | |
var usedNumbers = this.state.usedNumbers; | |
if(usedNumbers.length === 9) { | |
this.setState({ | |
doneStatus: "Nice! you win." | |
}); | |
return; | |
} | |
if(this.state.redraws === 0 && !this.possibleSolutions()) { | |
this.setState({ | |
doneStatus: "Game Over!" | |
}); | |
} | |
}, | |
render: function() { | |
var selectedNumbers = this.state.selectedNumbers, | |
numberOfStars = this.state.numberOfStars, | |
correct = this.state.correct, | |
redraws = this.state.redraws, | |
doneStatus = this.state.doneStatus, | |
usedNumbers = this.state.usedNumbers, | |
bottomFrame; | |
if(doneStatus) { | |
bottomFrame = React.createElement(DoneFrame, {doneStatus: doneStatus, | |
restartGame: this.restartGame}) | |
} else { | |
bottomFrame = React.createElement(NumbersFrame, {selectedNumbers: selectedNumbers, | |
selectedNumber: this.selectedNumber, | |
usedNumbers: usedNumbers}) | |
} | |
return ( | |
React.createElement("div", {id: "game"}, | |
React.createElement("h1", null, "Play Nine"), | |
React.createElement("hr", null), | |
React.createElement("div", {className: "clearfix"}, | |
React.createElement(StarsFrame, {numberOfStars: numberOfStars}), | |
React.createElement(ButtonFrame, {selectedNumbers: selectedNumbers, | |
correct: correct, | |
checkAnswer: this.checkAnswer, | |
acceptAnswer: this.acceptAnswer, | |
redraw: this.redraw, | |
redraws: redraws} | |
), | |
React.createElement(AnswerFrame, {selectedNumbers: selectedNumbers, | |
unselectedNumber: this.unselectedNumber}) | |
), | |
bottomFrame | |
) | |
) | |
} | |
}); | |
React.render(React.createElement(Game, null), | |
document.getElementById("root") | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment