Статьи

Как создать игру Tic Tac Toe с помощью Svelte

Svelte — это способ создания пользовательских интерфейсов следующего поколения.

В то время как фреймворки, такие как React, Vue и Angular, выполняют основную часть своей работы в браузере, Svelte поднимает ее на следующий уровень. Он выполняет свою работу при сборке приложения и компилирует приложение Svelte в эффективный ванильный JavaScript. Таким образом, вы получаете лучшее из обоих миров. Вы пишете свой код на Svelte, который облегчает чтение, повторное использование и все другие преимущества, которые вы получаете, когда используете фреймворк, и делает его невероятно быстрым веб-приложением, которое соответствует ванильному JavaScript, так что вам не нужно нет накладных расходов на JavaScript каркас, который вы используете.

Svelte позволяет писать меньше кода. Он также не использует концепцию Virtual DOM, популяризованную React. Вместо этого он хирургически обновляет DOM при изменении состояния приложения, поэтому приложение запускается быстро и остается быстрым.

Предпосылки

Для этого урока вам необходимы базовые знания HTML, CSS и JavaScript.

Вы также должны установить последнюю версию Node.js.

Мы также будем использовать npx , который устанавливается по умолчанию вместе с Node.js.

В этом уроке мы будем использовать yarn . Если у вас еще не установлена yarn , установите ее отсюда .

Чтобы убедиться, что мы находимся на одной странице, вот версии, используемые в этом руководстве:

  • Узел 12.10.0
  • NPX 6.11.3
  • пряжа 1.17.3

Начало работы с Svelte

В этом уроке мы будем создавать игру Tic Tac Toe в Svelte. К концу вы сможете быстро приступить к работе с Svelte и начать создавать свои собственные приложения на Svelte.

Для начала мы должны подготовить наше приложение с помощью degit . degit более или менее degit на git clone , но гораздо быстрее. Вы можете узнать больше об этом здесь .

Сделайте новый проект, набрав в терминале следующее:

 $ npx degit sveltejs/template tic-tac-toe-svelte 

npx позволяет использовать команду degit не устанавливая ее глобально.

До npx нам пришлось бы выполнить два следующих шага, чтобы достичь того же результата:

 $ npm install --global degit $ degit sveltejs/template tic-tac-toe-svelte 

Благодаря npx мы не раздуваем наше глобальное пространство имен и всегда используем последнюю версию degit .

degit клонирует репозиторий https://github.com/sveltejs/template в папку tic-tac-toe-svelte .

Перейдите в каталог tic-tac-toe-svelte и установите зависимости, набрав в терминале следующее:

 $ cd tic-tac-toe-svelte $ yarn 

Теперь запустите приложение, набрав в терминале следующее:

 $ yarn dev 

Теперь откройте браузер и перейдите по адресу http: // localhost: 5000, и вы должны увидеть следующее:

Svelte - Hello World

Если вы App.svelte папку src/ , вы увидите два файла: App.svelte и main.js main.js — это точка входа в приложение Svelte.

Откройте main.js и вы должны увидеть следующее:

 import App from './App.svelte'; const app = new App({ target: document.body, props: { name: 'world' } }); export default app; 

Приведенный выше файл импортирует App.svelte и создает его экземпляр, используя target элемент. Он помещает компонент в DOM document.body . Он также передает реквизиты имени компоненту App . Эта опора будет доступна в App.svelte .

Компоненты в Svelte написаны с использованием файлов .svelte которые содержат HTML, CSS и JavaScript. Это будет выглядеть знакомо, если вы работали с Vue .

Теперь откройте App.svelte и вы должны увидеть следующее:

 <script> export let name; </script> <style> h1 { color: purple; } </style> <h1>Hello {name}!</h1> 

Во-первых, у нас есть тег script , в котором мы имеем именованный экспорт с именем name . Это должно быть похоже на опору, упомянутую в main.js

Затем у нас есть тег style который позволяет нам стилизовать все элементы в этом конкретном файле, который ограничен только этим файлом, поэтому нет проблем каскадирования.

Затем внизу у нас есть тег h1 , внутри которого мы имеем Hello {name}! , name в фигурных скобках будет заменено фактическим значением. Это называется интерполяцией значений. Вот почему Hello world! печатается на экране.

Базовая структура компонента Svelte

Все файлы .svelte основном имеют следующую структуру:

 <script> /* Javascript logic */ </script> <style> /* CSS styles */ </style> <!-- HTML markup --> 

HTML-разметка будет иметь некоторый дополнительный специфичный для Svelte синтаксис, а остальное — просто обычный HTML, CSS и JavaScript.

Делаем крестики-нолики в Svelte

Давайте начнем с создания нашей игры Tic Tac Toe.

Замените main.js следующим:

 import App from './App.svelte' const app = new App({ target: document.body, }) export default app 

Мы в основном удалили свойство props из экземпляра компонента App .

Теперь замените App.svelte следующим:

 <script> const title = "Tic Tac Toe"; </script> <svelte:head> <title>{title}</title> </svelte:head> <h1>{title}</h1> 

Здесь мы инициализируем постоянную переменную title строкой Tic Tac Toe .

Затем в разметке ниже мы используем специальный синтаксис Svelte, svelte:head , для установки свойства title в теге head .

Это в основном похоже на это:

 <head> <title>Tic Tac Toe</title> </head> 

Но преимущество использования синтаксиса svelte:head заключается в том, что title можно изменить во время выполнения.

Затем мы используем то же свойство title в нашем теге h1 . Теперь это должно выглядеть так:

Svelte - крестики-нолики

Теперь создайте два других файла в каталоге src/ именами Board.svelte и Square.svelte .

Откройте Square.svelte и вставьте следующее:

 <script> export let value; </script> <style> .square { flex: 1 0 25%; width: 50px; height: 70px; background-color: whitesmoke; border: 2px solid black; margin: 5px; padding: 5px; font-size: 20px; text-align: center; } .square:hover { border: 2px solid red; } </style> <button class="square">{value}</button> 

По сути, мы создаем кнопку и стилизуем ее.

