限制记忆游戏只允许在 React 中同时打开两张牌

问题描述 投票:0回答:1

我正在反应中创建一个简单的记忆游戏,并且遇到一个问题,可以一次选择两张以上的牌。仅单击两张卡时游戏可以正常运行,但如果选择更多卡则会中断。

我曾尝试将 openCards 中的卡片数量限制为 2 张,然后再翻转另一张,但没有成功。我还考虑过在您选择两张卡片时添加所有未向disabledCards开放的卡片,但这会将它们与已经匹配的卡片混合在一起。

function App() {
  const [images, setImages] = useState([]);
  const [openCards, setOpenCards] = useState([]);
  const [shouldFlipBack, setShouldFlipBack] = useState(false);
  const [disabledCards, setDisabledCards] = useState([]);  //cards that are matched
  const imageArray = [
    {type: "penguin", image: penguin},
    {type: "penguin", image: penguin},
    {type: "snail", image: snail},
    {type: "snail", image: snail},
    {type: "chicken", image: chicken},
    {type: "chicken", image: chicken},
    {type: "raccoon", image: raccoon},
    {type: "raccoon", image: raccoon},
    {type: "fox", image: fox},
    {type: "fox", image: fox}
  ];

  useEffect(() => {
    setImages((prevImages) => shuffleImages(prevImages));
  }, []);
  
  useEffect(() => {
    if (openCards.length === 2) {
      checkIfMatch();
      setOpenCards([]);
    }
  }, [openCards]);

  function checkIfMatch() {  
    if (openCards[0] === openCards[1]) {
      console.log("match");
      setDisabledCards(()=> [...disabledCards, openCards[0]]);
      setShouldFlipBack(false);

    } else {
        console.log("not match");
        setTimeout(() => {
          setShouldFlipBack(true);
        }, 1000); 
    }
    setShouldFlipBack(false);
  }
function Card({card, setOpenCards, openCards, shouldFlipBack, disabledCards}) {
  const [isFlipped, setFlipped] = useState(false);

  useEffect(() => {
    if (!disabledCards.includes(card.type)) {
      setTimeout(() => {
        setFlipped(false);
      }, 500);
    }
  }, [shouldFlipBack]);

  function flipCard() {
    if (!disabledCards.includes(card.type)) {
      setFlipped(!isFlipped);
      setOpenCards(()=> [...openCards, card.type]);
    }
  }
  return (
    <div className="card" onClick={flipCard}>
      <div className={isFlipped ? "card-inner flipped" : "card-inner"}>
        <div className="card-front"></div>
        <div className="card-back">
          {isFlipped && <img src={card.image} alt="card" />}
        </div>
      </div>
    </div>
  );
}

export default Card;
javascript reactjs logic game-development
1个回答
0
投票

您可以执行以下两项操作之一:

  1. 向上移动点击处理程序,使其位于父组件中
  2. 将一个道具传递到卡片中,说明是否允许翻转。

我认为第一个提供了更好的设计,所以这就是我将展示的:

const noop = () => {}

function App() {
  const [images, setImages] = useState([]);
  const [shouldFlipBack, setShouldFlipBack] = useState(false);
  const [isPending, setIsPEnding] = useState(false);
  
  const imageArray = [
    {type: "penguin", image: penguin, isFlipped: false, isMatcced: false},
    {type: "penguin", image: penguin, isFlipped: false, isMatched: false},
    {type: "snail", image: snail, isFlipped: false, isMatched: false},
    {type: "snail", image: snail, isFlipped: false, isMatched: false},
    {type: "chicken", image: chicken, isFlipped: false, isMatched: false},
    {type: "chicken", image: chicken, isFlipped: false, isMatched: false},
    {type: "raccoon", image: raccoon}, isFlipped: false, isMatched: false,
    {type: "raccoon", image: raccoon, isFlipped: false, isMatched: false},
    {type: "fox", image: fox, isFlipped: false, isMatcched: false},
    {type: "fox", image: fox, isFlipped: false, isMatcched: false}
  ];

  const flippedButNotMatched = useMemo(images => image.isFlippedlipped && !image.isMatched, [images]);

  useEffect(() => {
    setImages(shuffleImages(imageArray));
  }, []);

  const flipCard = useCallback(cardIndex => {
     const card = images[cardIndex]
     setImages(prevImages => image === card ? {...card, isFlipped: true} : image)
     if (flippedButNotMatched.length == 1 && flippedButNotMatched[0].type === card.type) {
        return;
     }
     setIsPending(true);
     const cancel = setTimeout(() => {
        setIsPending(true)
        setImages(prevImages => image.isMatched ? image : {...image, isFlipped: false})
     }, 500) 
     return () => clearTimeout(cancel)
  }, [flippedButNotMatched]}

  return (<div>
     {images.map(image => 
        <Card isFlipped={image.isFlipped} onClick={pending||image.isMapped ? noop: flipCard? />
     )}
  </div>)
}

祝你好运!

© www.soinside.com 2019 - 2024. All rights reserved.