svelte-easy-tictactoe Svelte Themes

Svelte Easy Tictactoe

šŸŽ® Tic Tac Toe - Learn SvelteKit Step by Step

A simple Tic Tac Toe game built with SvelteKit, TypeScript, and Bun. This guide is written for junior high students who are new to Svelte!

šŸ“š NEW TO THIS PROJECT? Check out DOCS_INDEX.md for a guide to all documentation!

⚔ IN A HURRY? See QUICKSTART.md for a 5-minute setup guide!

šŸŽÆ What You'll Learn

  • How to build interactive web applications with SvelteKit
  • Managing game state (keeping track of data)
  • Handling user interactions (clicks)
  • Styling with CSS
  • TypeScript basics

šŸ“¦ Getting Started

Prerequisites (What You Need)

Before starting, make sure you have Bun installed on your computer:

# Check if Bun is installed
bun --version

# If not installed, visit: https://bun.sh

Installation (Setting Up)

  1. Clone or download this project
  2. Open your terminal in the project folder
  3. Install dependencies (download required packages):
bun install
  1. Start the development server (run the game):
bun run dev
  1. Open your browser and go to: http://localhost:5173

šŸŽ‰ You should see your Tic Tac Toe game!


šŸ“– Understanding the Code - Step by Step

Part 1: What is SvelteKit?

SvelteKit is a framework for building web applications. Think of it like a toolbox that makes creating websites easier!

  • Svelte = The language/tool for building user interfaces
  • Kit = Extra features for building full websites (routing, server stuff, etc.)

Part 2: Project Structure

svelte-easy-tictactoe/
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ routes/
│   │   ā”œā”€ā”€ +page.svelte      ← Our game is here!
│   │   └── +layout.svelte     ← Page wrapper/layout
│   └── app.html               ← HTML template
ā”œā”€ā”€ package.json               ← Project info & dependencies
└── README.md                  ← You are here!

Key Concept: In SvelteKit, files in src/routes/ become pages on your website!

  • +page.svelte = The homepage (/)
  • about/+page.svelte = The about page (/about)

šŸŽ² Understanding the Game Code

Let's break down src/routes/+page.svelte section by section:

Section 1: The <script> Tag - The Brain 🧠

<script lang="ts">
  // This is where our game logic lives!
</script>

What does lang="ts" mean?

  • ts = TypeScript
  • TypeScript is JavaScript with types (it helps catch errors before running)

Section 2: Game State Variables

let board: string[] = $state(['', '', '', '', '', '', '', '', '']);
let currentPlayer: 'X' | 'O' = $state('X');
let winner: string | null = $state(null);
let isDraw: boolean = $state(false);

Breaking it down:

  1. board - An array with 9 empty strings (one for each cell)

    • string[] means "an array of strings"
    • Position 0 = top-left, position 8 = bottom-right
  2. currentPlayer - Who's turn it is: 'X' or 'O'

    • 'X' | 'O' means "only X or O, nothing else!"
  3. winner - Who won? (null = nobody yet)

    • string | null means "either a string or null"
  4. isDraw - Is the game a tie?

    • boolean means true or false

What is $state()?

  • In Svelte 5, $state() makes variables reactive
  • When they change, the page automatically updates! ✨

Section 3: Win Patterns

const winPatterns = [
  [0, 1, 2], [3, 4, 5], [6, 7, 8], // rows
  [0, 3, 6], [1, 4, 7], [2, 5, 8], // columns
  [0, 4, 8], [2, 4, 6]              // diagonals
];

What is this?

  • A list of all ways to win in Tic Tac Toe
  • [0, 1, 2] = top row (positions 0, 1, 2)
  • [0, 4, 8] = diagonal from top-left to bottom-right

Board positions:

0 | 1 | 2
---------
3 | 4 | 5
---------
6 | 7 | 8

Section 4: The handleClick Function

function handleClick(index: number) {
  // Don't allow click if game is over or cell is already filled
  if (winner || isDraw || board[index] !== '') return;

  // Place the current player's mark
  board[index] = currentPlayer;

  // Check if current player won
  if (checkWinner()) {
    winner = currentPlayer;
    return;
  }

  // Check if board is full (draw)
  if (board.every(cell => cell !== '')) {
    isDraw = true;
    return;
  }

  // Switch to the other player
  currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
}

Step-by-step explanation:

  1. Check if move is valid:

    • Is there already a winner? Stop!
    • Is it a draw? Stop!
    • Is this cell already taken? Stop!
  2. Place the mark:

    • Put X or O in the clicked cell
  3. Check for winner:

    • Did this move win the game?
  4. Check for draw:

    • board.every(...) checks if every cell is filled
  5. Switch players:

    • If X just played, now it's O's turn (and vice versa)
    • condition ? valueIfTrue : valueIfFalse is called a "ternary operator"

Section 5: The checkWinner Function

function checkWinner(): boolean {
  return winPatterns.some(pattern => {
    const [a, b, c] = pattern;
    return board[a] !== '' && 
           board[a] === board[b] && 
           board[a] === board[c];
  });
}

What does this do?

  1. .some() checks if ANY pattern is a win
  2. [a, b, c] = pattern breaks pattern into 3 positions
  3. Checks three things:
    • Position a is not empty
    • Position a equals position b
    • Position a equals position c
  4. Returns true if a winning pattern is found

Example: If positions 0, 1, 2 all have 'X', we have a winner!

Section 6: The resetGame Function

function resetGame() {
  board = ['', '', '', '', '', '', '', '', ''];
  currentPlayer = 'X';
  winner = null;
  isDraw = false;
}

Simple! Just reset everything back to starting values.


šŸŽØ Understanding the HTML/Svelte Part

Section 7: The Template

<div class="container">
  <h1>Tic Tac Toe</h1>
  
  <div class="status">
    {#if winner}
      <p class="winner">šŸŽ‰ Player {winner} wins!</p>
    {:else if isDraw}
      <p class="draw">It's a draw!</p>
    {:else}
      <p>Current player: <span class="player-{currentPlayer}">{currentPlayer}</span></p>
    {/if}
  </div>

  <div class="board">
    {#each board as cell, index}
      <button 
        class="cell" 
        class:x={cell === 'X'}
        class:o={cell === 'O'}
        onclick={() => handleClick(index)}
      >
        {cell}
      </button>
    {/each}
  </div>

  <button class="reset-btn" onclick={resetGame}>Reset Game</button>
</div>

Svelte Special Syntax:

  1. {#if}...{:else if}...{:else}...{/if}

    • Conditional rendering (show different things based on conditions)
    • Like an if-else statement in programming!
  2. {#each board as cell, index}

    • Loop through the board array
    • Create a button for each cell
    • cell = the value ('X', 'O', or '')
    • index = the position (0-8)
  3. {cell}

    • Show the value of a variable
    • Curly braces {} mean "run JavaScript here"
  4. class:x={cell === 'X'}

    • Conditional CSS class
    • If cell is 'X', add the 'x' class
    • This is Svelte magic! ✨
  5. onclick={() => handleClick(index)}

    • When button is clicked, call handleClick with the index
    • () => is an arrow function (a way to write functions)

šŸŽØ Understanding the CSS Part

Section 8: The Styles

<style>
  .container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  }
  
  .board {
    display: grid;
    grid-template-columns: repeat(3, 120px);
    grid-template-rows: repeat(3, 120px);
    gap: 10px;
  }
  
  .cell {
    width: 120px;
    height: 120px;
    font-size: 3rem;
    /* ... more styles ... */
  }
</style>

CSS Concepts Explained:

  1. Flexbox (display: flex)

    • A way to arrange items on the page
    • flex-direction: column = stack items vertically
    • align-items: center = center items horizontally
    • justify-content: center = center items vertically
  2. CSS Grid (display: grid)

    • Perfect for creating grids (like our 3Ɨ3 board!)
    • grid-template-columns: repeat(3, 120px) = 3 columns, each 120px wide
    • gap: 10px = 10px space between cells
  3. Viewport Height (100vh)

    • vh = viewport height
    • 100vh = 100% of the screen height
    • Makes the container fill the entire screen
  4. Pseudo-classes (:hover, :active)

    • :hover = when mouse is over the element
    • :active = when element is being clicked
  5. Animations

    @keyframes bounce {
      from { transform: translateY(0); }
      to { transform: translateY(-10px); }
    }
    
    • Creates a bouncing effect
    • translateY moves element up/down

šŸ”§ Exercises to Try

Now that you understand the code, try these challenges:

Easy Challenges 🟢

  1. Change the colors

    • Find the color codes (like #667eea) and change them
    • Try different background gradients!
  2. Change the cell size

    • Find where it says 120px and make cells bigger or smaller
  3. Add your name to the title

    • Change <h1>Tic Tac Toe</h1> to include your name

Medium Challenges 🟔

  1. Add a score counter

    • Create variables: xWins and oWins
    • Increment them when someone wins
    • Display the score on the page
  2. Add sound effects

    • Use HTML5 Audio API
    • Play a sound when someone clicks or wins
  3. Change X and O to emojis

    • Instead of 'X' and 'O', use 'āŒ' and 'ā­•'

Hard Challenges šŸ”“

  1. Add an AI opponent

    • Make the computer play as 'O'
    • Start with random moves
    • Then try to make it smarter!
  2. Add a timer

    • Each player has 10 seconds to make a move
    • If time runs out, they lose their turn
  3. Make it online multiplayer

    • Use WebSockets to play with friends
    • This is advanced! You'll need to learn about servers

šŸ¤” Common Questions

Q: What does $state() do?

A: In Svelte 5, $state() creates reactive state. When you change it, Svelte automatically updates the page. It's like magic! ✨

Q: Why TypeScript instead of JavaScript?

A: TypeScript adds "types" to JavaScript:

let age: number = 15;  // āœ… OK
let age: number = "fifteen";  // āŒ Error!

It helps catch mistakes before your code runs!

Q: What's the difference between let and const?

A:

  • let = can be changed later
  • const = cannot be changed (constant)
let score = 0;
score = 10;  // āœ… OK

const pi = 3.14;
pi = 3.15;  // āŒ Error!

Q: What does onclick={() => handleClick(index)} mean?

A: It's an arrow function that gets called when you click:

  • onclick = when clicked
  • () => = arrow function syntax
  • handleClick(index) = call this function with index

Without the arrow function, handleClick would run immediately!

Q: How does Svelte know when to update the page?

A: Svelte compiles your code and tracks which variables affect the display. When you change a $state() variable, Svelte knows exactly what to update. No need for virtual DOM like React!


šŸ“š Learn More

Next Steps

  1. Svelte Tutorial - learn.svelte.dev

    • Interactive lessons, great for beginners!
  2. SvelteKit Docs - kit.svelte.dev

    • Official documentation
  3. TypeScript Handbook - typescriptlang.org/docs

    • Learn more about types

Build More Projects

Once you're comfortable with this game, try building:

  • šŸŽ² A dice rolling game
  • šŸƒ A memory card game
  • šŸ“ A todo list app
  • šŸŽØ A drawing app
  • šŸŒ¤ļø A weather app (using APIs)

šŸ› Troubleshooting

The game won't start

# Try deleting node_modules and reinstalling
rm -rf node_modules
bun install
bun run dev

Port already in use

# Kill the process using port 5173
lsof -ti:5173 | xargs kill -9
# Then start again
bun run dev

TypeScript errors

Make sure you're using the latest version:

bun update

šŸŽ‰ Congratulations!

You've just learned:

  • āœ… How to build a SvelteKit app
  • āœ… Managing state with $state()
  • āœ… Handling user interactions
  • āœ… CSS Grid and Flexbox
  • āœ… TypeScript basics
  • āœ… Conditional rendering in Svelte

Keep coding and have fun! šŸš€


šŸ“ License

This project is open source and free to use for learning purposes.

šŸ¤ Contributing

Found a bug or want to improve the tutorial? Feel free to contribute!


Made with ā¤ļø for learning

Happy coding! šŸŽ®āœØ

Top categories

Loading Svelte Themes