Теперь откройте Board.svelte и вставьте следующее:

 <script> import Square from "./Square.svelte"; let squares = [null, null, null, null, null, null, null, null, null]; </script> <style> .board { display: flex; flex-wrap: wrap; width: 300px; } </style> <div class="board"> {#each squares as square, i} <Square value={i} /> {/each} </div> 

Здесь мы импортировали компонент Square . Мы также инициализировали массив squares , который будет содержать наши данные X и 0 , которые в настоящее время null .

Каждая петля в Svelte

В разметке HTML мы использовали специальный синтаксис Svelte для циклов. Это похоже на цикл Array.forEach в Array.forEach JavaScript. Синтаксис выглядит так:

 {#each squares as square, i} <Square value={i} /> {/each} 

Это squares.length более девяти раз, так как squares.length равен 9 . Значение square в первой итерации равно null , поскольку первый элемент равен null а значение i равно 0 поскольку индекс равен 0 в первый раз. Значение square остается null на каждой итерации, поскольку все значения массива squares в настоящее время равны null , но значение i продолжает увеличиваться от 0 до 8 как это значение индекса.

Затем он передает значение i как value prop компоненту Square .

Теперь это должно выглядеть так:

Svelte - Tic Tac Toe Доска

Теперь, когда у нас есть квадраты, давайте добавим немного логики.

Во-первых, нам нужно отобразить следующий ход, будь то его X или 0 . Кроме того, давайте удостоверимся, что квадраты можно щелкнуть с помощью X и 0 .

Для этого добавьте следующий код в Board.svelte :

 <script> . . . let xIsNext = true; $: status = "Next Player: " + (xIsNext ? "X" : "0"); function handleClick(i) { if (!squares[i]) { squares[i] = xIsNext ? "X" : "0"; xIsNext = !xIsNext; } } </script> <style> h3 { color: red; } . . . </style> <h3>{status}</h3> <div class="board"> {#each squares as square, i} <Square value={square} handleClick={() => handleClick(i)} /> {/each} </div> 

Приведенный выше код инициализирует переменную xIsNext как логическое значение. Это логическое значение будет продолжать переключаться относительно следующего хода.

Если X — следующий ход, тогда xIsNext будет true . Если 0 — следующий ход, то xIsNext будет false . По умолчанию установлено значение true .

Тогда у нас есть переменная status . Это особый тип переменной, известный как реактивное присваивание. Если поставить знак доллара ($) перед ним, он станет реагировать на изменения. Поэтому, если xIsNext снова изменится, то status будет обновлен до его нового значения. Когда xIsNext равен true , status будет Next Player: X , а когда xIsNext равен false , status будет Next Player: 0 .

Затем мы передаем value prop как square . Это будет отображать X или 0 зависимости от содержимого.

Затем у нас есть функция handleClick которая вызывается при нажатии на квадрат. Функция handleClick должна быть передана компоненту Square как опора, где она реализована для прослушивания щелчка. Таким образом, без изменения Square.svelte , клик по квадрату не будет работать.

В любом случае, функция handleClick получает индекс i так как мы должны хранить содержимое доски в нашем square массиве для сравнения, если кто-то выиграл или проиграл, или чтобы проверить, является ли это ничьей.

Первая строка, которая является условием if , требуется, чтобы убедиться, что мы не изменим содержимое квадрата, если оно уже заполнено. Если он уже null , только тогда он войдет в тело условия if .

Во второй строке проверяется значение xIsNext и если оно true , тогда X ставится в качестве значения квадрата, а если оно false , в качестве значения квадрата ставится 0 .

Наконец, xIsNext переключается для воспроизведения следующего хода.

Теперь отредактируйте Square.svelte следующим образом:

 <script> . . . export let handleClick; </script> <style> . . . </style> <button class="square" on:click={handleClick}>{value || ""}</button> 

Единственное, что мы здесь добавили, это именованный экспорт handleClick и обработчик on on:click для button , которая указывает на handleClick . Это передано от Board.svelte . Без приведенного выше кода, щелчок не будет работать. Кроме того, мы отображаем содержимое внутри кнопки только в том случае, если оно не равно null то есть мы отображаем только при наличии X и 0 .

Теперь это выглядит так:

Svelte - Tic Tac Toe Доска пустая

Если вы попытаетесь щелкнуть внутри квадратов, то X и 0 будут отображаться соответствующим образом. Вы также можете увидеть изменение статуса следующим образом:

Svelte - Tic Tac Toe Board Полный

В поисках победителя

Теперь, когда мы можем играть в игру, давайте выясним, как найти победителя, проигравшего или проверить, является ли это ничьей.

Откройте Board.svelte и добавьте следующее:

 <script> let winner = null; . . . function handleClick(i) { if (!squares[i]) { squares[i] = xIsNext ? "X" : "0"; xIsNext = !xIsNext; winner = calculateWinner(squares); } } function calculateWinner(squares) { const winningCombo = [ [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 < winningCombo.length; i++) { const [a, b, c] = winningCombo[i]; if (squares[a] && squares[a] === squares[b] && squares[a] === squares 
 

)
return `Winner: $ {squares [a]}`;
}

const isDraw = squares.every (square => square! == null);
вернуть isDraw? «Это ничья»: ноль;
}
</ Скрипт>

,
,
,

{# если победитель}
<H3> {победитель} </ h3>
{:} Еще
<H3> {состояния} </ h3>
{/если}

<div class = "board">
,
,
,
</ DIV>

В приведенном выше коде мы инициализируем переменную winner которая отслеживает победителя. Изначально это null . Затем, после каждого клика, мы вызываем handleClick как вы можете видеть в функции handleClick и устанавливаете его возвращаемое значение в winner .

calculateWinner - это функция, которая принимает массив squares и определяет победителя. winningCombo - это массив, который определяет выигрышную комбинацию. Чтобы выиграть матчи X и 0 , вам нужно либо иметь прямую линию по вертикали и горизонтали, либо диагональную линию. Приведенный выше массив является возможным списком выигрышных комбинаций.

В цикле for мы проверяем, находятся ли значения в массиве squares по прямой (горизонтальной или вертикальной) или диагональной линии, сравнивая индексы. Если они есть, то мы объявляем победителя. Если это не так, мы проверяем, заполнены ли все значения, и если это правда, то это ничья, так как у нас больше нет мест, чтобы играть в X и 0 . В противном случае мы возвращаем null если игра все еще включена.

Наконец, мы добавляем специфичный для Svelte синтаксис для if...else . Если winner не равен null , отобразить winner , иначе отобразить status .

Если кто-то выигрывает, теперь это должно выглядеть так:

Svelte - Tic Tac Toe Победитель Совета

И если это ничья, теперь она должна выглядеть так:

Svelte - Tic Tac Toe Доска Жеребьевка

Теперь давайте добавим способ перезапустить игру.

В том же файле Board.svelte добавьте следующее:

 <script> . . . function restartGame() { squares = [null, null, null, null, null, null, null, null, null]; xIsNext = true; winner = null; } . . . </script> . . . {#if winner} <button on:click={restartGame}>Restart Game</button> {/if} 

Приведенный выше код добавит в приложение кнопку « Restart Game , которая restartGame функцию restartGame которая сбрасывает все необходимые значения для нового запуска.

Поэтому, если вы выиграете игру или получите ничью, вы должны увидеть следующий экран с кнопкой « Restart Game :

Svelte - Tic Tac Toe Board Перезагрузка

Весь файл Board.svelte теперь должен выглядеть так:

 <script> import Square from "./Square.svelte"; let winner = null; let squares = [null, null, null, null, null, null, null, null, null]; let xIsNext = true; $: status = "Next Player: " + (xIsNext ? "X" : "0"); function restartGame() { squares = [null, null, null, null, null, null, null, null, null]; xIsNext = true; winner = null; } function handleClick(i) { if (!squares[i]) { squares[i] = xIsNext ? "X" : "0"; xIsNext = !xIsNext; winner = calculateWinner(squares); } } function calculateWinner(squares) { const winningCombo = [ [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 < winningCombo.length; i++) { const [a, b, c] = winningCombo[i]; if (squares[a] && squares[a] === squares[b] && squares[a] === squares 
 

)
return `Winner: $ {squares [a]}`;
}

const isDraw = squares.every (square => square! == null);
вернуть isDraw? «Это ничья»: ноль;
}
</ Скрипт>

<Стиль>
h3 {
красный цвет;
}

.board {
дисплей: гибкий;
flex-wrap: обертывание;
ширина: 300 пикселей;
}
</ Стиль>

{# если победитель}
<H3> {победитель} </ h3>
{:} Еще
<H3> {состояния} </ h3>
{/если}

<div class = "board">
{# Каждый квадрат как квадрат, я}
<Square value = {square} handleClick = {() => handleClick (i)} />
{/} Каждого
</ DIV>

{# если победитель}
<button on: click = {restartGame}> Перезапустить игру </ button>
{/если}

Теперь вы можете создать производственный код, набрав в терминале следующее:

 $ yarn build 

Это public/bundle.js файл public/bundle.js который содержит оптимизированный код, готовый к работе.

Весь код можно найти на Github .

Вы можете найти демо приложения здесь .

Вывод

В этом уроке мы создали полную игру с использованием Svelte. Мы многому научились, создав нашу игру Tic Tac Toe.

Svelte - это радикально новый компилятор, который можно использовать для создания быстродействующих веб-приложений. Он сильно отличается от традиционных фреймворков в том смысле, что он преобразует все в простой JavaScript, что делает его очень быстрым.

Если вы использовали фреймворки, такие как React или Vue, то подобрать Svelte будет очень просто. Дайте ему шанс, и вы не будете разочарованы.

Конечно, это была лишь верхушка айсберга. Посетите официальный веб-сайт для более удивительного контента и удивительного раздела примеров , который содержит массу примеров с REPL.