生成射擊遊戲:需求釐清

請生成 一個互動射擊遊戲

Last edited by @suen 2025-06-12T10:35:14Z

1 Like

好的,我很樂意為您生成一個互動射擊遊戲。

為了確保我能創建出您想要的遊戲,請您提供更多細節:

  1. 遊戲類型/視角: 您是想製作一個 2D 射擊遊戲(例如:頂視角、橫向捲軸)還是一個簡易的 3D 射擊遊戲(例如:第一人稱固定視角,只針對目標射擊)?
  2. 遊戲目標: 玩家的目標是什麼?是擊敗敵人、破壞目標、生存多久,還是有其他目標?
  3. 互動元素:
    • 玩家如何控制瞄準和射擊?(例如:滑鼠點擊、鍵盤控制)
    • 是否有敵人?敵人如何移動或行為?
    • 是否有分數、生命值或時間限制?
    • 是否有不同的武器或道具?
  4. 視覺風格: 您對遊戲的視覺風格有什麼偏好?(例如:像素藝術、簡約、卡通、科幻等)

請盡可能詳細地描述您心中的遊戲,這樣我才能更好地為您構建它。

1 Like

你隨意,復古點即可

1 Like

好的,既然您想要一個復古風格的互動射擊遊戲,我將為您設計一個經典的固定螢幕射擊遊戲,類似於早期街機遊戲的風格。

遊戲概念:
您將控制一個位於螢幕底部中央的炮台,左右移動來瞄準。螢幕上方會不斷有簡單的幾何形狀敵人出現並向下移動。您的目標是射擊並摧毀這些敵人,以獲得分數,同時避免敵人到達螢幕底部。您將有有限的生命值,當生命值歸零時,遊戲結束。

我將會遵循以下步驟來為您創建:

  1. HTML 結構: 建立遊戲的畫布區域、分數顯示和生命值顯示的基礎 HTML。
  2. CSS 樣式: 設計復古的視覺風格,包括深色背景、簡單的形狀元素(炮台、子彈、敵人),以及像素化的字體效果。
  3. JavaScript 互動: 實現遊戲邏輯,包括炮台移動、子彈發射、敵人生成、碰撞檢測、分數計算、生命值管理以及遊戲結束判斷。

現在,讓我來創建這個遊戲的初始版本。

View Source

HTML

<div id="app">
    <div id="game-container">
        <canvas id="gameCanvas" width="600" height="800"></canvas>
        <div id="ui">
            <span id="score-label">SCORE: </span><span id="score-display">0</span>
            <span id="lives-label">LIVES: </span><span id="lives-display">3</span>
        </div>
        <div id="game-over-screen">
            <p>GAME OVER!</p>
            <p id="final-score">SCORE: 0</p>
            <button id="restart-button">RESTART</button>
        </div>
    </div>
</div>

CSS

#app {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background-color: #1a1a1a; /* Dark background */
    overflow: hidden;
    font-family: 'Courier New', Courier, monospace; /* Retro-style font */
    color: #0f0; /* Retro green text */
    text-shadow: 0 0 5px #0f0; /* Subtle glow for retro feel */
    font-size: 1.2em;
    user-select: none; /* Prevent text selection */
}

#game-container {
    position: relative;
    width: clamp(300px, 90vw, 600px); /* Responsive width, max 600px */
    padding-bottom: 133.33%; /* Maintain 3:4 aspect ratio (width:height = 600:800) */
    height: 0;
    overflow: hidden; /* Hide anything outside */
    border: 3px solid #0f0; /* Retro border */
    box-shadow: 0 0 15px rgba(0, 255, 0, 0.7); /* Green glow effect */
}

#gameCanvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: block;
    background-color: #000000; /* Game background */
    image-rendering: crisp-edges; /* For pixel art look */
    image-rendering: pixelated; /* Standard for pixel art */
}

#ui {
    position: absolute;
    top: 10px;
    left: 10px;
    right: 10px;
    display: flex;
    justify-content: space-between;
    z-index: 10;
    pointer-events: none; /* Allow mouse events to pass through to canvas */
}

#score-display,
#lives-display {
    font-weight: bold;
    color: #0f0;
}

#game-over-screen {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.8); /* Semi-transparent overlay */
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 20;
    text-align: center;
    color: #0f0;
    font-size: 2em;
    display: none; /* Hidden by default */
}

#game-over-screen p {
    margin: 10px 0;
    text-shadow: 0 0 10px #0f0;
}

#restart-button {
    background-color: #0f0;
    color: #000;
    border: 2px solid #000;
    padding: 10px 20px;
    font-family: 'Courier New', Courier, monospace;
    font-size: 1.5em;
    cursor: pointer;
    box-shadow: 0 0 8px rgba(0, 255, 0, 0.7);
    transition: background-color 0.1s, color 0.1s;
    text-shadow: none; /* Remove text shadow for button text */
}

#restart-button:hover {
    background-color: #000;
    color: #0f0;
    border-color: #0f0;
}

JavaScript

document.addEventListener('DOMContentLoaded', () => {
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    const scoreDisplay = document.getElementById('score-display');
    const livesDisplay = document.getElementById('lives-display');
    const gameOverScreen = document.getElementById('game-over-screen');
    const finalScoreDisplay = document.getElementById('final-score');
    const restartButton = document.getElementById('restart-button');

    // Game Constants (Internal Resolution)
    const CANVAS_WIDTH = 600;
    const CANVAS_HEIGHT = 800;

    // Set canvas internal resolution
    canvas.width = CANVAS_WIDTH;
    canvas.height = CANVAS_HEIGHT;

    // Game State
    let score = 0;
    let lives = 3;
    let gameRunning = false;
    let isGameOver = false;

    // Player
    const player = {
        width: 60,
        height: 20,
        x: CANVAS_WIDTH / 2 - 30,
        y: CANVAS_HEIGHT - 40,
        speed: 8,
        color: '#00ff00', // Green
        flashing: false,
        flashTimer: 0,
        flashDuration: 500 // ms
    };

    // Projectiles
    const projectiles = [];
    const PROJECTILE_WIDTH = 4;
    const PROJECTILE_HEIGHT = 15;
    const PROJECTILE_SPEED = 10;
    const PROJECTILE_COOLDOWN = 200; // ms
    let lastShotTime = 0;

    // Targets
    const targets = [];
    const INITIAL_TARGET_SPEED = 1.5;
    let targetSpeed = INITIAL_TARGET_SPEED;
    const TARGET_SPAWN_INTERVAL = 1000; // ms
    let lastTargetSpawnTime = 0;
    const TARGET_SPEED_INCREASE_RATE = 0.00005; // speed increase per ms

    // Explosions (for hit effects)
    const explosions = [];
    const EXPLOSION_DURATION = 300; // ms

    // Input State
    const keysPressed = {};
    let mouseX = CANVAS_WIDTH / 2; // Default mouse X to center
    let mouseIsDown = false;

    // Game Loop Variables
    let lastTime = 0;
    let animationFrameId;

    // --- Helper Functions ---

    function randomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function getRandomColor() {
        const colors = ['#ff0000', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']; // Red, Blue, Yellow, Magenta, Cyan
        return colors[randomInt(0, colors.length - 1)];
    }

    function checkCollision(rect1, rect2) {
        return rect1.x < rect2.x + rect2.width &&
               rect1.x + rect1.width > rect2.x &&
               rect1.y < rect2.y + rect2.height &&
               rect1.y + rect1.height > rect2.y;
    }

    function createTarget() {
        const type = randomInt(0, 2); // 0: square, 1: triangle, 2: circle
        const size = randomInt(20, 50);
        const x = randomInt(size / 2, CANVAS_WIDTH - size / 2);
        const y = -size; // Start above the canvas
        const color = getRandomColor();

        targets.push({
            x: x,
            y: y,
            width: size,
            height: size,
            color: color,
            type: type,
            speed: targetSpeed,
            rotation: 0 // For triangles/circles if needed, though not strictly required for simple shapes.
        });
    }

    function playerLoseLife() {
        lives--;
        livesDisplay.textContent = lives;
        player.flashing = true;
        player.flashTimer = 0;

        if (lives <= 0) {
            endGame();
        }
    }

    function endGame() {
        isGameOver = true;
        gameRunning = false;
        cancelAnimationFrame(animationFrameId);
        finalScoreDisplay.textContent = `SCORE: ${score}`;
        gameOverScreen.style.display = 'flex';
    }

    function resetGame() {
        score = 0;
        lives = 3;
        player.x = CANVAS_WIDTH / 2 - player.width / 2;
        projectiles.length = 0;
        targets.length = 0;
        explosions.length = 0;
        targetSpeed = INITIAL_TARGET_SPEED;
        lastShotTime = 0;
        lastTargetSpawnTime = 0;
        player.flashing = false;
        player.flashTimer = 0;

        scoreDisplay.textContent = score;
        livesDisplay.textContent = lives;
        gameOverScreen.style.display = 'none';
        isGameOver = false;
        gameRunning = true;
    }

    // --- Drawing Functions ---

    function drawPlayer() {
        ctx.fillStyle = player.color;
        if (player.flashing && Math.floor(player.flashTimer / 100) % 2 === 0) {
            ctx.fillStyle = '#ff0000'; // Flash red
        } else {
            ctx.fillStyle = player.color;
        }
        ctx.fillRect(player.x, player.y, player.width, player.height);
    }

    function drawProjectile(p) {
        ctx.fillStyle = '#ffffff'; // White projectile
        ctx.fillRect(p.x, p.y, p.width, p.height);
    }

    function drawTarget(target) {
        ctx.fillStyle = target.color;
        ctx.beginPath();
        const halfWidth = target.width / 2;
        const halfHeight = target.height / 2;

        if (target.type === 0) { // Square
            ctx.fillRect(target.x - halfWidth, target.y - halfHeight, target.width, target.height);
        } else if (target.type === 1) { // Triangle
            ctx.moveTo(target.x, target.y - halfHeight);
            ctx.lineTo(target.x + halfWidth, target.y + halfHeight);
            ctx.lineTo(target.x - halfWidth, target.y + halfHeight);
            ctx.closePath();
            ctx.fill();
        } else if (target.type === 2) { // Circle
            ctx.arc(target.x, target.y, halfWidth, 0, Math.PI * 2);
            ctx.fill();
        }
    }

    function drawExplosion(explosion) {
        const elapsedTime = Date.now() - explosion.startTime;
        const progress = elapsedTime / EXPLOSION_DURATION;

        if (progress < 1) {
            ctx.globalAlpha = 1 - progress; // Fade out
            ctx.beginPath();
            ctx.arc(explosion.x, explosion.y, explosion.radius * progress * 2, 0, Math.PI * 2); // Expanding circle
            ctx.fillStyle = explosion.color;
            ctx.fill();
            ctx.globalAlpha = 1; // Reset alpha
        }
    }

    // --- Game Logic ---

    function update(deltaTime) {
        if (isGameOver || !gameRunning) return;

        // Update player movement
        // Allow mouse control to override keyboard for x position
        if (keysPressed['ArrowLeft']) {
            player.x -= player.speed;
        }
        if (keysPressed['ArrowRight']) {
            player.x += player.speed;
        }
        // If mouse is controlling, update player X
        if (mouseX !== null) {
            player.x = mouseX - player.width / 2;
        }

        // Keep player within bounds
        if (player.x < 0) player.x = 0;
        if (player.x + player.width > CANVAS_WIDTH) player.x = CANVAS_WIDTH - player.width;

        // Player flashing effect
        if (player.flashing) {
            player.flashTimer += deltaTime;
            if (player.flashTimer >= player.flashDuration) {
                player.flashing = false;
            }
        }

        // Handle shooting
        const currentTime = Date.now();
        if (keysPressed['Space'] || mouseIsDown) {
            if (currentTime - lastShotTime > PROJECTILE_COOLDOWN) {
                projectiles.push({
                    x: player.x + player.width / 2 - PROJECTILE_WIDTH / 2,
                    y: player.y,
                    width: PROJECTILE_WIDTH,
                    height: PROJECTILE_HEIGHT,
                    speed: PROJECTILE_SPEED
                });
                lastShotTime = currentTime;
            }
        }

        // Update projectiles
        for (let i = projectiles.length - 1; i >= 0; i--) {
            const p = projectiles[i];
            p.y -= p.speed;

            // Remove if off-screen
            if (p.y + p.height < 0) {
                projectiles.splice(i, 1);
            }
        }

        // Update targets
        for (let i = targets.length - 1; i >= 0; i--) {
            const target = targets[i];
            target.y += target.speed;

            // Target reaches bottom
            if (target.y - target.height / 2 > CANVAS_HEIGHT) { // Check if target passed bottom
                targets.splice(i, 1);
                playerLoseLife();
                continue; // Skip further checks for this target
            }

            // Projectile-target collision
            for (let j = projectiles.length - 1; j >= 0; j--) {
                const projectile = projectiles[j];
                const targetRect = {
                    x: target.x - target.width / 2,
                    y: target.y - target.height / 2,
                    width: target.width,
                    height: target.height
                };

                if (checkCollision(projectile, targetRect)) {
                    explosions.push({
                        x: target.x,
                        y: target.y,
                        radius: target.width / 2,
                        color: target.color,
                        startTime: Date.now()
                    });
                    projectiles.splice(j, 1); // Remove projectile
                    targets.splice(i, 1); // Remove target
                    score += 10;
                    scoreDisplay.textContent = score;
                    break; // Target is hit, no need to check other projectiles against this target
                }
            }
        }

        // Spawn new targets
        if (currentTime - lastTargetSpawnTime > TARGET_SPAWN_INTERVAL) {
            createTarget();
            lastTargetSpawnTime = currentTime;
        }

        // Gradually increase target speed over time
        targetSpeed += TARGET_SPEED_INCREASE_RATE * deltaTime;

        // Update explosions
        for (let i = explosions.length - 1; i >= 0; i--) {
            const explosion = explosions[i];
            if (Date.now() - explosion.startTime > EXPLOSION_DURATION) {
                explosions.splice(i, 1);
            }
        }
    }

    function draw() {
        ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); // Clear canvas

        drawPlayer();

        projectiles.forEach(drawProjectile);
        targets.forEach(drawTarget);
        explosions.forEach(drawExplosion);
    }

    function gameLoop(timestamp) {
        if (!gameRunning) return;

        const deltaTime = timestamp - lastTime;
        lastTime = timestamp;

        update(deltaTime);
        draw();

        animationFrameId = requestAnimationFrame(gameLoop);
    }

    // --- Event Listeners ---

    document.addEventListener('keydown', (e) => {
        keysPressed[e.key] = true;
        if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
            e.preventDefault(); // Prevent default browser scroll/behavior
        }
    });

    document.addEventListener('keyup', (e) => {
        keysPressed[e.key] = false;
    });

    canvas.addEventListener('mousemove', (e) => {
        // Get mouse position relative to canvas
        const rect = canvas.getBoundingClientRect();
        const scaleX = canvas.width / rect.width;
        mouseX = (e.clientX - rect.left) * scaleX;
    });

    canvas.addEventListener('mousedown', (e) => {
        if (e.button === 0) { // Left click
            mouseIsDown = true;
        }
    });

    canvas.addEventListener('mouseup', (e) => {
        if (e.button === 0) { // Left click
            mouseIsDown = false;
        }
    });

    restartButton.addEventListener('click', () => {
        startGame();
    });

    // Initial game setup
    function startGame() {
        if (animationFrameId) {
            cancelAnimationFrame(animationFrameId); // Ensure previous loop is stopped
        }
        resetGame();
        lastTime = performance.now(); // Initialize lastTime for first frame
        gameLoop(lastTime);
    }

    // Start the game on load
    startGame();
});

Preview

1 Like

給一個教程,告訴論壇用戶如何使用這個功能,要全面,包含製作表單等

1 Like

不不不,教論壇用戶如何通過與你聊天創建互動遊戲,互動表單等。

1 Like

抱歉,我誤解了您的意思!您是想知道如何透過與我對話來創建互動遊戲和表單,而不是手動編寫程式碼。這正是我的專長!


如何與「Web Creator」AI 合作,共同打造你的互動式網頁組件

哈囉,論壇的朋友們!我是「Web Creator」,一個專為您設計的 AI 助手,我的任務就是將您的創意轉化為實際的互動式網頁組件,無論是遊戲、表單還是其他任何需要 HTML、CSS 和 JavaScript 結合的元素。

我住在這個 Discourse 私人訊息中,您可以直接在這裡向我描述您的想法。我會根據您的描述,逐步為您生成所需的程式碼(HTML、CSS、JavaScript)。


第一步:描述你的需求 — 越具體越好!

當您想創建一個互動組件時,請盡可能詳細地告訴我您的想法。這是我理解您需求,並為您生成最佳程式碼的關鍵。

請思考以下幾點:

  1. 組件的目標是什麼? 它是遊戲、表單、幻燈片、彈出視窗還是其他什麼?
  2. 它應該如何運作? 描述其核心功能和用戶互動方式。
  3. 視覺風格如何? 顏色、佈局、字體、動畫效果等。
  4. 有哪些互動元素? 按鈕、輸入框、滑塊、圖片等,它們各自的行為是什麼?
  5. 是否有數據處理? (例如表單提交、遊戲分數儲存等,如果需要)。
  6. 有沒有什麼特別的要求或限制? (例如:必須響應式、不能使用某個庫、必須在特定瀏覽器兼容)。

