Tic Tac Toe Game
Experience the classic Tic Tac Toe game reimagined with LemonadeJS. Two players take turns marking spaces in a three-by-three grid with X or O. The first player to get three marks in a row wins!
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<div id='root'></div>
<script>
function Tictactoe() {
const self = this;
let text = [
'can start the game',
'turn to play',
'won the game',
]
self.players = [ 'O','X' ];
const checkMatching = function(a, b, c) {
if (self.board[a].player &&
self.board[a].player === self.board[b].player &&
self.board[b].player === self.board[c].player) {
return true;
}
return false;
}
const isWinner = function() {
return (checkMatching(0, 1, 2) || checkMatching(3, 4, 5) || checkMatching(6, 7, 8) ||
checkMatching(0, 3, 6) || checkMatching(1, 4, 7) || checkMatching(2, 5, 8) ||
checkMatching(0, 4, 8) || checkMatching(2, 4, 6));
}
self.click = function(e) {
if (e.target.tagName === 'SPAN') {
if (self.winner) {
alert(self.title.textContent);
} else {
if (!e.target.textContent) {
let index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
self.board[index].player = self.player;
self.text = text[1];
if (isWinner()) {
self.text = text[2];
self.winner = true;
alert(self.title.textContent);
} else {
self.player = self.player ? 0 : 1;
}
}
}
}
}
self.reset = function() {
self.player = 0;
self.text = text[0];
self.winner = false;
self.board = [{},{},{},{},{},{},{},{},{}];
}
self.reset();
return `<div class="tictactoe">
<div class="title" :ref="self.title">{{self.players[self.player]}} {{self.text}}</div>
<div :loop="self.board" class="board" onclick="self.click">
<span>{{self.parent.players[self.player]}}</span>
</div><br/>
<input type="button" onclick="self.reset" value="Reset the game" />
</div>`;
}
lemonade.render(Tictactoe, document.getElementById('root'));
</script>
<style>
.tictactoe {
max-width: 244px;
}
.tictactoe .title {
padding: 20px;
text-align: center;
}
.tictactoe .board {
display: grid;
gap: 1px;
grid-template-columns: repeat(3, 1fr);
}
.tictactoe .board > span {
margin: 2px;
width: 80px;
height: 80px;
background-color: #ddd;
line-height: 80px;
text-align: center;
font-size: 22px;
cursor: pointer;
}
.tictactoe button {
width: 100%;
}
</style>
</html>
import lemonade from 'lemonadejs';
export default function Tictactoe() {
const self = this;
let text = [
'can start the game',
'turn to play',
'won the game',
]
self.players = [ 'O','X' ];
const checkMatching = function(a, b, c) {
if (self.board[a].player &&
self.board[a].player === self.board[b].player &&
self.board[b].player === self.board[c].player) {
return true;
}
return false;
}
const isWinner = function() {
return (checkMatching(0, 1, 2) || checkMatching(3, 4, 5) || checkMatching(6, 7, 8) ||
checkMatching(0, 3, 6) || checkMatching(1, 4, 7) || checkMatching(2, 5, 8) ||
checkMatching(0, 4, 8) || checkMatching(2, 4, 6));
}
self.click = function(e) {
if (e.target.tagName === 'SPAN') {
if (self.winner) {
alert(self.title.textContent);
} else {
if (!e.target.textContent) {
let index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
self.board[index].player = self.player;
self.text = text[1];
if (isWinner()) {
self.text = text[2];
self.winner = true;
alert(self.title.textContent);
} else {
self.player = self.player ? 0 : 1;
}
}
}
}
}
self.reset = function() {
self.player = 0;
self.text = text[0];
self.winner = false;
self.board = [{},{},{},{},{},{},{},{},{}];
}
self.reset();
return `<div class="tictactoe">
<div class="title" :ref="self.title">{{self.players[self.player]}} {{self.text}}</div>
<div :loop="self.board" class="board" onclick="self.click">
<span>{{self.parent.players[self.player]}}</span>
</div><br/>
<input type="button" onclick="self.reset" value="Reset the game" />
</div>`;
}
import React, { useState, useEffect } from 'react';
import './TicTacToe.css';
export default function TicTacToe() {
const [player, setPlayer] = useState(0);
const [text, setText] = useState('can start the game');
const [winner, setWinner] = useState(false);
const [board, setBoard] = useState([{},{},{},{},{},{},{},{},{}]);
const players = ['O', 'X'];
const checkMatching = (a, b, c) => {
if (board[a].player &&
board[a].player === board[b].player &&
board[b].player === board[c].player) {
return true;
}
return false;
}
const isWinner = () => {
return (checkMatching(0, 1, 2) || checkMatching(3, 4, 5) || checkMatching(6, 7, 8) ||
checkMatching(0, 3, 6) || checkMatching(1, 4, 7) || checkMatching(2, 5, 8) ||
checkMatching(0, 4, 8) || checkMatching(2, 4, 6));
}
const handleClick = (index) => {
if (winner) {
alert(`${players[player]} won the game`);
} else {
if (!board[index].player) {
const newBoard = [...board];
newBoard[index].player = player;
setBoard(newBoard);
setText('turn to play');
if (isWinner()) {
setText('won the game');
setWinner(true);
setTimeout(() => alert(`${players[player]} won the game`), 100);
} else {
setPlayer(player ? 0 : 1);
}
}
}
}
const reset = () => {
setPlayer(0);
setText('can start the game');
setWinner(false);
setBoard([{},{},{},{},{},{},{},{},{}]);
}
return (
<div className="tictactoe">
<div className="title">{players[player]} {text}</div>
<div className="board">
{board.map((cell, index) => (
<span key={index} onClick={() => handleClick(index)}>
{cell.player !== undefined ? players[cell.player] : ''}
</span>
))}
</div>
<br/>
<input type="button" onClick={reset} value="Reset the game" />
</div>
);
}
<template>
<div class="tictactoe">
<div class="title">{{ players[player] }} {{ text }}</div>
<div class="board">
<span v-for="(cell, index) in board" :key="index" @click="handleClick(index)">
{{ cell.player !== undefined ? players[cell.player] : '' }}
</span>
</div>
<br/>
<input type="button" @click="reset" value="Reset the game" />
</div>
</template>
<script>
export default {
name: 'TicTacToe',
data() {
return {
player: 0,
text: 'can start the game',
winner: false,
board: [{},{},{},{},{},{},{},{},{}],
players: ['O', 'X']
}
},
methods: {
checkMatching(a, b, c) {
if (this.board[a].player &&
this.board[a].player === this.board[b].player &&
this.board[b].player === this.board[c].player) {
return true;
}
return false;
},
isWinner() {
return (this.checkMatching(0, 1, 2) || this.checkMatching(3, 4, 5) || this.checkMatching(6, 7, 8) ||
this.checkMatching(0, 3, 6) || this.checkMatching(1, 4, 7) || this.checkMatching(2, 5, 8) ||
this.checkMatching(0, 4, 8) || this.checkMatching(2, 4, 6));
},
handleClick(index) {
if (this.winner) {
alert(`${this.players[this.player]} won the game`);
} else {
if (!this.board[index].player) {
this.board[index].player = this.player;
this.text = 'turn to play';
if (this.isWinner()) {
this.text = 'won the game';
this.winner = true;
setTimeout(() => alert(`${this.players[this.player]} won the game`), 100);
} else {
this.player = this.player ? 0 : 1;
}
}
}
},
reset() {
this.player = 0;
this.text = 'can start the game';
this.winner = false;
this.board = [{},{},{},{},{},{},{},{},{}];
}
}
}
</script>
<style scoped>
.tictactoe {
max-width: 244px;
}
.tictactoe .title {
padding: 20px;
text-align: center;
}
.tictactoe .board {
display: grid;
gap: 1px;
grid-template-columns: repeat(3, 1fr);
}
.tictactoe .board > span {
margin: 2px;
width: 80px;
height: 80px;
background-color: #ddd;
line-height: 80px;
text-align: center;
font-size: 22px;
cursor: pointer;
}
.tictactoe button {
width: 100%;
}
</style>