构建一个 React 拖放式拼图游戏

JavaScriptJavaScriptBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个项目中,我们将使用 React 创建一个拖放拼图游戏。对于初学者来说,这是一个了解 React 组件、状态管理和处理用户交互的绝佳项目。在本项目结束时,你将拥有一个功能齐全的拼图游戏。

👀 预览

拼图游戏预览动画

🎯 任务

在这个项目中,你将学习:

  • 如何设置一个新的 React 应用程序
  • 如何创建主要的拼图游戏组件
  • 如何管理状态并设置拼图图像
  • 如何在屏幕上显示拼图碎片
  • 如何实现拖放功能
  • 如何将 PuzzleGame 组件合并到主应用程序文件中
  • 如何添加 CSS 来设计拼图的样式

🏆 成果

完成本项目后,你将能够:

  • 设置一个 React 应用程序并创建一个组件
  • 管理状态并处理用户交互
  • 实现拖放功能
  • 加入样式以使拼图在视觉上更具吸引力

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL javascript(("JavaScript")) -.-> javascript/ToolsandEnvironmentGroup(["Tools and Environment"]) javascript(("JavaScript")) -.-> javascript/NetworkingGroup(["Networking"]) javascript(("JavaScript")) -.-> javascript/BasicConceptsGroup(["Basic Concepts"]) javascript(("JavaScript")) -.-> javascript/DOMManipulationGroup(["DOM Manipulation"]) javascript/BasicConceptsGroup -.-> javascript/functions("Functions") javascript/BasicConceptsGroup -.-> javascript/array_methods("Array Methods") javascript/BasicConceptsGroup -.-> javascript/obj_manip("Object Manipulation") javascript/DOMManipulationGroup -.-> javascript/dom_select("DOM Selection") javascript/DOMManipulationGroup -.-> javascript/dom_manip("DOM Manipulation") javascript/DOMManipulationGroup -.-> javascript/event_handle("Event Handling") javascript/ToolsandEnvironmentGroup -.-> javascript/version_control("Version Control") javascript/NetworkingGroup -.-> javascript/api_interact("API Interaction") subgraph Lab Skills javascript/functions -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} javascript/array_methods -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} javascript/obj_manip -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} javascript/dom_select -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} javascript/dom_manip -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} javascript/event_handle -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} javascript/version_control -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} javascript/api_interact -.-> lab-445703{{"构建一个 React 拖放式拼图游戏"}} end

项目设置

目标:我们拼图游戏的基础是一个新的 React 应用程序。

  • 打开你的终端。

  • 导航到你的项目目录:

    cd puzzle-game
  • 安装项目依赖项:

    npm install

创建 PuzzleGame 组件

目标:设置主要的拼图游戏组件。

  • src 目录内,创建一个名为 components 的文件夹。
  • components 文件夹中,创建一个名为 PuzzleGame.js 的新文件。
  • PuzzleGame.js 添加以下基本结构:
// src/components/PuzzleGame.js
// 导入 React 和 useState 用于管理组件状态
import React, { useState, useEffect } from "react";

// 定义 PuzzleGame 组件
const PuzzleGame = () => {
  // 此组件将处理游戏逻辑和用户界面
  return <div className="game-container">{/* 这是将渲染拼图的地方 */}</div>;
};

// 导出组件以便在其他文件中使用
export default PuzzleGame;
✨ 查看解决方案并练习

实现状态和图像设置

目标:设置状态以管理拼图碎片并定义拼图图像。

  • PuzzleGame.js 中,从 React 导入 useState
  • 定义一个状态变量来跟踪拼图碎片的位置。
  • 定义拼图图像的 URL(在 public 文件夹中放置一个名为 corgi.png 的图像)。
// src/components/PuzzleGame.js

//...其他导入
const PuzzleGame = () => {
  // 定义图像 URL 和拼图碎片的初始位置
  const imgUrl = "corgi.png"; // 确保此图像存在于 public 文件夹中
  const [positions, setPositions] = useState([...Array(16).keys()]);

  useEffect(() => {
    // 为初始拼图设置打乱位置
    setPositions((prevPositions) => {
      const newPos = [...prevPositions];
      newPos.sort(() => Math.random() - 0.5);
      return newPos;
    });
  }, []);

  // 组件的返回语句
  return (
    <div className="game-container">
      {/* 拼图的用户界面将在后续步骤中添加到此 */}
    </div>
  );
};

// 导出 PuzzleGame 组件
export default PuzzleGame;
✨ 查看解决方案并练习

渲染拼图碎片

目标:在屏幕上显示拼图碎片。

  • 遍历 positions 状态以渲染各个拼图碎片。
  • 每个碎片应显示图像的一部分。