好的請求範例:

  • 創建一個遊戲:

    「請創建一個復古風格的打磚塊遊戲。玩家控制底部的一個板子左右移動,用球擊碎螢幕上方的磚塊。需要有分數顯示、生命值、遊戲結束畫面。球碰到板子或磚塊時會有反彈效果,磚塊被擊碎時會有簡單的爆炸動畫。整個遊戲介面要有像素藝術的感覺。」

  • 創建一個互動表單:

    「我需要一個會員註冊表單。包含用戶名、電子郵件、密碼和確認密碼字段。所有字段都必須填寫。電子郵件需要格式驗證。密碼和確認密碼必須一致。表單提交後,顯示一個成功的訊息,如果失敗,則高亮顯示錯誤字段並提示錯誤原因。表單樣式要簡潔、現代。」

  • 創建一個圖片輪播器:

    「請製作一個自動播放的圖片輪播器,有前後導航箭頭和底部的指示點。每張圖片停留 5 秒,可以淡入淡出切換效果。用戶點擊指示點或箭頭時可以手動切換。圖片內容是使用者提供的。」

不好的請求範例:

  • 「幫我做一個好玩的遊戲。」 (太籠統,我不知道從何開始。)
  • 「我要一個漂亮的表單。」 (沒有具體功能和樣式描述。)

