React JS Card Game,计数状态中的值

时间:2019-12-05 02:05:10

标签: javascript reactjs loops state playing-cards

我正在用React JS制作纸牌游戏,该游戏需要3套独特的纸牌。 格式的工作方式是有成分卡可以创建药水。成分在游戏的顶行中进行处理,因此我拥有名为TopRow的组件。

由于这些不是普通的纸牌,因此我必须生成5张不同纸牌中的10张的阵列。 (随机播放(a)) 然后我将这笔交易拼接成只得到5张卡片(a.splice(5);)

所以我希望成分的值根据成分出现的次数增加,例如:函数handleHoneyIncrement应该将countHoney增加1。

我已经尝试了几种不同的方法,并且我想我对如何为此创建一个for循环感到不高兴。

function TopRow(props) {
let a=["Honey0", "Bone0", "Herbs0", "Mushroom0", "Seeds0",
"Honey1", "Bone1", "Herbs1", "Mushroom1", "Seeds1",
"Honey2", "Bone2", "Herbs2", "Mushroom2", "Seeds2",
"Honey3", "Bone3", "Herbs3", "Mushroom3", "Seeds3",
"Honey4", "Bone4", "Herbs4", "Mushroom4", "Seeds4",
"Honey5", "Bone5", "Herbs5", "Mushroom5", "Seeds5",
"Honey6", "Bone6", "Herbs6", "Mushroom6", "Seeds6",
"Honey7", "Bone7", "Herbs7", "Mushroom7", "Seeds7",
"Honey8", "Bone8", "Herbs8", "Mushroom8", "Seeds8",
"Honey9", "Bone9", "Herbs9", "Mushroom9", "Seeds9"
];

shuffle(a);

function shuffle(a) {
  for (let i = a.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [a[i], a[j]] = [a[j], a[i]];
  }
  return a.splice(5);
}
let imageIngredients = a.map(image => {
   return <img key={image} src={require(`../pngs/${image}.png`)}
   alt="ingredients" className="img-responsive" 
   style={{width:"15%", float:"left"}}
   />
});

  let handleHoneyIncrement = () => {
    if (shuffle.length= "Honey0" ||"Honey1" ||"Honey2" ||"Honey3" ||"Honey4" ||"Honey5" ||"Honey6" ||"Honey7" || "Honey8" || "Honey9" ){
      this.setState({countHoney: this.state.countHoney + 1})
    };
  };

    return (
<div className="row" id="topRow"
          style={{WebkitBorderRadius:2, WebkitTextStrokeColor: "red", width:"90%", maxHeight:"30%", padding:0}} >
            <div className="col-6-md">
            <img src={require('../pngs/IngredientBacks.png')} alt="ingredientsBack" style={{width:"15%", float:"left"}} /> 
            </div>

            <div className="col-6-md">
                {imageIngredients}
                {handleHoneyIncrement}
              {a}
            </div>
             </div>
);}
export default TopRow;

2 个答案:

答案 0 :(得分:0)

不能100%确定这是您要的东西,但是听起来您只需要将配料表转换为配料/计数对的集合?

const ingredientCounts = a.reduce((obj, curr) => ({
  ...obj,
  [curr]: obj[curr] ? obj[curr] + 1 : 1
}), {})

ingredientCounts["Honey0"] // 1

如果您希望将所有Honey(例如Honey0 + Honey1等)一起计算,那么应该可以:

const ingredientCounts = a.reduce((obj, curr) => {
  const keys = ["Honey", "etc"]; // maybe this list should be somewhere else, IDK
  const key = keys.find(k => curr.includes(k)); // missing null check :)
  return {
    ...obj,
    [key]: obj[key] ? obj[key] + 1 : 1
  }
}, {})

ingredientCounts["Honey"] // 10

然后我们可以为所有这些对象设置状态,

this.setState({
  counts: ingredientCounts
})

并具有以下状态:

{
  Honey: 10,
  etc: 0
}

答案 1 :(得分:0)

