Есть ли лучший (более чистый) способ написания этого кода JS с использованием троичных операторов (без повторения кода)? - PullRequest
4 голосов
/ 27 марта 2019

Итак, я пишу простое приложение React.js и просто задаюсь вопросом о настройке состояния. Можно ли это сделать как-нибудь почище?

const enemy = this.state.enemy;
        if (this.state.isRock) {
            enemy === "rock"
                ? this.setState({ result: "Draw!" })
                : enemy === "paper"
                ? this.setState({ result: "You lose!" })
                : enemy === "scissors"
                ? this.setState({ result: "You win!" })
                : this.setState({ result: null });
        } else if (this.state.isPaper) {
            enemy === "rock"
                ? this.setState({ result: "You win!" })
                : enemy === "paper"
                ? this.setState({ result: "Draw!" })
                : enemy === "scissors"
                ? this.setState({ result: "You lose!" })
                : this.setState({ result: null });
        } else if (this.state.isScissors) {
            enemy === "rock"
                ? this.setState({ result: "You lose!" })
                : enemy === "paper"
                ? this.setState({ result: "You win!" })
                : enemy === "scissors"
                ? this.setState({ result: "Draw!" })
                : this.setState({ result: null });
        }

Ответы [ 4 ]

4 голосов
/ 27 марта 2019

Учитывая, что существует только три возможных состояния (победа, поражение, ничья), нам нужно проверить только два из них.На ничью легко проверить, поэтому нам нужно только состояние победы или поражения.Вот пример:

const enemy = this.state.enemy;
let wins = {
    "rock"     : "scissors",
    "paper"    : "rock" ,
    "scissors" : "paper",
}
let play = (this.state.isRock ? "rock" : (
  this.state.isPaper ? "paper" : (
    this.state.isScissors ? "scissors" : null
    )
  )
)

if (!wins[play]) {
    this.setState({ result: null })
} else if (enemy == play) {
    this.setState({ result: "Draw!" })
} else if (wins[play] == enemy) {
    this.setState({ result: "You win!" })
} else {
    this.setState({ result: "You lose!" })
}
3 голосов
/ 27 марта 2019

Вы можете иметь условия как часть карты, так как условие никогда не меняется и установить состояние.

const condition = {
  "rock": {
    "paper": "You lose!",
    "sccissors": "You win!",
    "rock": "Draw!"
  },
  "paper": {
    "rock": "You win!",
    "sccissors": "You lose!",
    "paper": "Draw!"
  },
  "sccissors": {
    "rock": "You lose!",
    "paper": "You win!",
    "sccissors": "Draw!"
  }
};

function getResult(enemy, isRock, isScissors, isPaper) {
  let result = null;
  
  if (isRock) {
    result = condition['rock'][enemy];
  } else if (isPaper) {
    result = condition['paper'][enemy];
  } else if (isScissors) {
    result = condition['scissors'][enemy];
  }
  
  return result;
}

const {
  isRock, 
  isScissors,
  isPaper,
  enemy
} = this.state;


this.setState({
  result: getResult(enemy, isRock, isScissors, isPaper)
})
1 голос
/ 27 марта 2019

У меня есть интересный подход, который вы можете попробовать, который использует цикл for и только один оператор if.

Вы можете использовать литералы объекта для установки значений каждого состояния:

const stateConditions = {
    "isRock": {
      "paper": "You lose!",
      "scissors": "You win!",
      "rock": "Draw!"
    },
    "isPaper": {
      "rock": "You win!",
      "scissors": "You lose!",
      "paper": "Draw!"
    },
    "isScissors": {
      "rock": "You lose!",
      "paper": "You win!",
      "scissors": "Draw!"
    }
  };

В приведенном выше объекте, если вы сделали state = stateConditions ['isRock'], вы получите соответствующие условия для rock

С javascript this.state ['isRock'] совпадает с this.state.isRock. И вы можете использовать свойство для зацикливания каждого свойства в объекте, используя forin , таким образом, вы можете сделать следующее, чтобы найти текущее состояние. Таким образом, вы можете перебрать все возможные состояния и посмотреть, истинно ли this.state ['somestate']:

for (let state in stateConditions) {
    if (this.state[state] === true) {
        // you found which state was true!
    }
}

Финальный код:

const conditions = {
    "isRock": {
      "paper": "You lose!",
      "scissors": "You win!",
      "rock": "Draw!"
    },
    "isPaper": {
      "rock": "You win!",
      "scissors": "You lose!",
      "paper": "Draw!"
    },
    "isScissors": {
      "rock": "You lose!",
      "paper": "You win!",
      "scissors": "Draw!"
    }
  };

  for (const state in conditions) {
      // check if this is the state
      if (this.state[state]) {
          this.setState({ result: condition[state][this.state.enemy] });
          break;
      }
  }

Вот интересная статья о замене операторов switch на литералы объекта

0 голосов
/ 27 марта 2019

Выполнение другого спина одного из текущих ответов, чтобы уменьшить количество повторений:

const condition = {
  rock: {
    paper: -1,
    scissors: 1,
    rock: 0
  },
  paper: {
    paper: 0,
    scissors: -1,
    rock: 1
  },
  scissors: {
    paper: 1,
    scissors: 0,
    rock: -1
  }
};

function getResult({enemy, isRock, isScissors, isPaper}) {
  let result = null;

  if (isRock) {
    result = condition.rock[enemy];
  } else if (isPaper) {
    result = condition.paper[enemy];
  } else if (isScissors) {
    result = condition.scissors[enemy];
  }

  return result === -1 ? "You loose!" : result === 1 ? "You win!" : result === 0 ? "Draw!" : null;
}

this.setState({
  result: getResult(this.state)
});
...