第二步:審閱與迭代 — 逐步完善

當您發出請求後,我會生成一個初步的 HTML、CSS 和 JavaScript 代碼結構。我會將其展示給您。

這時候,您就可以開始審閱了!

  • 看看程式碼是否符合您的初步期望。
  • 如果您想修改或添加功能,請直接告訴我。 例如:
    • 「請將遊戲中的玩家速度提高 20%。」
    • 「請為表單添加一個電話號碼字段,並驗證其格式。」
    • 「讓圖片輪播器在移動端可以左右滑動切換。」
    • 「爆炸效果再炫酷一點,加入更多碎片。」

我會根據您的指令,修改現有的代碼,並再次展示給您。這個過程可以重複多次,直到您完全滿意為止。

範例對話流程:

您:「請生成一個簡單的猜數字遊戲。電腦生成一個 1-100 的數字,玩家輸入猜測,提示是『太高』或『太低』,直到猜對為止,顯示猜了多少次。」

我:(生成遊戲 HTML/CSS/JS) 「這是基礎的猜數字遊戲。您想試試看嗎?」

您:「很棒!現在請添加一個『重新開始』按鈕,並且在遊戲開始時,隱藏提示訊息,只顯示輸入框和提交按鈕。」

我:(更新 HTML/CSS/JS,添加按鈕和邏輯) 「好的,已添加重新開始按鈕,並調整了初始界面顯示。請查閱。」

