使用HTML、CSS和JavaScript创建井字游戏

2025-03-29T12:37:13+08:00 | 3分钟阅读 | 更新于 2025-03-29T12:37:13+08:00

Macro Zhao

使用HTML、CSS和JavaScript创建井字游戏

推荐超级课程:

@TOC

井字游戏是一种永恒且广为人知的游戏,它提供了简单却引人入胜的挑战。其简单性使其成为任何想要涉足编程和网页开发世界的人的理想项目。这个游戏在一个3×3的网格上进行,两名玩家X和O轮流标记单元格,试图以水平、垂直或对角线的方式排列他们的三个标记。第一个达到这个目标的玩家获胜,如果所有单元格都被填满而没有赢家,则游戏以平局结束。

在网页开发领域,创建井字游戏是学习HTML、CSS和JavaScript基础知识的绝佳练习。HTML提供了游戏板的布局和控件的结构,CSS用于设置样式和增强视觉吸引力,而JavaScript是实现游戏逻辑和交互元素的关键。

在本指南中,我们将带您逐步从零开始构建自己的井字游戏。我们将从创建HTML结构开始,该结构概述了游戏板和控件的布局。接下来,我们将使用CSS对游戏进行样式设计,以确保其看起来精致且视觉吸引。最后,我们将深入JavaScript来处理游戏的功能,如跟踪玩家移动、确定赢家以及允许游戏重新开始。

这个项目不仅可以帮助您了解这三种技术如何协同工作,还可以提供创建功能性和交互式网页应用程序的实际经验。跟随本指南,您将获得宝贵的前端开发技能,这些技能可以应用于未来更复杂的项目。

1. 设置您的HTML

我们将从创建一个基本的HTML结构开始。这个文件将包括游戏的布局以及对我们CSS和JavaScript文件的引用。

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Tic-Tac-Toe</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <section>
      <h1 class="game--title">Tic-Tac-Toe</h1>
      <div class="game--container">
        <div data-cell-index="0" class="cell"></div>
        <div data-cell-index="1" class="cell"></div>
        <div data-cell-index="2" class="cell"></div>
        <div data-cell-index="3" class="cell"></div>
        <div data-cell-index="4" class="cell"></div>
        <div data-cell-index="5" class="cell"></div>
        <div data-cell-index="6" class="cell"></div>
        <div data-cell-index="7" class="cell"></div>
        <div data-cell-index="8" class="cell"></div>
      </div>
      <h2 class="game--status"></h2>
      <button class="game--restart">Restart Game</button>
    </section>
    <script src="game.js"></script>
  </body>
</html>

2. 使用CSS美化游戏

接下来,我们将添加一些样式以使游戏在视觉上更具吸引力。这个文件将设置游戏板、单元格和状态消息的样式。

styles.css

body {
  font-family: 'Arial', sans-serif;
}

section {
  text-align: center;
}

.cell {
  font-family: 'Permanent Marker', cursive;
  width: 100px;
  height: 100px;
  box-shadow: 2px 2px 2px 2px #ecd7ba;
  border: 2px solid #ecd7ba;
  cursor: pointer;
  line-height: 100px;
  font-size: 60px;
}

.game--title {
  font-size: 100px;
  color: #d7a62f;
  margin: 10px auto;
}

.game--container {
  display: grid;
  grid-template-columns: repeat(3, auto);
  width: 306px;
  margin: 10px auto;
  background-color: #11213a;
  color: #04c0b2;
}

.game--status {
  font-size: 50px;
  color: #d7a62f;
  margin: 20px auto;
}

.game--restart {
  background-color: #f7e4ac;
  width: 200px;
  height: 50px;
  font-size: 25px;
  color[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];

function handleCellPlayed(clickedCell, clickedCellIndex) {
  gameState[clickedCellIndex] = currentPlayer;
  clickedCell.innerHTML = currentPlayer;
}

function handlePlayerChange() {
  currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
  statusDisplay.innerHTML = currentPlayerTurn();
}

function handleResultValidation() {
  let roundWon = false;
  for (let i = 0; i <= 7; i++) {
    const winCondition = winningConditions[i];
    const a = gameState[winCondition[0]];
    const b = gameState[winCondition[1]];
    const c = gameState[winCondition[2]];
    if (a === '' || b === '' || c === '') continue;
    if (a === b && b === c) {
      roundWon = true;
      break;
    }
  }

  if (roundWon) {
    statusDisplay.innerHTML = winningMessage();
    gameActive = false;
    return;
  }

  const roundDraw = !gameState.includes('');
  if (roundDraw) {
    statusDisplay.innerHTML = drawMessage();
    gameActive = false;
    return;
  }

  handlePlayerChange();
}

function handleCellClick(clickedCellEvent) {
  const clickedCell = clickedCellEvent.target;
  const clickedCellIndex = parseInt(
    clickedCell.getAttribute('data-cell-index')
  );

  if (gameState[clickedCellIndex] !== '' || !gameActive) return;

  handleCellPlayed(clickedCell, clickedCellIndex);
  handleResultValidation();
}

function handleRestartGame() {
  gameActive = true;
  currentPlayer = 'X';
  gameState = ['', '', '', '', '', '', '', '', ''];
  statusDisplay.innerHTML = currentPlayerTurn();
  document.querySelectorAll('.cell').forEach((cell) => (cell.innerHTML = ''));
}

document
  .querySelectorAll('.cell')
  .forEach((cell) => cell.addEventListener('click', handleCellClick));
document
  .querySelector('.game--restart')
  .addEventListener('click', handleRestartGame);

工作原理

  1. HTML: 定义游戏的布局,包括游戏板和状态消息。
  2. CSS: 对游戏进行样式设计,使其具有视觉吸引力。
  3. JavaScript: 实现游戏逻辑,包括处理玩家移动、检查赢家或平局以及更新游戏状态。

通过结合这些元素,您已经创建了一个功能性和互动性的井字游戏。享受编码和玩游戏的乐趣!

© 2011 - 2025 Macro Zhao的分享站

关于我

如遇到加载502错误,请尝试刷新😄

Hi,欢迎访问 Macro Zhao 的博客。Macro Zhao(或 Macro)是我在互联网上经常使用的名字。

我是一个热衷于技术探索和分享的IT工程师,在这里我会记录分享一些关于技术、工作和生活上的事情。

我的CSDN博客:
https://macro-zhao.blog.csdn.net/

欢迎你通过评论或者邮件与我交流。
Mail Me

推荐好玩(You'll Like)
  • AI 动·画
    • 这是一款有趣·免费的能让您画的画中的角色动起来的AI工具。
    • 支持几十种动作生成。
我的项目(My Projects)
  • 爱学习网

  • 小乙日语App

    • 这是一个帮助日语学习者学习日语的App。
      (当然初衷也是为了自用😄)
    • 界面干净,简洁,漂亮!
    • 其中包含 N1 + N2 的全部单词和语法。
    • 不需注册,更不需要订阅!完全免费!
  • 小乙日文阅读器

    • 词汇不够?照样能读日语名著!
    • 越读积累越多,积跬步致千里!
    • 哪里不会点哪里!妈妈再也不担心我读不了原版读物了!
赞助我(Sponsor Me)

如果你喜欢我的作品或者发现它们对你有所帮助,可以考虑给我买一杯咖啡 ☕️。这将激励我在未来创作和分享更多的项目和技术。🦾

👉 请我喝一杯咖啡

If you like my works or find them helpful, please consider buying me a cup of coffee ☕️. It inspires me to create and share more projects in the future. 🦾

👉 Buy me a coffee