宾果游戏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成线,同时检测多条的情况。

相关推荐
bin91532 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
晴空万里藏片云3 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
曦月合一3 小时前
html中iframe标签 隐藏滚动条
前端·html·iframe
奶球不是球3 小时前
el-button按钮的loading状态设置
前端·javascript
kidding7233 小时前
前端VUE3的面试题
前端·typescript·compositionapi·fragment·teleport·suspense
无责任此方_修行中5 小时前
每周见闻分享:杂谈AI取代程序员
javascript·资讯
Σίσυφος19005 小时前
halcon 条形码、二维码识别、opencv识别
前端·数据库
学代码的小前端5 小时前
0基础学前端-----CSS DAY13
前端·css
dorabighead6 小时前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
css趣多多7 小时前
案例自定义tabBar
前端