我不确定100%正确地理解您的目标,但是我认为您想显示一个简化的版本:

  • 从卡组中随机抽取5张牌
  • 一个按钮或触发器,可以使牌组洗牌并显示来自同一牌组的5张牌的新手
  • 更新手牌时累积的蜂蜜卡总数

您的代码示例中有很多令人困惑的事情,因此,我没有尝试进行更正,而是快速演示了如何处理该问题,并给出了一些注释,解释了在这些假设下我的所作所为。 https://codesandbox.io/s/trusting-mclean-kwwq4

import React, { useState, useEffect } from "react";

// The deck of cards is probably a constant whose values never change directly. 
// It's possible that I'm wrong and the deck *does* change, but even so I imagine 
// it would come from a prop or context from a parent component. Either way the 
// cards array should not be mutable.
const CARDS = [
  "Honey0", "Bone0", "Herbs0", "Mushroom0", "Seeds0",
  "Honey1", "Bone1", "Herbs1", "Mushroom1", "Seeds1",
  "Honey2", "Bone2", "Herbs2", "Mushroom2", "Seeds2",
  "Honey3", "Bone3", "Herbs3", "Mushroom3", "Seeds3",
  "Honey4", "Bone4", "Herbs4", "Mushroom4", "Seeds4",
  "Honey5", "Bone5", "Herbs5", "Mushroom5", "Seeds5",
  "Honey6", "Bone6", "Herbs6", "Mushroom6", "Seeds6",
  "Honey7", "Bone7", "Herbs7", "Mushroom7", "Seeds7",
  "Honey8", "Bone8", "Herbs8", "Mushroom8", "Seeds8",
  "Honey9", "Bone9", "Herbs9", "Mushroom9", "Seeds9"
];

const initialCards = [];

function TopRow(props) {
  // Keep the current hand of cards in state rather than mutating an array 
  // directly in the function body. React function components should be pure, 
  // with all side effects occurring inside of effect hooks.
  let [cards, setCards] = useState(initialCards);
  let [honeyCount, setHoneyCount] = useState(
    countSubstrings(initialCards, "Honey")
  );

  let imageIngredients = cards.map(image => (
    <img
      key={image}
      src={require(`../pngs/${image}.png`)}
      alt={humanReadableAltTag}
      className="img-responsive"
      style={{ width: "15%", float: "left" }}
    />
  ));

  function shuffleCards() {
    // Reset your hand of cards with the original array (the deck)
    setCards(shuffleArray(CARDS));
  }

  // Return all state to initial values
  function reset() {
    setCards(initialCards);
    setHoneyCount(countSubstrings(initialCards, "Honey"));
  }

  // Any time our cards are updated, we want to increment the number of Honey 
  // cards in our hand. useState accepts a lazy initializer to access the 
  // previous state, which is very useful for effects like this!
  useEffect(() => {
    setHoneyCount(count => count + countSubstrings(cards, "Honey"));
  }, [cards]);

  return (
    <div
      {...props}
      className="row"
      id="topRow"
      style={
        {
          WebkitBorderRadius: 2,
          WebkitTextStrokeColor: "red",
          width: "90%",
          maxHeight: "30%",
          padding: 0
        }
      }
    >
      <button onClick={shuffleCards}>
        {cards.length ? "Shuffle" : "Deal"}
      </button>
      <button onClick={reset}>Reset</button>
      <hr />
      <div className="col-6-md">
        <img
          src={require("../pngs/IngredientBacks.png")}
          alt="Back of ingredient card"
          style={{ width: "15%", float: "left" }}
        />
      </div>

      <div className="col-6-md">
        {imageIngredients}
      </div>
      <hr />
      <div>
        <strong>TOTAL HONEY COUNT:</strong> {honeyCount}
      </div>
    </div>
  );
}
export default TopRow;

// I put these utility functions outside of the component body since there is no 
// real reason to recreate them on each render.

/**
 * @param {any[]} array
 */
function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  // Use slice instead of splice here to prevent mutating the original array
  return array.slice(0, 5);
}

/**
 * @param {string[]} array
 * @param {string} subs
 */
function countSubstrings(array, subs) {
  return array.filter(card => card.includes(subs)).length;
}