HTML+JS谁是卧底游戏

先说一句:一段时间没发文章,好多僵尸粉关注我,这CSDN😠

主要功能

  1. 玩家设置:在游戏开始前,输入总人数、卧底人数和白板人数。系统会自动计算出剩下的平民人数,并随机分配身份。

  2. 身份查看:在游戏开始后,所有玩家的身份都会以卡片形式呈现。你可以点击卡片来查看自己的身份,内容会显示"你是白板"或者对应的词语。

  3. 判决系统:所有玩家看完自己的身份后,可以通过"判决"按钮来猜测谁是卧底或白板。你输入认为是卧底或白板的玩家编号,无论猜测正确与否,都会减少一次判决机会。

  4. 剩余机会提示:每次判决后,系统会自动计算并提示你剩余的判决机会

  5. 胜负判定:如果你在机会用完前成功找出了所有的卧底和白板,游戏会提示平民获胜。如果机会用尽而卧底或白板还没被全部找出,游戏会提示失败。

效果图


源代码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>谁是卧底</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
            background-color: #1c1c2b;
            color: white;
        }
        .input-container {
            background-color: #2d2d44;
            padding: 20px;
            border-radius: 15px;
            box-shadow: 0 10px 25px rgba(0,0,0,0.3);
            margin-bottom: 20px;
            text-align: center;
        }
        h1 {
            margin-bottom: 15px;
            font-size: 24px;
            font-weight: bold;
        }
        label {
            display: block;
            margin-bottom: 10px;
            font-size: 18px;
        }
        input[type="number"] {
            width: 100px;
            padding: 8px;
            margin-bottom: 15px;
            border-radius: 10px;
            border: none;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
            text-align: center;
        }
        button {
            padding: 10px 20px;
            border: none;
            border-radius: 15px;
            background-color: #007BFF;
            color: white;
            font-size: 16px;
            cursor: pointer;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
        }
        .card-container {
            position: relative;
            width: 200px;
            height: 300px;
            perspective: 1000px;
        }
        .card {
            width: 100%;
            height: 100%;
            background-color: orange;
            border-radius: 15px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
            position: absolute;
            top: 0;
            left: 0;
            transition: transform 0.6s;
            transform-style: preserve-3d;
            cursor: pointer;
        }
        .card.flipped {
            transform: rotateY(180deg);
        }
        .card-content {
            position: absolute;
            width: 100%;
            height: 100%;
            backface-visibility: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
            color: white;
        }
        .card-content.back {
            transform: rotateY(180deg);
            background-color: #FFEB3B;
            border-radius: 15px;
        }
        .judge-button {
            display: none;
            padding: 20px 40px;
            border: none;
            border-radius: 25px;
            background-color: #FFD700;
            color: black;
            font-size: 20px;
            cursor: pointer;
            margin-top: 20px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
        }
    </style>
