Mejoras y optimizaciones en general.

This commit is contained in:
2025-10-03 00:05:08 +02:00
parent bd76741bd2
commit d1a7442ffa
32 changed files with 3336 additions and 783 deletions

View File

@@ -1,55 +1,156 @@
let randomNumber;
let attemptsLeft = 7;
'use strict';
const DIFFICULTIES = {
normal: { max: 100, attempts: 7 },
facil: { max: 50, attempts: 10 },
dificil: { max: 200, attempts: 7 },
extremo: { max: 1000, attempts: 10 }
};
let randomNumber = 0;
let attemptsLeft = 0;
let attemptsTotal = 0;
let maxNumber = 100;
let history = [];
let currentDifficulty = 'normal';
// DOM refs
const guessInput = document.getElementById('guess-input');
const guessBtn = document.getElementById('guess-btn');
const restartBtn = document.getElementById('restart-btn');
const infoDiv = document.getElementById('info');
const attemptsSpan = document.getElementById('attempts-left');
const difficultySelect = document.getElementById('difficulty');
const errorDiv = document.getElementById('error');
const rangeMaxSpan = document.getElementById('range-max');
const attemptsTotalSpan = document.getElementById('attempts-total');
const bestScoreSpan = document.getElementById('best-score');
const historyList = document.getElementById('history-list');
function getBest(difficulty) {
const key = `adivina_best_${difficulty}`;
const v = localStorage.getItem(key);
return v ? parseInt(v, 10) : null;
}
function setBest(difficulty, attemptsUsed) {
const prev = getBest(difficulty);
if (prev === null || attemptsUsed < prev) {
localStorage.setItem(`adivina_best_${difficulty}`, String(attemptsUsed));
bestScoreSpan.textContent = String(attemptsUsed);
}
}
function updateBestDisplay() {
const best = getBest(currentDifficulty);
bestScoreSpan.textContent = best !== null ? String(best) : '—';
}
function renderHistory() {
// Safe clear
while (historyList.firstChild) historyList.removeChild(historyList.firstChild);
history.forEach(item => {
const li = document.createElement('li');
li.textContent = `${item.guess}${item.hint}`;
historyList.appendChild(li);
});
}
function startGame() {
randomNumber = Math.floor(Math.random() * 100) + 1;
attemptsLeft = 7;
attemptsSpan.textContent = attemptsLeft;
currentDifficulty = (difficultySelect && difficultySelect.value) || 'normal';
const conf = DIFFICULTIES[currentDifficulty] || DIFFICULTIES.normal;
maxNumber = conf.max;
attemptsTotal = conf.attempts;
attemptsLeft = attemptsTotal;
randomNumber = Math.floor(Math.random() * maxNumber) + 1;
history = [];
// Update UI
if (rangeMaxSpan) rangeMaxSpan.textContent = String(maxNumber);
if (attemptsTotalSpan) attemptsTotalSpan.textContent = String(attemptsTotal);
attemptsSpan.textContent = String(attemptsLeft);
errorDiv.textContent = '';
infoDiv.textContent = '';
renderHistory();
updateBestDisplay();
// Reset input/button state
guessInput.value = '';
guessInput.disabled = false;
guessInput.setAttribute('min', '1');
guessInput.setAttribute('max', String(maxNumber));
guessBtn.disabled = false;
restartBtn.classList.add('hidden');
guessInput.focus();
}
function checkGuess() {
const guess = Number(guessInput.value);
errorDiv.textContent = '';
if (guess < 1 || guess > 100 || isNaN(guess)) {
infoDiv.textContent = "Por favor ingresa un número válido entre 1 y 100.";
const raw = guessInput.value.trim();
if (raw === '') {
errorDiv.textContent = 'Introduce un número.';
return;
}
const guess = Number(raw);
if (!Number.isFinite(guess) || !Number.isInteger(guess)) {
errorDiv.textContent = 'El valor debe ser un número entero.';
return;
}
if (guess < 1 || guess > maxNumber) {
errorDiv.textContent = `El número debe estar entre 1 y ${maxNumber}.`;
return;
}
attemptsLeft--;
attemptsSpan.textContent = attemptsLeft;
attemptsSpan.textContent = String(attemptsLeft);
if (guess === randomNumber) {
infoDiv.textContent = "¡Correcto! 🎉 Has adivinado el número.";
endGame(true);
} else if (attemptsLeft === 0) {
infoDiv.textContent = '¡Correcto! 🎉 Has adivinado el número.';
const usedAttempts = attemptsTotal - attemptsLeft;
history.push({ guess, hint: '✅ Correcto' });
renderHistory();
endGame(true, usedAttempts);
return;
}
const hint = guess < randomNumber ? '⬇️ Bajo' : '⬆️ Alto';
infoDiv.textContent = guess < randomNumber
? 'Demasiado bajo. Intenta nuevamente.'
: 'Demasiado alto. Intenta nuevamente.';
history.push({ guess, hint });
renderHistory();
if (attemptsLeft === 0) {
infoDiv.textContent = `¡Oh no! Te quedaste sin intentos. El número era ${randomNumber}.`;
endGame(false);
} else if (guess < randomNumber) {
infoDiv.textContent = "Demasiado bajo. Intenta nuevamente.";
} else {
infoDiv.textContent = "Demasiado alto. Intenta nuevamente.";
endGame(false, attemptsTotal);
}
}
function endGame(won) {
function endGame(won, usedAttempts) {
guessInput.disabled = true;
guessBtn.disabled = true;
restartBtn.classList.remove('hidden');
if (won) {
setBest(currentDifficulty, usedAttempts);
}
}
guessBtn.onclick = checkGuess;
restartBtn.onclick = startGame;
guessInput.onkeydown = (e) => { if (e.key === "Enter") checkGuess(); };
// Listeners (avoid inline handlers)
guessBtn.addEventListener('click', checkGuess);
restartBtn.addEventListener('click', startGame);
guessInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') checkGuess();
});
guessInput.addEventListener('input', () => {
errorDiv.textContent = '';
});
if (difficultySelect) {
difficultySelect.addEventListener('change', startGame);
}
// Init
startGame();