Last active
October 20, 2024 06:37
-
-
Save fermelli/6a11a0029349d40cc0b58c92943e6f56 to your computer and use it in GitHub Desktop.
Este es un juego de tic-tac-toe simple implementado en Vue 3. Basado en la version de React de la documentacion oficial (https://react.dev/learn/tutorial-tic-tac-toe)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Tic Tac Toe: Implementacion en Vue 3</title> | |
<style> | |
* { | |
box-sizing: border-box; | |
} | |
body { | |
font-family: sans-serif; | |
margin: 20px; | |
padding: 0; | |
} | |
h1 { | |
margin-top: 0; | |
font-size: 22px; | |
} | |
h2 { | |
margin-top: 0; | |
font-size: 20px; | |
} | |
h3 { | |
margin-top: 0; | |
font-size: 18px; | |
} | |
h4 { | |
margin-top: 0; | |
font-size: 16px; | |
} | |
h5 { | |
margin-top: 0; | |
font-size: 14px; | |
} | |
h6 { | |
margin-top: 0; | |
font-size: 12px; | |
} | |
code { | |
font-size: 1.2em; | |
} | |
ul { | |
padding-inline-start: 20px; | |
} | |
.square { | |
background: #fff; | |
border: 1px solid #999; | |
float: left; | |
font-size: 24px; | |
font-weight: bold; | |
line-height: 34px; | |
height: 34px; | |
margin-right: -1px; | |
margin-top: -1px; | |
padding: 0; | |
text-align: center; | |
width: 34px; | |
} | |
.board-row:after { | |
clear: both; | |
content: ''; | |
display: table; | |
} | |
.status { | |
margin-bottom: 10px; | |
} | |
.game { | |
display: flex; | |
flex-direction: row; | |
} | |
.game-info { | |
margin-left: 20px; | |
} | |
</style> | |
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> | |
</head> | |
<body> | |
<div id="app"></div> | |
<script> | |
/* Tic Tac Toe: Vue 3 */ | |
/* | |
Este es un juego de tic-tac-toe simple implementado en Vue 3. | |
Basado en la version de React de la documentacion oficial (https://react.dev/learn/tutorial-tic-tac-toe) | |
Extensiones recomendadas para VSCode: | |
- Prettier - Code formatter | |
- es6-string-html | |
*/ | |
const { computed, createApp, ref } = Vue; | |
function calculateWinner(squares) { | |
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 Square = { | |
props: { | |
value: { | |
type: [String, null], | |
required: true, | |
}, | |
}, | |
emits: ['onSquareClick'], | |
template: /*html*/ ` | |
<button class="square" @click="$emit('onSquareClick')"> | |
{{ value }} | |
</button> | |
`, | |
}; | |
const Board = { | |
props: { | |
xIsNext: { | |
type: Boolean, | |
required: true, | |
}, | |
squares: { | |
type: Array, | |
required: true, | |
}, | |
}, | |
emits: ['onPlay'], | |
components: { | |
Square, | |
}, | |
setup(props) { | |
const winner = computed(() => calculateWinner(props.squares)); | |
function handleClick(i) { | |
if (calculateWinner(props.squares) || props.squares[i]) { | |
return; | |
} | |
const nextSquares = props.squares.slice(); | |
if (props.xIsNext) { | |
nextSquares[i] = 'X'; | |
} else { | |
nextSquares[i] = 'O'; | |
} | |
this.$emit('onPlay', nextSquares); | |
} | |
return { winner, handleClick }; | |
}, | |
template: /*html*/ ` | |
<div class="status"> | |
{{ winner ? 'Ganador: ' + winner : 'Siguiente jugador: ' + (xIsNext ? 'X' : 'O') }} | |
</div> | |
<div class="board-row"> | |
<Square :value="squares[0]" @onSquareClick="handleClick(0)" /> | |
<Square :value="squares[1]" @onSquareClick="handleClick(1)" /> | |
<Square :value="squares[2]" @onSquareClick="handleClick(2)" /> | |
</div> | |
<div class="board-row"> | |
<Square :value="squares[3]" @onSquareClick="handleClick(3)" /> | |
<Square :value="squares[4]" @onSquareClick="handleClick(4)" /> | |
<Square :value="squares[5]" @onSquareClick="handleClick(5)" /> | |
</div> | |
<div class="board-row"> | |
<Square :value="squares[6]" @onSquareClick="handleClick(6)" /> | |
<Square :value="squares[7]" @onSquareClick="handleClick(7)" /> | |
<Square :value="squares[8]" @onSquareClick="handleClick(8)" /> | |
</div> | |
`, | |
}; | |
const Game = { | |
setup() { | |
const history = ref([Array(9).fill(null)]); | |
const currentMove = ref(0); | |
const xIsNext = computed(() => currentMove.value % 2 === 0); | |
const currentSquares = computed( | |
() => history.value[currentMove.value], | |
); | |
function handlePlay(nextSquares) { | |
const nextHistory = [ | |
...history.value.slice(0, currentMove.value + 1), | |
nextSquares, | |
]; | |
history.value = nextHistory; | |
currentMove.value = nextHistory.length - 1; | |
} | |
function jumpTo(nextMove) { | |
currentMove.value = nextMove; | |
} | |
return { | |
history, | |
currentMove, | |
xIsNext, | |
currentSquares, | |
handlePlay, | |
jumpTo, | |
}; | |
}, | |
components: { | |
Board, | |
}, | |
template: /*html*/ ` | |
<div className="game"> | |
<div className="game-board"> | |
<Board :xIsNext="xIsNext" :squares="currentSquares" @onPlay="handlePlay" /> | |
</div> | |
<div className="game-info"> | |
<ol> | |
<li v-for="(squares, move) in history.slice(0, currentMove + 1)" :key="move"> | |
<button @click="jumpTo(move)"> | |
{{ | |
move > 0 ? 'Ir al movimiento #' + move : 'Ir al inicio del juego' | |
}} | |
</button> | |
</li> | |
</ol> | |
</div> | |
</div> | |
`, | |
}; | |
const app = createApp({ | |
components: { | |
Game, | |
}, | |
template: /*html*/ ` | |
<Game /> | |
`, | |
}); | |
app.mount('#app'); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment