ReactJS简单卡牌对战游戏开发实现问题求助
卡牌对战功能实现方案
代码修改说明
所有改动基于你现有逻辑扩展,核心新增了状态管理控制对战流程、胜负判断逻辑、游戏结束判定,默认你的NFT元数据中包含score字段作为对战评分依据,可根据你的实际数据结构调整对应取值逻辑:
import "./styles.css"; import React, { useState } from "react"; import styled from "styled-components"; import data0 from "./NFTs/Team1/0.json"; import data1 from "./NFTs/Team1/1.json"; import data2 from "./NFTs/Team1/2.json"; import data3 from "./NFTs/Team1/3.json"; import data4 from "./NFTs/Team2/0.json"; import data5 from "./NFTs/Team2/1.json"; import data6 from "./NFTs/Team2/2.json"; import data7 from "./NFTs/Team2/3.json"; // 组件移到App外部避免重复初始化 class Welcome extends React.Component { render() { return ( <div className={`NFT ${this.props.winClass ? 'winner-card' : ''}`}> <img className={this.props.className} src={this.props.src} alt="NFT" /> <h1 className="nftnum">{this.props.name}</h1> {this.props.score && <p className="card-score">得分:{this.props.score}</p>} </div> ); } } const NavBar = styled.div` width: 100%; height: 100px; background: #fff; position: fixed; top: 0; display: flex; justify-content: space-between; `; const TeamName = styled.h1` font-size: 30px; display: flex; flex-direction: column; justify-content: center; width: 50%; text-align: center; `; const Logo = styled.img` position: fixed; top: 0; left: 50%; transform: translate(-50%); z-index: 1; width: 25%; `; const BattleBtn = styled.button` position: fixed; bottom: 50px; left: 50%; transform: translateX(-50%); padding: 12px 36px; font-size: 20px; cursor: pointer; background: #e74c3c; color: #fff; border: none; border-radius: 8px; &:disabled { background: #ccc; cursor: not-allowed; } `; const ResultTip = styled.div` position: fixed; top: 120px; left: 50%; transform: translateX(-50%); font-size: 24px; font-weight: bold; color: #2c3e50; `; export default function App() { const matchups = [ [data0, data1, data2, data3], // 队伍1卡牌池 [data4, data5, data6, data7] // 队伍2卡牌池 ]; // 状态管理 const [team1Idx, setTeam1Idx] = useState(0); // 队伍1当前出战卡牌索引 const [team2Idx, setTeam2Idx] = useState(0); // 队伍2当前出战卡牌索引 const [roundWinner, setRoundWinner] = useState(null); // 单轮胜负:left/right/draw const [gameOver, setGameOver] = useState(false); // 游戏是否结束 const [finalWinner, setFinalWinner] = useState(null); // 最终胜者 // 对战核心逻辑 const handleBattle = () => { const card1 = matchups[0][team1Idx]; const card2 = matchups[1][team2Idx]; // 请根据你的实际JSON结构修改得分取值逻辑 const score1 = card1.score; const score2 = card2.score; if (score1 > score2) { setRoundWinner('left'); // 队伍2败,换下一张卡牌 if (team2Idx + 1 >= matchups[1].length) { setGameOver(true); setFinalWinner('队伍1'); return; } setTeam2Idx(prev => prev + 1); } else if (score2 > score1) { setRoundWinner('right'); // 队伍1败,换下一张卡牌 if (team1Idx + 1 >= matchups[0].length) { setGameOver(true); setFinalWinner('队伍2'); return; } setTeam1Idx(prev => prev + 1); } else { setRoundWinner('draw'); // 平局规则可自行调整,当前逻辑为双方都换下一张 if (team1Idx + 1 >= matchups[0].length || team2Idx + 1 >= matchups[1].length) { setGameOver(true); setFinalWinner('平局'); return; } setTeam1Idx(prev => prev + 1); setTeam2Idx(prev => prev + 1); } }; return ( <div className="App"> <Logo src="logo.png" /> <NavBar> <TeamName>Aids Sack</TeamName> <TeamName>Balls Tucked</TeamName> </NavBar> <ResultTip> {gameOver ? `游戏结束,最终胜者:${finalWinner}` : roundWinner === 'left' ? '上轮胜者:左侧卡牌' : roundWinner === 'right' ? '上轮胜者:右侧卡牌' : roundWinner === 'draw' ? '上轮平局' : '点击下方按钮开始对战'} </ResultTip> <div className="nftWrapper"> <Welcome className="leftNFT" name={matchups[0][team1Idx].name} src={matchups[0][team1Idx].properties.files[0].uri} score={matchups[0][team1Idx].score} winClass={roundWinner === 'left'} /> <Welcome className="rightNFT" name={matchups[1][team2Idx].name} src={matchups[1][team2Idx].properties.files[0].uri} score={matchups[1][team2Idx].score} winClass={roundWinner === 'right'} /> </div> <BattleBtn onClick={handleBattle} disabled={gameOver}> {gameOver ? '游戏结束' : '开始对战'} </BattleBtn> </div> ); }
补充说明
- 你可以在
styles.css中添加.winner-card { border: 4px solid #f39c12; box-shadow: 0 0 20px #f39c12; }实现胜者卡牌高亮效果 - 如果你的NFT元数据中得分字段不是
score,请修改handleBattle函数内的score1、score2取值逻辑 - 平局规则、对战触发方式、动画效果都可以根据你的需求自行扩展调整
内容的提问来源于stack exchange,提问作者Thud Designs
相关产品推荐
相关产品推荐

