首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >乡村猜谜游戏

乡村猜谜游戏
EN

Code Review用户
提问于 2018-01-04 23:48:50
回答 3查看 1.9K关注 0票数 9

我在学习反应,我制作了这个国家的猜谜游戏。你对此有什么改进/建议?

在这里预览

代码语言:javascript
复制
import React, {Component} from 'react';
import './Country.css';

class Country extends Component {
    constructor(props) {
        super(props);
        this.state = {
            countries: [],
            randomCountry: {},
            randomOptions: [],
            userIsWin: '',
            disableFieldset: false,
            goodGuess: 0,
            bgColor: {backgroundColor: 'white'}
        }
        this.getRandomCountry = this.getRandomCountry.bind(this);
        this.checkWin = this.checkWin.bind(this);
    }

componentDidMount() {
    const apiUrl = "https://restcountries.eu/rest/v2/all";
    fetch(apiUrl)
    .then(data => data.json())
    .then(countries => this.setState({countries}))
    .then(this.getRandomCountry)
}


getRandomCountry() {
    const random = this.state.countries[Math.floor(Math.random()*this.state.countries.length)];
    const randomOpt1 = this.state.countries[Math.floor(Math.random()*this.state.countries.length)];
    const randomOpt2 = this.state.countries[Math.floor(Math.random()*this.state.countries.length)];
    const randomOpt3 = this.state.countries[Math.floor(Math.random()*this.state.countries.length)];
    const randomOptions = [random.name, randomOpt1.name, randomOpt2.name, randomOpt3.name];
    randomOptions.sort(() => { return 0.5 - Math.random() });
    this.setState({
        randomCountry: random,
        randomOptions: randomOptions,
        userIsWin: '',
        disableFieldset: false
    })
}

checkWin(e) {
    this.setState({
        disableFieldset: true
    })
    const winCountry = this.state.randomCountry.name;
    const userGuess = e.target.value;
    if (winCountry === userGuess) {
        this.setState({
            userIsWin: 'Win',
            goodGuess: this.state.goodGuess + 1,
            bgColor: {backgroundColor: '#81C784'}
        })
    } else {
        this.setState({
            userIsWin: 'Lose',
            bgColor: {backgroundColor: '#FF8A65'}
        })
    }
    setTimeout(()=>{
        this.getRandomCountry();
        this.setState({
            userIsWin: '',
            disableFieldset: false,
            bgColor: {backgroundColor: 'white'}
        })
        console.log(e.target)
    }, 2000)

}


render() {
    return (
        <div className="main" style={this.state.bgColor}>
            <div className="wrapper">
                <h1>Country Guessing Game</h1>
                <button className="rnd mui-btn mui-btn--raised" onClick={this.getRandomCountry}>Random</button>
                <div className="img-container">
                    <img className="mui-panel" src={this.state.randomCountry.flag} alt="Country flag" />
                </div>
                <h2>{this.state.userIsWin === 'Win' ? 'You guess right! ' : ''}
                    {this.state.userIsWin === 'Lose' ? 'You guess wrong. ' : ''} 
                    Score:{this.state.goodGuess}</h2>
            </div>
            <fieldset disabled={this.state.disableFieldset}>
                <form onClick={e => this.checkWin(e)}>
                    <button className="mui-btn mui-btn--raised" value={this.state.randomOptions[0]}>{this.state.randomOptions[0]}</button>
                    <button className="mui-btn mui-btn--raised" value={this.state.randomOptions[1]}>{this.state.randomOptions[1]}</button>
                    <button className="mui-btn mui-btn--raised" value={this.state.randomOptions[2]}>{this.state.randomOptions[2]}</button>
                    <button className="mui-btn mui-btn--raised" value={this.state.randomOptions[3]}>{this.state.randomOptions[3]}</button>
                </form>
            </fieldset>
        </div>
    )
}
}

export default Country;
EN

回答 3

Code Review用户

回答已采纳

发布于 2018-01-05 06:02:13

