Skip to content

Instantly share code, notes, and snippets.

@niquepa
Created August 3, 2017 21:27
Show Gist options
  • Save niquepa/7fd7ec9d12595b409cbbb017ba5578ac to your computer and use it in GitHub Desktop.
Save niquepa/7fd7ec9d12595b409cbbb017ba5578ac to your computer and use it in GitHub Desktop.
React tutorial - play nine game
var 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;
};
const Stars = (props) => {
return(
<div className='col-5'>
{_.range(props.numberOfStars).map(i =>
<i key={i} className='fa fa-star'></i>
)}
</div>
);
}
const Button = (props) => {
let button;
switch(props.answerIsCorrect) {
case true:
button = <button className="btn btn-success" onClick={props.acceptAnswer} >
<i className="fa fa-check"></i>
</button>;
break;
case false:
button = <button className="btn btn-danger" >
<i className="fa fa-times"></i>
</button>;
break;
default:
button = <button className="btn" disabled={props.selectedNumbers.length === 0}
onClick={props.checkAnswer}>
=
</button>;
break;
}
let reDrawButton;
reDrawButton = <button className="btn btn-warning" onClick={props.reDraw} disabled={props.reDraws <= 0}>
<i className="fa fa-refresh"></i> {props.reDraws}
</button>
return(
<div className='col-2 text-center'>
{button}
<br /><br />
{reDrawButton}
</div>
);
}
const Answer = (props) => {
return(
<div className='col-5'>
{props.selectedNumbers.map((number,i) =>
<span key={i} onClick={() => props.unSelectNumber(number)}>{number}</span>
)}
</div>
);
}
const Numbers = (props) => {
const numberClassName = (number) => {
if(props.selectedNumbers.indexOf(number) >= 0) {
return 'selected';
}
if(props.usedNumbers.indexOf(number) >= 0) {
return 'used';
}
}
return(
<div className='card text-center'>
<div>
{Numbers.list.map((number,i) =>
<span key={i}
className={numberClassName(number)}
onClick={() => props.selectNumber(number)}>
{number}
</span>
)}
</div>
</div>
);
}
Numbers.list = _.range(1,10);
const DoneFrame = (props) => {
return(
<div className="text-center">
<h3>{props.doneStatus}</h3>
<button onClick={props.resetGame}>Play Again!</button>
</div>
);
};
class Game extends React.Component {
static randomNumber = () => 1+Math.floor(Math.random()*9);
static initialState = () => ({
selectedNumbers: [],
randomNumberOfStars: Game.randomNumber(),
answerIsCorrect: null,
usedNumbers: [],
reDraws: 5,
doneStatus: null,
});
state = Game.initialState();
resetGame = () => this.setState(Game.initialState());
selectNumber = (clickedNumber) => {
if (this.state.selectedNumbers.indexOf(clickedNumber) < 0 && this.state.usedNumbers.indexOf(clickedNumber) < 0) {
this.setState(prevState => ({
answerIsCorrect: null,
selectedNumbers: prevState.selectedNumbers.concat(clickedNumber)
}));
}
};
unSelectNumber = (clickedNumber) => {
this.setState(prevState => ({
answerIsCorrect: null,
selectedNumbers: prevState.selectedNumbers.
filter(number => number !== clickedNumber)
}));
};
checkAnswer = () => {
this.setState(prevState => ({
answerIsCorrect: prevState.randomNumberOfStars ===
prevState.selectedNumbers.reduce((acc, n) => acc+n, 0)
}));
};
acceptAnswer = () => {
this.setState(prevState => ({
usedNumbers: prevState.usedNumbers.concat(prevState.selectedNumbers),
selectedNumbers: [],
answerIsCorrect: null,
randomNumberOfStars: Game.randomNumber(),
}), this.updateDoneStatus);
};
reDraw = () => {
if(this.state.reDraws === 0) {return;}
this.setState(prevState => ({
selectedNumbers: [],
answerIsCorrect: null,
randomNumberOfStars: Game.randomNumber(),
reDraws: prevState.reDraws - 1
}), this.updateDoneStatus);
};
possibleSolutions = ({randomNumberOfStars, usedNumbers}) => {
const possibleNumbers = _.range(1,10).filter(number => usedNumbers.indexOf(number) === -1);
return possibleCombinationSum(possibleNumbers, randomNumberOfStars);
};
updateDoneStatus = () => {
this.setState(prevState => {
if(prevState.usedNumbers.lenght === 9) {
return {doneStatus: "Well done!"};
}
if(prevState.reDraws === 0 && !this.possibleSolutions(prevState)) {
return {doneStatus: "Game Over!"};
}
});
};
render() {
const {randomNumberOfStars, selectedNumbers} = this.state;
return(
<div className='container'>
<h3>Play nine</h3>
<hr />
<div className='row'>
<Stars numberOfStars={randomNumberOfStars}/>
<Button selectedNumbers={selectedNumbers}
checkAnswer={this.checkAnswer}
answerIsCorrect={this.state.answerIsCorrect}
acceptAnswer={this.acceptAnswer}
reDraw={this.reDraw}
reDraws={this.state.reDraws}/>
<Answer selectedNumbers={selectedNumbers} unSelectNumber={this.unSelectNumber}/>
</div>
<br />
{this.state.doneStatus ?
<DoneFrame resetGame={this.resetGame} doneStatus={this.state.doneStatus} /> :
<Numbers selectedNumbers={selectedNumbers} selectNumber={this.selectNumber} usedNumbers={this.state.usedNumbers}/>
}
</div>
);
}
}
class App extends React.Component {
render() {
return(
<div>
<Game />
</div>);
}
}
ReactDOM.render(<App />,mountNode);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment