1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.jsとNext UIでTicTacToe(まるばつ)ゲームを実装してみた

Posted at

この記事では、Next.jsとNext UIを使って、TicTacToeゲームを作成する方法をステップバイステップで解説します。

TicTacToeゲームとは、三目並べのことです。
2人で交互にマスを埋めていき、先に縦、横、斜めのいずれかで一直線に自分のマークを3つ並べた方が勝ちという、シンプルながら戦略を要するゲームです

本記事ではパッケージマネージャとしてyarnを使用します。

Play映像

技術スタック

Next.js
React
Next UI
Tailwind CSS
yarn(パッケージマネージャ)

プロジェクトのセットアップ

まず、新しいNext.jsプロジェクトを作成します。

yarn create next-app tic-tac-toe-next
cd tic-tac-toe-next

プロンプトでは以下のように選択してください:

  • TypeScript: Yes
  • ESLint: Yes
  • Tailwind CSS: Yes
  • src/ directory: Yes
  • App Router: Yes
  • Import alias: No

次に、必要なパッケージをインストールします。

yarn add @nextui-org/react tailwindcss framer-motion

Tailwind CSSの設定

生成されたtailwind.config.tsファイルを以下のように更新します:

import type { Config } from "tailwindcss";
import { nextui } from "@nextui-org/react";

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  plugins: [nextui()],
};
export default config;

Next UIプロバイダーの設定

src/app/layout.tsxファイルを以下のように更新して、Next UIプロバイダーを設定します:

src/app/layout.tsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { NextUIProvider } from "@nextui-org/react";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Tic-Tac-Toe Game",
  description: "Modern Tic-Tac-Toe game built with Next.js and Next UI",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <NextUIProvider>
          {children}
        </NextUIProvider>
      </body>
    </html>
  );
}

Tic-Tac-Toeゲームコンポーネントの作成

src/components/TicTacToe.tsxファイルを以下のように更新します:

"use client";
import React, { useState } from "react";
import { Button, Card, CardBody, CardHeader } from "@nextui-org/react";

export const TicTacToe = () => {
  const [board, setBoard] = useState(Array(9).fill(null));
  const [xIsNext, setXIsNext] = useState(true);

  const calculateWinner = (squares: (string | null)[]) => {
    const lines = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8],
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      [0, 4, 8],
      [2, 4, 6],
    ];
    for (let i = 0; i < lines.length; i++) {
      const [a, b, c] = lines[i];
      if (
        squares[a] &&
        squares[a] === squares[b] &&
        squares[a] === squares[c]
      ) {
        return squares[a];
      }
    }
    return null;
  };

  const handleClick = (i: number) => {
    if (calculateWinner(board) || board[i]) return;
    const newBoard = board.slice();
    newBoard[i] = xIsNext ? "X" : "O";
    setBoard(newBoard);
    setXIsNext(!xIsNext);
  };

  const renderSquare = (i: number) => (
    <Button
      key={i}
      className="w-24 h-24 text-4xl font-bold rounded-none border-1 border-gray-300"
      onClick={() => handleClick(i)}
    >
      {board[i]}
    </Button>
  );

  const winner = calculateWinner(board);
  let status;
  if (winner) {
    status = `Winner: ${winner}`;
  } else if (board.every((square) => square)) {
    status = "Draw";
  } else {
    status = `Next player: ${xIsNext ? "X" : "O"}`;
  }

  const resetGame = () => {
    setBoard(Array(9).fill(null));
    setXIsNext(true);
  };

  return (
    <div>
      <Card className="w-full max-w-md">
        <CardHeader className="flex justify-center pb-0">
          <h1 className="text-2xl font-bold">Tic-Tac-Toe game</h1>
        </CardHeader>
        <CardBody>
          <p
            className={`text-center mb-4 text-2xl ${
              winner ? "text-yellow-300" : "text-white"
            }`}
          >
            {status}
          </p>
          <div className="grid grid-cols-3 gap-0 mb-4">
            {[...Array(9)].map((_, i) => renderSquare(i))}
          </div>
          <Button color="primary" onClick={resetGame} className="w-full mt-4">
            Reset Game
          </Button>
        </CardBody>
      </Card>
    </div>
  );
};

メインページの更新

src/app/page.tsxファイルを以下のように更新します:

import { TicTacToe } from "../components/TicTacToe";

export default function Home() {
  return (
    <main className="bg-blue-600 min-h-screen p-24 flex justify-center">
      <TicTacToe />
    </main>
  );
}

アプリケーションの起動

以下のコマンドでアプリケーションを起動できます:

yarn dev

ブラウザでhttp://localhost:3000にアクセスすると、新しく作成したTic-Tac-Toeゲームが表示されます。

ソースコード

GitHubに公開しています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?