宾果游戏Bingo

javascript 复制代码
<template>
    <div class="bingo-container">
      <h3>Bingo Game</h3>
      <div class="bingo-board">
        <div
          v-for="(cell, index) in boardFlat"
          :key="index"
          :class="['bingo-cell', { selected: cell.selected, bingo: cell.isBingo }]"
          :style="{ backgroundColor: cell.isBingo ? 'rgba(124, 76, 220, 1)' : cell.selected ? 'rgba(109, 45, 8, 1)' : 'lightgray' }"
          @click="markCell(index)"
        >
          {{ cell.number }}
        </div>
        <!-- 绘制所有胜利的线 -->
        <div
          v-for="(style, index) in bingoLines"
          :key="index"
          class="bingo-line"
          :style="style"
        ></div>
      </div>
      <button @click="resetGame">Reset Game</button>
    </div>
  </template>
  
  <script setup>
  import { ref, onMounted } from 'vue';
  
  const size = 5; // 5x5 Bingo board
  const boardFlat = ref([]); // One-dimensional array to store board cells
  const bingo = ref(false); // Bingo flag
  const bingoLines = ref([]); // Array to store styles for each winning line
  
  // Initialize the Bingo board
  const initBoard = () => {
    let numbers = Array.from({ length: size * size }, (_, i) => i + 1);
    numbers = shuffleArray(numbers);
    boardFlat.value = numbers.map(number => ({ number, selected: false, isBingo: false }));
  };
  
  // Shuffle the array of numbers
  const shuffleArray = (array) => {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  };
  
  // Mark a cell as selected
  const markCell = (index) => {
    if (boardFlat.value[index].selected) return; // Skip if already selected
    boardFlat.value[index].selected = true;
    checkBingo();
  };
  
  // Check for Bingo
  const checkBingo = () => {
    bingoLines.value = []; // Reset lines before checking
    const rows = Array(size).fill(0).map((_, i) => boardFlat.value.slice(i * size, (i + 1) * size));
    const cols = Array(size).fill(0).map((_, i) => rows.map(row => row[i]));
    const diag1 = Array(size).fill(0).map((_, i) => rows[i][i]);
    const diag2 = Array(size).fill(0).map((_, i) => rows[i][size - i - 1]);
  
    const checkLine = (line) => line.every(cell => cell.selected);
  
    // Check rows, columns, and diagonals, adding each winning line to bingoLines
    rows.forEach((line, i) => {
      if (checkLine(line)) {
        line.forEach(cell => (cell.isBingo = true));
        bingoLines.value.push(calculateLineStyle('row', i));
      }
    });
    cols.forEach((line, i) => {
      if (checkLine(line)) {
        line.forEach(cell => (cell.isBingo = true));
        bingoLines.value.push(calculateLineStyle('col', i));
      }
    });
    if (checkLine(diag1)) {
      diag1.forEach(cell => (cell.isBingo = true));
      bingoLines.value.push(calculateLineStyle('diag1'));
    }
    if (checkLine(diag2)) {
      diag2.forEach(cell => (cell.isBingo = true));
      bingoLines.value.push(calculateLineStyle('diag2'));
    }
  
    if (bingoLines.value.length > 0) {
      bingo.value = true;
    }
  };
  
  // Calculate the winning line style dynamically
  const calculateLineStyle = (type, index = 0) => {
    const cellSize = 49; // Each cell's width/height
    const gap = 11; // Gap between cells
    const padding = 27; // Board padding
  
    if (type === 'row') {
      const topPosition = padding + index * (cellSize + gap) + cellSize / 2 - 1.5;
      return {
        top: `${topPosition}px`,
        left: `${padding}px`,
        width: `${size * (cellSize + gap) - gap}px`, // Width covers 5 cells minus gaps
        height: '3px',
        position: 'absolute',
        backgroundColor: 'rgba(82, 33, 156, 1)',
      };
    } else if (type === 'col') {
      const leftPosition = padding + index * (cellSize + gap) + cellSize / 2 - 1.5;
      return {
        top: `${padding}px`,
        left: `${leftPosition}px`,
        height: `${size * (cellSize + gap) - gap}px`, // Height covers 5 cells minus gaps
        width: '3px',
        position: 'absolute',
        backgroundColor: 'rgba(82, 33, 156, 1)',
      };
    } else if (type === 'diag1') {
      return {
        top: `${padding}px`,
        left: `${padding}px`,
        width: `${Math.sqrt(2) * (size * cellSize + (size - 1) * gap)}px`,
        height: '3px',
        position: 'absolute',
        backgroundColor: 'rgba(82, 33, 156, 1)',
        transform: 'rotate(45deg)',
        transformOrigin: '0 0',
      };
    } else if (type === 'diag2') {
      return {
        top: `${padding}px`,
        right: `${padding}px`,
        width: `${Math.sqrt(2) * (size * cellSize + (size - 1) * gap)}px`,
        height: '3px',
        position: 'absolute',
        backgroundColor: 'rgba(82, 33, 156, 1)',
        transform: 'rotate(-45deg)',
        transformOrigin: '100% 0',
      };
    }
  };
  
  // Reset the game
  const resetGame = () => {
    bingo.value = false;
    bingoLines.value = [];
    initBoard(); // Reinitialize the board
  };
  
  // Initialize the Bingo board on mount
  onMounted(() => {
    initBoard();
  });
  </script>
  
  <style scoped>
  .bingo-container {
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  
  .bingo-board {
    position: relative;
    width: 343px;
    height: 342px;
    padding: 27px;
    display: grid;
    grid-template-columns: repeat(5, 49px);
    grid-template-rows: repeat(5, 49px);
    grid-gap: 11px;
    margin-top: 20px;
    box-sizing: border-box;
    background-color: white;
  }
  
  .bingo-cell {
    width: 49px;
    height: 49px;
    background-color: lightgray;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
  }
  
  .bingo-cell.selected {
    color: white;
  }
  
  .bingo-line {
    position: absolute;
    background-color: rgba(82, 33, 156, 1);
    z-index: 1;
  }
  
  button {
    margin-top: 20px;
  }
  </style>
  

以上是宾果的vue3代码 实现基础的选中变色,连线变色+bingo成线,同时检测多条的情况。

相关推荐
扯蛋43831 分钟前
LangChain的学习之路( 一 )
前端·langchain·mcp
Mr.Jessy40 分钟前
Web APIs学习第一天:获取 DOM 对象
开发语言·前端·javascript·学习·html
午安~婉40 分钟前
javaScript八股问题
开发语言·javascript·原型模式
西西学代码1 小时前
Flutter---个人信息(5)---持久化存储
java·javascript·flutter
芝麻开门-新起点1 小时前
flutter 生命周期管理:从 Widget 到 State 的完整解析
开发语言·javascript·ecmascript
ConardLi2 小时前
Easy Dataset 已经突破 11.5K Star,这次又带来多项功能更新!
前端·javascript·后端
冴羽2 小时前
10 个被严重低估的 JS 特性,直接少写 500 行代码
前端·javascript·性能优化
rising start2 小时前
四、CSS选择器(续)和三大特性
前端·css
一 乐2 小时前
高校后勤报修系统|物业管理|基于SprinBoot+vue的高校后勤报修系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·毕设
爱喝水的小周2 小时前
《UniApp 页面配置文件pages.json》
前端·uni-app·json