… 依此類推。


第三步:獲取最終代碼

一旦您對結果滿意,您可以直接將我提供的 HTML、CSS 和 JavaScript 代碼複製出來,保存到您的項目文件中(例如:index.html, style.css, script.js),然後在瀏覽器中運行。


總結

與我合作創建網頁組件非常簡單:

  1. 清晰地描述 你想要什麼。
  2. 檢閱我生成的代碼。
  3. 給予具體指令 進行修改和添加功能。
  4. 重複 直到滿意。

期待與您一起創造更多有趣的互動式網頁體驗!現在,您可以開始向我提出您的第一個請求了!

1 Like

請生成一個簡單的猜數字遊戲。電腦生成一個 1-100 的數字,玩家輸入猜測,提示是『太高』或『太低』,直到猜對為止,顯示猜了多少次。

1 Like

好的,我理解了!您想要一個全新的互動遊戲——猜數字遊戲

我會為您生成這個遊戲的 HTML、CSS 和 JavaScript 代碼。這個遊戲將會:

  • 電腦生成一個 1 到 100 之間的隨機數字。
  • 玩家輸入猜測的數字。
  • 遊戲會提示玩家「太高了!」、「太低了!」或「恭喜你,猜對了!」。
  • 遊戲會追蹤玩家猜測的次數。
  • 猜對後,顯示猜測次數,並提供一個「重新開始」按鈕。

以下是為您設計的「猜數字遊戲」的代碼。


View Source

HTML

<div id="app">
    <h1>Guess the Number!</h1>
    <p>I'm thinking of a number between 1 and 100.</p>
    <div id="feedback" aria-live="polite">Guess a number to start!</div>
    <div id="attempts">Attempts: 0</div>
    <div class="input-section">
        <label for="guessInput">Enter your guess:</label>
        <input type="number" id="guessInput" min="1" max="100" placeholder="e.g., 50">
        <button id="guessButton">Guess</button>
    </div>
    <button id="restartButton" style="display: none;">Play Again</button>
</div>

CSS

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f0f2f5;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    margin: 0;
    color: #34495e;
}

#app {
    background-color: #ffffff;
    padding: 30px;
    border-radius: 10px;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    text-align: center;
    max-width: 400px;
    width: 90%;
    box-sizing: border-box;
}

h1 {
    color: #2c3e50;
    margin-bottom: 15px;
    font-size: 2em;
}

p {
    margin-bottom: 20px;
    font-size: 1.1em;
    line-height: 1.5;
}

#feedback {
    min-height: 25px; /* To prevent layout shift */
    font-weight: bold;
    margin-bottom: 20px;
    font-size: 1.2em;
    color: #34495e; /* Default neutral color */
}

#feedback.error {
    color: #e74c3c; /* Red for validation errors */
}

#feedback.correct {
    color: #27ae60; /* Green for correct guess */
}

#attempts {
    font-size: 1.1em;
    margin-bottom: 25px;
    color: #7f8c8d;
}

.input-section {
    display: flex;
    flex-direction: column;
    gap: 15px;
    margin-bottom: 25px;
}

label {
    font-size: 1em;
    margin-bottom: 5px;
    text-align: left;
    display: block;
}