屏幕设计看上去很漂亮。这是极简主义的,但令人愉快。它几乎完全适合我的手机的小屏幕(只是有时,我必须向下滚动,以看到所有的答案按钮)。这些标志非常大,可以探索精细的图形细节。为了欣赏尼泊尔国旗的形状,它周围不应该有边框,背景颜色可以设置为白色以外的东西,因为这是在一些旗帜中使用的。

错误:永远不要使用随机比较器进行排序。相反,对数组进行洗牌。这个问题经常已经得到了回答,只需搜索上面的术语。

当大声阅读代码时,“国家是一个组件”是没有意义的。国家是有名字和国旗的东西,所以最好把这个类命名为CountryComponent

大多数JavaScript代码可以重写为不使用this关键字或bind函数,这将导致代码更清晰、更简单。有关示例,请参见此代码评审

setTimeout调用中,我更倾向于将第一个参数提取到一个命名函数中,以便setTimeout看起来更接近于2000

代码语言:javascript
复制
function action() {}

setTimeout(action, 2000);

在标签“得分:”和分数号之间应该有一个空格。

当我进行测验时,我的总分总是保持在0,所以一定有什么问题。每次点击一个答案按钮后,页面会在大约一秒内变成绿色或橙色,然后重新加载,这解释了分数被重置,屏幕闪烁。另一方面,随机按钮工作正常,所以它们之间肯定有一些不同之处。(在Android上用Firefox进行测试。)

票数 7
EN

Code Review用户

发布于 2018-01-05 00:20:21

反馈

很好地使用箭头函数、fetch API (以及相关的承诺)等等。布局看起来也不错。

建议/审查要点

选项可能多次出现

getRandomCountry()中的代码不考虑Math.floor(Math.random()*this.state.countries.length)在4个连续调用中产生相同值的情况。即使有250个选项,也有可能在选项列表中出现一个国家名称( 2+ )。可以使用一个循环来代替选择三个随机选项,直到选择了4个唯一的名称。

因此,代替了这些行:

const随机= this.state.countriesMath.floor(Math.random()*this.state.countries.length);const randomOpt1 = this.state.countriesMath.floor(Math.random()*this.state.countries.length);const randomOpt2 = this.state.countriesMath.floor(Math.random()*this.state.countries.length);const randomOpt3 = this.state.countriesMath.floor(Math.random()*this.state.countries.length);const randomOptions = 名称,随机Opt1.name,随机Opt2.name,随机Opt3.name;

使用while (或for)循环继续添加选项。在循环中,选择“随机”国家名,然后可以使用Array.includes()检查数组中是否已经存在每个随机名称:

代码语言:javascript
复制
const random = this.state.countries[Math.floor(Math.random()*this.state.countries.length)];
let randomOptions = [random.name];
while(randomOptions.length < 4 ){ 
    const randomOpt = this.state.countries[Math.floor(Math.random()*this.state.countries.length)];
    if (!randomOptions.includes(randomOpt.name)) { 
        randomOptions.push(randomOpt.name);
    }
}

不一致颜色规范

虽然它没有什么问题,但它与颜色的规格不一致(例如,初始背景色的white,然后是#81C784表示win,或者#FFA865表示损失)。其他阅读您的代码的人可能会因为规范的不同而被抛之脑后。至少,在十六进制密码之后发表一句有用的评论可能会有帮助.例如:

代码语言:javascript
复制
bgColor: {backgroundColor: '#81C784'} //green

代码语言:javascript
复制
bgColor: {backgroundColor: '#FFa865'} //orange
票数 6
EN

Code Review用户

发布于 2018-01-05 11:48:50

代码和游戏看起来都很好!我只想几句:

我不认为你需要:

代码语言:javascript
复制
this.getRandomCountry = this.getRandomCountry.bind(this);
this.checkWin = this.checkWin.bind(this);

在类中,您可以调用自己的方法,而无需绑定它们。如果这给了你一个错误,你可能失去了其他地方的范围

代码语言:javascript
复制
class Thing {
   constructor(){
      this.doThing()
   }
   doThing(){
   }
}

你可以让“赢”成为一个布尔值,并将它用于正反两方面:

代码语言:javascript
复制
<h2>{(this.state.userIsWin) ? 'You guess right! ' : 'You guess wrong.'}</h2>
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/184324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档