This is a solution to the Rock, Paper, Scissors challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.
β‘οΈ Frontend Mentor Projects: https://github.com/anushkachauhxn/frontend-mentor-projects
-
Your challenge is to build out this Rock, Paper, Scissors game and get it looking as close to the design as possible.
-
Your users should be able to:
- βοΈ View the optimal layout for the game depending on their device's screen size
- βοΈ Play Rock, Paper, Scissors against the computer
- βοΈ Maintain the state of the score after refreshing the browser (optional)
- βοΈ Bonus: Play Rock, Paper, Scissors, Lizard, Spock against the computer (optional)
- React JS
- React Router
- Redux
- Material UI
- CSS custom properties
The all CSS winner animation!
/* Animation On Result */
.game__side button {
position: relative;
}
.game__side button::before,
.game__side button::after {
content: "";
position: absolute;
z-index: -1;
border-radius: 50%;
animation: ripple 0.75s cubic-bezier(0.65, 0, 0.34, 1) 0s 1;
}
.game__side button::before {
height: calc(332px * 1.75);
width: calc(332px * 1.75);
border: 84px solid hsl(223, 44%, 21%); /* Outer Ring */
}
.game__side button::after {
height: calc(332px * 1.28);
width: calc(332px * 1.28);
background: hsl(224, 33%, 28%); /* Inner Ring */
border: 78px solid hsl(223, 39%, 24%); /* Middle Ring */
}
@keyframes ripple {
from {
transform: scale3d(0, 0, 1);
}
to {
transform: scale3d(1, 1, 1);
}
}
The whole Redux store structure and the actions have to be precise. The timing for calling the functions should be well thought.
gameSlice.js :
const winners = [
// winners[userVal] = [compVals that make user win]
[2, 3],
[0, 4],
[1, 3],
[1, 4],
[0, 2],
];
export const gameSlice = createSlice({
name: "game",
initialState: {
userVal: null,
compVal: -1,
result: null,
score: 0,
},
reducers: {
setUserVal: (state, action) => {
state.userVal = action.payload;
},
setCompVal: (state) => {
let res = Math.floor(Math.random() * 5);
for (let i = 1; res === state.userVal; i++) {
// To avoid draws
res = Math.floor(Math.random() * 5);
if (i > 5) {
alert("Something went wrong.");
break;
}
}
state.compVal = res;
},
calculateResult: (state) => {
const compVals = winners[state.userVal];
if (compVals.includes(state.compVal)) {
state.result = 1; // user wins
} else {
state.result = -1; // comp wins
}
},
updateScore: (state) => {
state.score = parseInt(state.score);
state.score += parseInt(state.result);
if (state.score < 0) {
state.score = 0;
}
sessionStorage.setItem("score", state.score);
},
setScore: (state) => {
// Getting the score after page has been refreshed
state.score = sessionStorage.getItem("score") || 0;
},
resetGame: (state) => {
state.userVal = null;
state.compVal = -1;
state.result = null;
},
},
});
Main.js :
const openGame = (usersPick) => {
dispatch(setUserVal(usersPick));
setTimeout(() => {
dispatch(setCompVal());
setTimeout(() => {
dispatch(calculateResult());
dispatch(updateScore());
}, 500);
}, 1000);
history.push("/game");
};
-
GitHub - @anushkachauhxn
-
Behance - @anushka_creates
-
LinkedIn - @anushka-chauhan
-
Twitter - @anushka_creates