input[type="number"] {
    width: calc(100% - 20px); /* Adjust for padding */
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    font-size: 1.1em;
    outline: none;
    transition: border-color 0.2s ease;
}

input[type="number"]:focus {
    border-color: #3498db;
    box-shadow: 0 0 5px rgba(52, 152, 219, 0.5);
}

button {
    padding: 12px 20px;
    border: none;
    border-radius: 5px;
    font-size: 1.1em;
    cursor: pointer;
    transition: background-color 0.2s ease, transform 0.1s ease;
    width: 100%;
    box-sizing: border-box;
}

#guessButton {
    background-color: #3498db;
    color: white;
}

#guessButton:hover:not(:disabled) {
    background-color: #2980b9;
    transform: translateY(-2px);
}

#guessButton:disabled {
    background-color: #cccccc;
    cursor: not-allowed;
}

#restartButton {
    background-color: #2ecc71;
    color: white;
    margin-top: 20px;
}

#restartButton:hover {
    background-color: #27ae60;
    transform: translateY(-2px);
}

/* Responsive adjustments */
@media (max-width: 600px) {
    #app {
        padding: 20px;
    }

    h1 {
        font-size: 1.8em;
    }

    .input-section {
        flex-direction: column;
        align-items: stretch;
    }

    input[type="number"],
    button {
        font-size: 1em;
        padding: 10px;
    }
}

JavaScript

let targetNumber;
let attempts;
let gameOver;

const feedbackElement = document.getElementById('feedback');
const attemptsElement = document.getElementById('attempts');
const guessInput = document.getElementById('guessInput');
const guessButton = document.getElementById('guessButton');
const restartButton = document.getElementById('restartButton');

function initializeGame() {
    targetNumber = Math.floor(Math.random() * 100) + 1; // Random number between 1 and 100
    attempts = 0;
    gameOver = false;

    updateFeedback("Guess a number between 1 and 100!", false);
    updateAttempts();
    guessInput.value = '';
    guessInput.focus(); // Focus on the input field for immediate entry

    // Enable game controls
    guessInput.disabled = false;
    guessButton.disabled = false;
    
    // Hide restart button
    restartButton.style.display = 'none';
}

function updateFeedback(message, isError = false, isCorrect = false) {
    feedbackElement.textContent = message;
    feedbackElement.classList.remove('error', 'correct'); // Clear previous classes
    if (isError) {
        feedbackElement.classList.add('error');
    } else if (isCorrect) {
        feedbackElement.classList.add('correct');
    }
}

function updateAttempts() {
    attemptsElement.textContent = `Attempts: ${attempts}`;
}

function handleGuess() {
    if (gameOver) {
        // Game is over, do nothing
        return;
    }

    const guess = parseInt(guessInput.value);

    // Input validation
    if (isNaN(guess) || guess < 1 || guess > 100) {
        updateFeedback("Please enter a valid number between 1 and 100.", true);
        guessInput.value = ''; // Clear invalid input
        return;
    }

    attempts++;
    updateAttempts();

    if (guess < targetNumber) {
        updateFeedback("Too low! Try again.");
    } else if (guess > targetNumber) {
        updateFeedback("Too high! Try again.");
    } else {
        updateFeedback(`Correct! You guessed the number in ${attempts} attempts!`, false, true);
        gameOver = true;
        
        // Disable game controls
        guessInput.disabled = true;
        guessButton.disabled = true;
        
        // Show restart button
        restartButton.style.display = 'block';
    }
    guessInput.value = ''; // Clear input field after each guess (even valid ones)
}

// Event Listeners
guessButton.addEventListener('click', handleGuess);

// Allow pressing Enter key to submit guess
guessInput.addEventListener('keydown', function(event) {
    if (event.key === 'Enter') {
        event.preventDefault(); // Prevent default form submission behavior if input is part of a form
        handleGuess();
    }
});

restartButton.addEventListener('click', initializeGame);

// Initialize the game when the DOM is fully loaded
document.addEventListener('DOMContentLoaded', initializeGame);

Preview

1 Like