Skip to content

Commit 1be6b3e

Browse files
committed
Do flag guessing exercise
1 parent 5fa194f commit 1be6b3e

File tree

6 files changed

+204
-27
lines changed

6 files changed

+204
-27
lines changed

Section29-Component-LifeCycle-Methods/flag-guessing-game/package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Section29-Component-LifeCycle-Methods/flag-guessing-game/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
"dependencies": {
66
"react": "^16.4.1",
77
"react-dom": "^16.4.1",
8-
"react-scripts": "1.1.4"
8+
"react-scripts": "1.1.4",
9+
"shuffle-array": "^1.0.1"
910
},
1011
"scripts": {
1112
"start": "react-scripts start",
1213
"build": "react-scripts build",
1314
"test": "react-scripts test --env=jsdom",
1415
"eject": "react-scripts eject"
1516
}
16-
}
17+
}
Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
1-
.App {
2-
text-align: center;
1+
body{
2+
background-color: #ccc;
33
}
44

5-
.App-logo {
6-
animation: App-logo-spin infinite 20s linear;
7-
height: 80px;
5+
.container {
6+
margin: 20px auto;
7+
display: flex;
8+
justify-content: space-around;
89
}
910

10-
.App-header {
11-
background-color: #222;
12-
height: 150px;
13-
padding: 20px;
14-
color: white;
11+
img {
12+
max-width: 550px;
13+
max-height: 250px;
14+
box-shadow: 1px 1px #ccc;
1515
}
1616

17-
.App-title {
18-
font-size: 1.5em;
17+
li{
18+
list-style: none;
19+
}
20+
21+
label{
22+
display: inline-block;
23+
margin-right: 20px;
24+
margin-top: 20px;
1925
}
2026

21-
.App-intro {
22-
font-size: large;
27+
button{
28+
display: block;
2329
}
2430

25-
@keyframes App-logo-spin {
26-
from { transform: rotate(0deg); }
27-
to { transform: rotate(360deg); }
31+
.options {
32+
margin: 10px;
2833
}
34+
35+
.result{
36+
margin: 20px 0;
37+
font-size: 1.5em;
38+
}

Section29-Component-LifeCycle-Methods/flag-guessing-game/src/App.js

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,111 @@
11
import React, { Component } from 'react';
2-
import logo from './logo.svg';
32
import './App.css';
3+
import shuffle from "shuffle-array";
4+
import Navbar from "./Navbar";
45

56
class App extends Component {
7+
constructor(props){
8+
super(props);
9+
this.state = {
10+
countries: [],
11+
flag:"",
12+
name: "",
13+
options: [],
14+
result : "",
15+
disabled: false,
16+
newGame: false,
17+
};
18+
this.handleCheck = this.handleCheck.bind(this);
19+
this.handleNewGame = this.handleNewGame.bind(this);
20+
}
21+
componentDidMount(){
22+
const countriesUrl = "https://restcountries.eu/rest/v2/all";
23+
fetch(countriesUrl)
24+
.then(d=>d.json())
25+
.then(countries => {
26+
let country = this.generateRandomCountries(countries);
27+
let flag = country.flag;
28+
let name = country.name;
29+
let options = country.options;
30+
this.setState({countries,flag,name,options});
31+
});
32+
}
33+
generateRandomCountries(countries){
34+
const len = countries.length;
35+
36+
let randomCountries = Array.from(new Set([Math.floor(Math.random()*len),Math.floor(Math.random()*len),Math.floor(Math.random()*len),Math.floor(Math.random()*len)]));
37+
38+
while(randomCountries.length<4){
39+
randomCountries = Array.from(new Set([Math.floor(Math.random()*len),Math.floor(Math.random()*len),Math.floor(Math.random()*len),Math.floor(Math.random()*len)]));
40+
};
41+
42+
let choices = [countries[randomCountries[0]],countries[randomCountries[1]],countries[randomCountries[2]],countries[randomCountries[3]]];
43+
let options = choices.map(c => c.name);
44+
let rightIndex = Math.floor(Math.random()*choices.length);
45+
let rightCountry = choices[rightIndex];
46+
let name = rightCountry.name;
47+
let flag = rightCountry.flag;
48+
49+
return {flag,name,options};
50+
}
51+
handleCheck(e){
52+
let result;
53+
let disabled = true;
54+
let newGame = true;
55+
e.target.value === this.state.name?result ="Correct!":result="Wrong. The right answer is "+this.state.name;
56+
this.setState({...this.state,result,disabled,newGame});
57+
console.log(e.target.checked)
58+
}
59+
60+
handleNewGame(e){
61+
let newGame = false;
62+
let result = "";
63+
let disabled = false;
64+
let countries = shuffle([...this.state.countries]);
65+
let country = this.generateRandomCountries(countries);
66+
let flag = country.flag;
67+
let name = country.name;
68+
let options = country.options;
69+
let inputs = Array.from(document.querySelectorAll("input"));
70+
inputs.forEach(i=>{
71+
if(i.checked) i.checked = false;
72+
})
73+
74+
this.setState({flag,name,options,newGame,result,disabled,countries});
75+
}
76+
677
render() {
78+
let views = <div>Loading...</div>;
79+
let next = <button onClick={this.handleNewGame}>New Game</button>;
80+
const flag = this.state.flag;
81+
82+
const selections = <div className="options">
83+
<ul>
84+
{this.state.options.map((c,i)=>(
85+
<li key={i}><label><input
86+
type="radio"
87+
name="country"
88+
value={c}
89+
onClick={this.handleCheck}
90+
disabled={this.state.disabled}
91+
/>{c}</label></li>
92+
))}
93+
</ul>
94+
</div>;
95+
96+
if(this.state.countries && flag) views = (<div className="container">
97+
<div>
98+
<img src={flag} alt="flag" />
99+
{selections}
100+
<div className="result">{this.state.result}</div>
101+
{this.state.newGame?next:null}
102+
</div>
103+
</div>)
104+
7105
return (
8106
<div className="App">
9-
<header className="App-header">
10-
<img src={logo} className="App-logo" alt="logo" />
11-
<h1 className="App-title">Welcome to React</h1>
12-
</header>
13-
<p className="App-intro">
14-
To get started, edit <code>src/App.js</code> and save to reload.
15-
</p>
107+
<Navbar />
108+
{views}
16109
</div>
17110
);
18111
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
header {
2+
background-color: #2c3e50;
3+
display: flex;
4+
justify-content: space-around;
5+
align-items: center;
6+
color: white;
7+
padding: 0 15px;
8+
}
9+
10+
header h1 {
11+
text-align: center;
12+
}
13+
14+
header a {
15+
text-decoration: none;
16+
color: inherit;
17+
cursor: pointer;
18+
opacity: 0.9;
19+
}
20+
21+
header a:hover {
22+
opacity: 1;
23+
}
24+
25+
header nav {
26+
display: flex;
27+
}
28+
29+
header nav li {
30+
margin: 0 15px;
31+
}
32+
33+
header nav li:first-child {
34+
margin-left: 0;
35+
}
36+
37+
header nav li:last-child {
38+
margin-right: 0;
39+
}
40+
41+
@media (max-width: 1000px) {
42+
header{
43+
padding: 20px 50px;
44+
}
45+
}
46+
47+
48+
@media (max-width: 700px) {
49+
header{
50+
flex-direction: column;
51+
}
52+
53+
header h2{
54+
margin-bottom: 15px;
55+
}
56+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from "react";
2+
import "./Navbar.css";
3+
4+
const Navbar = (props) => {
5+
return(
6+
<header>
7+
<h1><a>Guess the Flag</a></h1>
8+
</header>
9+
);
10+
}
11+
12+
export default Navbar;

0 commit comments

Comments
 (0)