DEV Community

Cover image for Building a Joke guesser game in React
vigneshiyergithub
vigneshiyergithub

Posted on

1

Building a Joke guesser game in React

What is this post about ?

Hello fellow humanoids. Today we will build a Joke guesser game and cover some basic concepts of making API calls and other react concepts.
Check out the game here : Joke Guesser Game
Github repo for reference : Repo Link

Content

  • How to create a game ?
  • How to use Joke API for game ?
  • How to do scoring ?

Lets go deep dive into each one and explore how it was implemented.

How to create a game

The game we are creating today will be a joke guesser game.
It will be comprised of 2 part Joke. The first part will set the premise for the joke and the gamer will enter the probable second part of the joke and will be scored according to the string similarity. The complete game is comprised of 10 rounds.
Game UI

import React, { Fragment, useEffect, useState } from "react";
import { JokeDisplayer } from "./JokeDisplayer";
import { JokeTypeDisplayer } from "./JokeTypeDisplayer";
import { Block, Container, Col } from "./common";
export const JokeTextContent = React.createContext();
const GAME_PAGE_LIMIT = 10;
export const Game = (props) => {
const [counter, setCounter] = useState(0);
const [display, setDisplay] = useState(false);
const [score, setScore] = useState([]);
const [jokeText, setJokeText] = useState("");
const incrementCounter = () => {
setCounter(counter + 1);
setDisplay(false);
setTimeout(() => {
setDisplay(true);
}, 1000);
};
const resetState = () => {
setCounter(0);
setScore([]);
};
const onSave = (levelScore) => {
const arr = [...score, levelScore];
setScore(arr);
};
const average = (nums) => {
return nums.length > 0 ? nums.reduce((a, b) => a + b) / nums.length : 0;
};
return (
<Container>
<Block height={"5rem"} />
<Col>
<Block height={"1rem"}>
Game Page <br /> {counter}/{GAME_PAGE_LIMIT}
</Block>
<Block height={"1rem"}>Total Score <br/> {average(score)}</Block>
</Col>
<Container
height={"70vh"}
marginTop={"2rem"}
border
marginHorizontal
noHeight
>
{counter === 0 && (
<Block marginTop={"2rem"} paddingLeft={"30%"} paddingRight={"30%"}>
<button onClick={incrementCounter}>Start Game</button>
</Block>
)}
{counter !== 0 && counter < GAME_PAGE_LIMIT && (
<Fragment>
{display && (
<JokeTextContent.Provider value={setJokeText}>
<JokeContainer onSave={onSave} />
</JokeTextContent.Provider>
)}
<Block
marginBottom={"2rem"}
paddingLeft={"30%"}
paddingRight={"30%"}
>
<button disabled={!jokeText} onClick={incrementCounter}>
Next
</button>
</Block>
</Fragment>
)}
{counter === GAME_PAGE_LIMIT && (
<Container
height="5rem"
marginTop="2rem"
paddingLeft="30%"
paddingRight="30%"
textAlign="left"
>
<Block>Total Score - {average(score)}</Block>
<Block>
<button onClick={resetState}>New Game</button>
</Block>
</Container>
)}
</Container>
</Container>
);
};
const JokeContainer = (props) => {
const [jokeType, setJokeType] = useState(null);
return (
<Fragment>
<JokeTypeDisplayer jokeType={jokeType} setJokeType={setJokeType} />
{jokeType && <JokeDisplayer jokeType={jokeType} onSave={props.onSave} />}
</Fragment>
);
};
view raw Game.js hosted with ❤ by GitHub

How to use Joke API for game ?

For the game in context we would query a Joke API endpoint to fetch the joke for the round. The joke will be a bi-parted joke which we would use to form Question for the joke and use the second part for the text similarity score.

import React, { Fragment, useEffect, useState } from "react";
import styled from "styled-components";
import stringSimilarity from "string-similarity";
import { Container, Block } from "./common";
import {JokeTextContent} from './Game'
const JokeContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: ${(props) => (props.marginHorizontal ? "30%" : "0")};
margin-right: ${(props) => (props.marginHorizontal ? "30%" : "0")};
`;
const EmptyBlock = styled.div`
height: 5rem;
`;
const Input = styled.input``;
const jokeURL = "https://sv443.net/jokeapi/v2/joke/";
export const JokeDisplayer = (props) => {
const [firstPartJoke, setFirstPartJoke] = useState("");
const [secondPartJoke, setSecondPartJoke] = useState("");
useEffect(() => {
fetch(jokeURL + `${props.jokeType}?type=twopart`)
.then((data) => data.json())
.then(({ setup, delivery }) => {
if (setup && delivery) {
setFirstPartJoke(setup);
setSecondPartJoke(delivery);
}
});
}, []);
return (
<JokeContainer marginHorizontal={true}>
<FirstPartJoke joke={firstPartJoke} />
<EmptyBlock />
<JokeGuesser joke={secondPartJoke} onSave={props.onSave} />
</JokeContainer>
);
};
const FirstPartJoke = (props) => {
return <div>Premise : {props.joke}</div>;
};
const JokeGuesser = (props) => {
const [text, setText] = useState("");
const [score, setScore] = useState(null);
const [showSection, setShowSection] = useState(false);
useEffect(() => {
setScore(stringSimilarity.compareTwoStrings(text, props.joke));
}, [text, props.joke]);
const buttonClick = (e) => {
setShowSection(true);
props.onSave(score);
};
const style = {
// width: "20rem",
// marginRight: "2rem",
};
return (
<JokeTextContent.Consumer>
{( value ) => (
<Container>
<Block
justifyContent={"space-between"}
height={'5rem'}
>
<Input
value={text}
style={style}
onChange={(e) => {
setText(e.target.value);
value(e.target.value);
}}
type="text"
/>
<button onClick={buttonClick} disabled={showSection}>Check</button>
</Block>
{showSection && (
<Container height={'5rem'} marginTop="1rem" textAlign="left">
<Block>Score : {score}</Block>
<Block>Actual Answer : {props.joke}</Block>
</Container>
)}
</Container>
)}
</JokeTextContent.Consumer>
);
};

How to do scoring ?

Once the gamer has entered his guess for scoring with the original joke we would be using Text Similarity.
For text similarity we would be using "string-similarity" npm package.

Conclusion

This game is not developed to it's entirety and has room for improvement. Please feel free to fork the repo and make changes as you please. Do let me know if I made any grave blunders in coding this. Thanks for reading this post.
Stay safe and lend a hand to another :)

Top comments (0)

Cloudinary image

Optimize, customize, deliver, manage and analyze your images.

Remove background in all your web images at the same time, use outpainting to expand images with matching content, remove objects via open-set object detection and fill, recolor, crop, resize... Discover these and hundreds more ways to manage your web images and videos on a scale.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay