<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <title>Crucigrama OurNorth</title> <link href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css'> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.min.js"></script> <style> /*Downloaded from https://www.codeseek.co/arandaschimpf/crucigrama-vRgKZP */ .container { margin-top: 3vh; } .table-container { display: flex; flex-direction: column; align-items: center; } table { border-collapse: collapse; font-size: 18px; } td { width: 36px; height: 36px; border: 1px solid black; text-align: center; position: relative; text-transform: uppercase; font-family: arial; } td.empty { background: #ff9f55; background: #ffffff; border: 0; } td.selected { background: lightblue; } td.start { cursor: pointer; } td.start label { position: absolute; top: 0; left: 2px; text-align: left; font-size: 10px; } td.start:hover { background: #eee; } td.start.selected:hover { background: #ddf; } .mensaje { position: absolute; color: white; left: 25vw; text-align: center; border-radius: 8px; padding: 10px; width: 50vw; z-index: 1000; background: rgba(0, 0, 255, 0.9) } .mensaje button { margin-top: 10px; } </style> </head> <body> <div align="center"><h2>De click sobre el número para activar el cricigrama</h2></div> <div id="app" class="container" @keyup.escape="selected = undefined"> <div class="table-container" style="display:none;" v-show="true"> <div class="timer">{{cronometro}}</div> <div class="mensaje" v-if="mensaje !== undefined"> <div class="content">{{mensaje}}</div> <button @click="mensaje = undefined" class="btn btn-primary">OK</button> </div> <table> <tr v-for="(row, y) in matrix" :key="y"> <td v-for="(cell, x) in row" :class="{empty: cell.empty, start: !!cell.start, selected: cell.words.includes(selected)}" @click="selectWord(cell.start)"> <label v-if="!!cell.start">{{cell.start}}</label> {{cell.words.some(i => completed[i]) ? cell.letter : ' '}} </td> </tr> </table> <div v-if="selected !== undefined" style="text-align: center;"> <p class="pista" v-if="pista"> {{pista}} </p> <input v-model="answer" ref="input" @keyup.enter="corregir"/> <button @click="corregir" class="btn btn-primary">Colocar</button> <button @click="solucion" class="btn btn-danger">Pista</button> </div> <hr> <button class="btn btn-block btn-primary" @click="finalizar">Finalizar</button> </div> <h3 v-show="false">Cargando....</h3> </div> <script src='https://unpkg.com/vue'></script> <script> /*Downloaded from https://www.codeseek.co/arandaschimpf/crucigrama-vRgKZP */ // Arreglo de palabras indicando la posición de su inicio, su sentido (vertical u horizontal), // la palabra en cuestión y la pista que se presenta al usuario const palabras = [ { pos: [0, 0], sentido: 0, palabra: 'gravedad', pista: 'Fuerza que nos mantiene unidos a la superficie del planeta' }, { pos: [2, 0], sentido: 1, palabra: 'agua', pista: 'Compuesta por dos moléculas de hidrógeno y una de oxígeno' }, { pos: [0, 3], sentido: 0, palabra: 'plantas', pista: 'Renuevan el aire que respiramos' }, { pos: [4, 3], sentido: 1, palabra: 'tierra', pista: 'Planeta en donde vivimos' }, { pos: [0, 5], sentido: 0, palabra: 'oxigeno', pista: 'Gas incoloro e inodoro esencial para la vida' }, { pos: [1, 8], sentido: 0, palabra: 'casa', pista: 'Donde Vivimos' } ] // Objeto default para celdas vacías de la grilla const empty = { start: false, letter: '', words: [], empty: true } new Vue({ el: '#app', data () { return { // Arreglo de booleanos indicando si una palabra fue completada completed: Array(palabras.length).fill(false), // Entero indicando la palabra que fue seleccionada para completar selected: undefined, // String donde se guarda lo que ingresa el usuario answer: '', // Cantidad de veces que se solicitó una pista penalties: 0, // Temporizador en segundos desde el comienzo de la partida. Comienza en 5 minutos. timer: 60 * 5, // La tabla que será armada al inicio, conteniendo todas las celdas matrix: [], // Mensaje final a mostrar mensaje: undefined } }, created () { // Creación de la tabla que contiene las celdas. const width = palabras.reduce((max, cur) => Math.max(max, cur.pos[0] + (cur.sentido === 0 ? cur.palabra.length : 1)), 0) const height = palabras.reduce((max, cur) => Math.max(max, cur.pos[1] + (cur.sentido === 1 ? cur.palabra.length : 1)), 0) let matrix = Array(height).fill(0).map(() => Array(width).fill(null).map(() => empty)) palabras.forEach((palabra, index) => { const [x, y] = palabra.pos palabra.palabra.split('').forEach((l, i) => { let cell = matrix[y + (palabra.sentido ? i : 0)][x + (palabra.sentido ? 0 : i)] if (cell === empty) { cell = matrix[y + (palabra.sentido ? i : 0)][x + (palabra.sentido ? 0 : i)] = {words: []} } cell.empty = false cell.words.push(index) if (i === 0) { cell.start = index + 1 } cell.letter = l }) }) this.matrix = matrix // Control del temporizador y disparador del evento final cuando éste se acabe this.$options.interval = setInterval(() => { this.timer-- if (this.timer <= 0) { clearInterval(this.$options.interval) this.finalizar() } }, 1000) }, computed: { // Contiene la pista de la palabra seleccionada pista () { if (this.selected === undefined) return undefined return `${palabras[this.selected].sentido ? 'Vertical' : 'Horizontal'} ${this.selected + 1}: ${palabras[this.selected].pista}` }, // Formato a mostrar del cronómetro cronometro () { const minutes = Math.floor(this.timer/60).toString().padStart(2, '0') const seconds = Math.floor(this.timer%60).toString().padStart(2, '0') return `${minutes}:${seconds}` } }, methods: { selectWord (index) { if (index > 0) { this.selected = index - 1 this.answer = '' setTimeout(() => this.$refs.input.focus(), 50) } }, // Se fija si la palabra ingresada es correcta y de ser así, modifica el arreglo de palabras completas corregir () { const solucion = palabras[this.selected].palabra const answer = this.answer.toLowerCase() if (answer === solucion) { this.completed[this.selected] = true this.selected = undefined } }, // Agrega una letra correcta más a la respuesta actual solucion () { const solucion = palabras[this.selected].palabra const answer = this.answer.toLowerCase() if (answer === solucion) { return } if (answer !== solucion.slice(0, answer.length)) { this.penalties++ this.answer = '' } this.answer = solucion.slice(0, this.answer.length + 1) this.penalties++ }, // Calcula el puntaje final del jugador en base a las respuestas correctas y las penalidades por pistas finalizar () { const total = this.completed.reduce((total, current, i) => total + palabras[i].palabra.length, 0) const completo = this.completed.reduce((total, current, i) => current ? total + palabras[i].palabra.length : total, 0) const tempScore = Math.ceil(100 * completo / total) const finalScore = Math.max(tempScore - this.penalties, 0) if (tempScore < 100) { this.penalties++ } this.mensaje = ` Tu puntuación es ${finalScore}%. ` } } }) </script> </body> </html>