// src/components/PuzzleGame.js
const PuzzleGame = () => {
  //...之前的代码

  return (
    <div className="game-container">
      <div className="reference-image">
        <img src={imgUrl} alt="参考图像" />
      </div>
      <div className="puzzle-container">
        {positions.map((pos, index) => {
          const x = (pos % 4) * 100;
          const y = Math.floor(pos / 4) * 100;
          return (
            <div
              key={index}
              className="puzzle-piece"
              style={{
                backgroundImage: `url('${imgUrl}')`,
                backgroundPosition: `-${x}px -${y}px`
              }}
            />
          );
        })}
      </div>
    </div>
  );
};
✨ 查看解决方案并练习

添加拖放功能

目标:实现拼图碎片的拖放逻辑。

  • 为拖放开始、拖放经过和放下事件添加处理程序。
  • 实现放下时交换拼图碎片的逻辑。
// src/components/PuzzleGame.js

const PuzzleGame = () => {
  //...之前的代码

  // 处理拖放开始事件
  const handleDragStart = (e, position) => {
    e.dataTransfer.setData("text/plain", position);
  };

  // 处理放下事件
  const handleDrop = (e, position) => {
    e.preventDefault();
    const originalPosition = e.dataTransfer.getData("text");
    // 在此处添加交换拼图碎片位置的逻辑
    setPositions((prevPositions) => {
      const newPos = [...prevPositions];
      [newPos[originalPosition], newPos[position]] = [
        newPos[position],
        newPos[originalPosition]
      ];
      return newPos;
    });
  };

  // 通过阻止默认行为允许放下操作
  const handleDragOver = (e) => {
    e.preventDefault();
  };

  // 渲染添加了拖放处理程序的拼图碎片
};
// src/components/PuzzleGame.js
const PuzzleGame = () => {
  //...之前的代码

  return (
    <div className="game-container">
      <div className="reference-image">
        <img src={imgUrl} alt="参考图像" />
      </div>
      <div className="puzzle-container">
        {positions.map((pos, index) => {
          const x = (pos % 4) * 100;
          const y = Math.floor(pos / 4) * 100;
          return (
            <div
              key={index}
              className="puzzle-piece"
              draggable
              onDragStart={(e) => handleDragStart(e, index)}
              onDrop={(e) => handleDrop(e, index)}
              onDragOver={handleDragOver}
              style={{
                backgroundImage: `url('${imgUrl}')`,
                backgroundPosition: `-${x}px -${y}px`
              }}
            />
          );
        })}
      </div>
    </div>
  );
};
✨ 查看解决方案并练习

更新 App 组件

目标:将 PuzzleGame 组件集成到主应用程序文件中。

  • 打开 src/App.js
  • 渲染 PuzzleGame 组件。
// src/App.js

import React from "react";
import "./App.css";
import PuzzleGame from "./components/PuzzleGame";

// 渲染 PuzzleGame 组件的 App 组件
function App() {
  return (
    <div className="App">
      <PuzzleGame />
    </div>
  );
}

export default App;
✨ 查看解决方案并练习

美化拼图样式

目标:添加 CSS 以使拼图在视觉上更具吸引力。

  • 打开 src/App.css
  • .game-container.puzzle-piece 添加样式,以正确布局拼图。
body {
  font-family: "Arial", sans-serif;
  text-align: center;
  padding: 20px;
  background: #f0f0f0;
}

.game-container {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 20px;
}

.reference-image {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 3px solid #aaa9a9;
  /* 添加边框以保持一致性 */
  padding: 10px;
  /* 在图像周围添加一些内边距 */
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  /* 添加阴影以增加深度 */
}

.reference-image img {
  display: block;
  /* 移除任何默认的内联间距 */
  max-width: 200px;
}

.puzzle-container {
  width: 400px;
  height: 400px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
  border: 5px solid #aaa9a9;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
  /* 添加更大的阴影以实现 3D 效果 */
  background: #ddd;
  /* 为间隙设置浅背景 */
}

.puzzle-piece {
  width: 100%;
  height: 100%;
  background-size: 400px 400px;
  cursor: grab;
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.3);
  /* 为每个拼图块添加内阴影 */
}
✨ 查看解决方案并练习

运行应用程序

目标:启动应用程序以查看完整的拼图游戏。

  • 在项目目录中,运行:

    npm start
  • 应用程序应在你的网页浏览器中打开,并显示拼图游戏。

✨ 查看解决方案并练习

总结

恭喜你!你已经成功地在 React 中构建了一个拖放式拼图游戏。这个项目涵盖了设置 React 项目、创建组件、管理状态、处理用户交互以及应用基本样式。现在,你可以尝试添加更多功能,如计时器、分数或不同难度级别,以增强游戏体验。