</head>
<body>

    <div class="input-container">
        <h1>谁是卧底游戏</h1>
        <label for="totalPlayers">总人数 (2-10):</label>
        <input type="number" id="totalPlayers" min="2" max="10">
        
        <label for="undercoverCount">卧底人数:</label>
        <input type="number" id="undercoverCount" min="1">
        
        <label for="blankCount">白板人数:</label>
        <input type="number" id="blankCount" min="0">
        <p></p>
        <button onclick="startGame()">开始游戏</button>
    </div>

    <div class="card-container" id="cardContainer">
        <!-- 卡片将会在这里生成 -->
    </div>

    <button class="judge-button" id="judgeButton" onclick="judge()">判决</button>

    <script>
        const wordsPairs = [
            ['苹果', '香蕉'],
            ['水泥', '瓷砖'],
            ['博客园', 'CSDN']
        ];

        let totalPlayers, undercoverCount, blankCount, civilians, undercovers, blanks;
        let remainingChances;
        let cardsFlipped = 0;

        function startGame() {
            totalPlayers = parseInt(document.getElementById('totalPlayers').value);
            undercoverCount = parseInt(document.getElementById('undercoverCount').value);
            blankCount = parseInt(document.getElementById('blankCount').value);

            if (isNaN(totalPlayers) || isNaN(undercoverCount) || isNaN(blankCount) || 
                totalPlayers < 2 || totalPlayers > 10 || 
                undercoverCount > totalPlayers || blankCount > totalPlayers ||
                blankCount > undercoverCount || (undercoverCount + blankCount) > totalPlayers) {
                alert('请检查输入,确保所有数值合理!');
                return;
            }

            civilians = totalPlayers - undercoverCount - blankCount;
            
            // 设置判决机会 = 白板数 + 卧底数 + 1
            remainingChances = blankCount + undercoverCount + 1;

            const wordPair = wordsPairs[Math.floor(Math.random() * wordsPairs.length)];
            undercovers = Array(undercoverCount).fill(wordPair[1]);
            blanks = Array(blankCount).fill('白板');
            const civiliansArr = Array(civilians).fill(wordPair[0]);

            const words = [...undercovers, ...blanks, ...civiliansArr].sort(() => Math.random() - 0.5);

            document.querySelector('.input-container').style.display = 'none';

            generateCards(words);
        }

        function generateCards(words) {
            const cardContainer = document.getElementById('cardContainer');
            cardContainer.innerHTML = '';

            words.forEach((word, index) => {
                const card = document.createElement('div');
                card.className = 'card';
                card.setAttribute('data-word', word);
                card.onclick = () => flipCard(card, index);

                const front = document.createElement('div');
                front.className = 'card-content front';
                front.innerText = '点击查看';

                const back = document.createElement('div');
                back.className = 'card-content back';
                back.innerText = word === '白板' ? '你是白板' : word;

                card.appendChild(front);
                card.appendChild(back);
                cardContainer.appendChild(card);

                card.style.zIndex = words.length - index;
                card.style.top = `${index * 5}px`;
                card.style.left = `${index * 5}px`;
            });
        }

        function flipCard(card, index) {
            if (card.classList.contains('flipped')) return;

            card.classList.add('flipped');
            cardsFlipped++;

            setTimeout(() => {
                card.style.display = 'none';
                if (cardsFlipped === totalPlayers) {
                    document.getElementById('judgeButton').style.display = 'block';
                }
            }, 1500);
        }

        function judge() {
            const guess = prompt('请输入你认为的卧底或白板编号(1-' + totalPlayers + '):');
            const guessIndex = parseInt(guess) - 1;
            if (isNaN(guessIndex) || guessIndex < 0 || guessIndex >= totalPlayers) {
                alert('无效的编号,请重新输入!');
                return;
            }

            const word = document.querySelectorAll('.card')[guessIndex].getAttribute('data-word');

            if (word === '白板' || word === undercovers[0]) {
                alert(`你找到了${word === '白板' ? '白板' : '卧底'},他们被淘汰了!`);
                document.querySelectorAll('.card')[guessIndex].remove();
                if (word === '白板') {
                    blanks.pop();
                } else {
                    undercovers.pop();
                }
            } else {
                alert('你猜错了!');
            }
            
            remainingChances--;
            alert('剩余机会: ' + remainingChances);

            if (undercovers.length === 0 && blanks.length === 0) {
                alert('平民获胜!');
                resetGame();
            } else if (remainingChances === 0) {
                alert('游戏失败!');
                resetGame();
            }
        }

        function resetGame() {
            document.querySelector('.input-container').style.display = 'block';
            document.getElementById('cardContainer').innerHTML = '';
            document.getElementById('judgeButton').style.display = 'none';
            cardsFlipped = 0;
        }
    </script>

</body>
</html>

游戏规则

1. 角色分配

  • 平民:多数玩家会被分配到同一个词语,这些玩家就是平民。平民的目标是找出谁是卧底。
  • 卧底:少数玩家(通常只有一人)会被分配到一个与平民词语类似但不同的词语。卧底的目标是混淆视听,让自己不被平民发现。
  • 白板(可选):某些版本中还有"白板"角色,他们不会得到任何词语,只能靠别人的描述来猜测其他人的身份。

2. 游戏流程

  • 第一轮:描述词语 每个玩家依次用一句话描述自己的词语,注意不能太直白,也不能过于模糊。平民需要小心描述,确保卧底不会轻易发现他们的词语,但又要让其他平民认出自己是同伴。卧底则需要假装自己是平民,在描述时尽量不暴露自己的词语。
  • 讨论与投票 一轮描述结束后,玩家可以互相讨论,并试图找出谁的描述最可疑。然后,所有玩家进行投票,选出他们认为是卧底的玩家。得票最多的玩家会被淘汰,并揭示自己的身份。
  • 下一轮 剩下的玩家继续进行描述和投票,直到所有的卧底被找出(平民获胜)或平民人数与卧底人数相等(卧底获胜)。

3. 胜负判定

  • 平民获胜:如果所有的卧底被投票淘汰,平民获胜。
  • 卧底获胜:如果卧底成功存活到剩下人数与卧底人数相等,卧底获胜。

4. 游戏策略

  • 平民需要通过描述、观察和推理来识别卧底的微妙差异。
  • 卧底则需要运用策略来隐藏自己的身份,并尽量让平民之间互相怀疑。
相关推荐
加勒比海涛12 分钟前
ElementUI 布局——行与列的灵活运用
前端·javascript·elementui
你不讲 wood16 分钟前
postcss 插件实现移动端适配
开发语言·前端·javascript·css·vue.js·ui·postcss
前端小程42 分钟前
使用vant UI实现时间段选择
前端·javascript·vue.js·ui
whyfail1 小时前
React 事件系统解析
前端·javascript·react.js
禾苗种树1 小时前
element form rules 验证数组对象属性时如何写判断规则
javascript·vue.js·elementui
liangshanbo12151 小时前
JavaScript 中的一些常见陷阱
开发语言·javascript·ecmascript
小tenten2 小时前
js延迟for内部循环方法
开发语言·前端·javascript
幻影浪子2 小时前
Web网站常用测试工具
前端·测试工具
我的运维人生2 小时前
JavaScript在网页设计中的应用案例
开发语言·javascript·ecmascript·运维开发·技术共享
暮志未晚Webgl2 小时前
94. UE5 GAS RPG 实现攻击击退效果
java·前端·ue5