Amélioration intéraction, game over + check cases numéro
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { genCellGrid, genMineGrid, cliqueGauche, cliqueDroit } from '@/utils/game'
|
||||
import { ref, watch, onMounted, onUnmounted } from 'vue'
|
||||
import { getDirections, genCellGrid, genMineGrid, cliqueGauche, cliqueDroit } from '@/utils/game'
|
||||
import type { CellGrid, MineGrid } from '@/utils/game'
|
||||
|
||||
// Variables du jeu
|
||||
const width = 10
|
||||
const length = 15
|
||||
const nbMines = 25
|
||||
@@ -13,48 +14,111 @@ cellGrid.value = genCellGrid(width, length)
|
||||
|
||||
// Création grille des mines
|
||||
let mineGrid: MineGrid = []
|
||||
mineGrid = genMineGrid(width, length, nbMines)
|
||||
|
||||
// État du jeu
|
||||
const gameStatus = ref(0) // 0: vide, 1: en cours, 2: gagné, 3: perdu
|
||||
const timer = ref(0)
|
||||
let timerInterval: number | undefined = undefined
|
||||
|
||||
watch(gameStatus, async (status) => {
|
||||
if (status === 1) {
|
||||
timerInterval = setInterval(() => timer.value++, 1000)
|
||||
} else {
|
||||
if (timerInterval !== null) clearInterval(timerInterval)
|
||||
if (status === 2) alert('Vous avez gagné !')
|
||||
if (status === 3) alert('Vous avez perdu !')
|
||||
}
|
||||
})
|
||||
|
||||
// État pour gérer le clic et la position de la cellule
|
||||
const isMouseDown = ref(false)
|
||||
const currentCell = ref<{ rowIndex: number, cellIndex: number } | null>(null)
|
||||
|
||||
// État pour suivre les cases surlignées
|
||||
const highlightedCells = ref<number[][]>([])
|
||||
|
||||
// Gestion des événements de clic et de la position de la cellule
|
||||
const handleMouseDown = (rowIndex: number, cellIndex: number) => {
|
||||
isMouseDown.value = true
|
||||
currentCell.value = { rowIndex, cellIndex }
|
||||
if (cellGrid.value[rowIndex][cellIndex] === '/sUnknown.png') cellGrid.value[rowIndex][cellIndex] = '/sClick.png'
|
||||
const cellValue = cellGrid.value[rowIndex][cellIndex]
|
||||
|
||||
if (cellValue === '/sUnknown.png') cellGrid.value[rowIndex][cellIndex] = '/sClick.png' // Si la cellule est inconnue, on la vérifie
|
||||
else if (/\/s\d\.png$/.test(cellValue)) highlightAdjacentUnknownCells(cellIndex, rowIndex) // Vérifie si la cellule contient un chiffre
|
||||
|
||||
}
|
||||
|
||||
const handleMouseUp = (rowIndex: number, cellIndex: number) => {
|
||||
// Gestion des événements de relâchement de clic et de la position de la cellule
|
||||
const handleMouseUp = async (rowIndex: number, cellIndex: number) => {
|
||||
isMouseDown.value = false
|
||||
cliqueGauche(cellGrid.value, mineGrid, cellIndex, rowIndex)
|
||||
if (!mineGrid.length) {
|
||||
mineGrid = genMineGrid(width, length, nbMines, cellIndex, rowIndex)
|
||||
gameStatus.value = 1
|
||||
}
|
||||
|
||||
cliqueGauche(gameStatus.value, cellGrid.value, mineGrid, cellIndex, rowIndex)
|
||||
currentCell.value = null
|
||||
|
||||
// Réinitialiser les cases surlignées
|
||||
for (const [dx, dy] of highlightedCells.value) { if (cellGrid.value[dy][dx] === '/sHighlight.png') cellGrid.value[dy][dx] = '/sUnknown.png' }
|
||||
highlightedCells.value = []
|
||||
}
|
||||
|
||||
// Gestion des événements de déplacement de la souris et de la position de la cellule
|
||||
const handleMouseMove = (rowIndex: number, cellIndex: number) => {
|
||||
if (isMouseDown.value && currentCell.value) {
|
||||
const { rowIndex: prevRowIndex, cellIndex: prevCellIndex } = currentCell.value
|
||||
|
||||
if (prevRowIndex !== rowIndex || prevCellIndex !== cellIndex) {
|
||||
if (cellGrid.value[prevRowIndex][prevCellIndex] === '/sClick.png') cellGrid.value[prevRowIndex][prevCellIndex] = '/sUnknown.png' // Réinitialiser l'image précédente
|
||||
if (cellGrid.value[rowIndex][cellIndex] === '/sUnknown.png') cellGrid.value[rowIndex][cellIndex] = '/sClick.png' // Changer l'image actuelle
|
||||
const cellValue = cellGrid.value[rowIndex][cellIndex]
|
||||
|
||||
// Réinitialiser les cases surlignées
|
||||
for (const [dx, dy] of highlightedCells.value) { cellGrid.value[dy][dx] = '/sUnknown.png' }
|
||||
highlightedCells.value = []
|
||||
|
||||
// Changer l'image actuelle
|
||||
if (cellValue === '/sUnknown.png') cellGrid.value[rowIndex][cellIndex] = '/sClick.png'
|
||||
else if (/\/s\d\.png$/.test(cellValue)) highlightAdjacentUnknownCells(cellIndex, rowIndex)
|
||||
|
||||
// Réinitialiser l'image précédente
|
||||
const prevCellValue = cellGrid.value[prevRowIndex][prevCellIndex]
|
||||
if (prevCellValue === '/sClick.png') cellGrid.value[prevRowIndex][prevCellIndex] = '/sUnknown.png'
|
||||
|
||||
currentCell.value = { rowIndex, cellIndex }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gestion des événements de déplacement de la souris et de la position de la cellule
|
||||
const handleGlobalMouseMove = (event: MouseEvent) => {
|
||||
if (isMouseDown.value && currentCell.value) {
|
||||
const target = event.target as HTMLElement
|
||||
|
||||
if (!target.classList.contains('cell')) {
|
||||
const { rowIndex, cellIndex } = currentCell.value
|
||||
if (cellGrid.value[rowIndex][cellIndex] === '/sClick.png') {
|
||||
cellGrid.value[rowIndex][cellIndex] = '/sUnknown.png'
|
||||
}
|
||||
|
||||
if (cellGrid.value[rowIndex][cellIndex] === '/sClick.png') cellGrid.value[rowIndex][cellIndex] = '/sUnknown.png'
|
||||
currentCell.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour surligner toutes les cases adjacentes inconnues
|
||||
const highlightAdjacentUnknownCells = (cellIndex: number, rowIndex: number) => {
|
||||
const directions = getDirections(cellIndex, rowIndex)
|
||||
|
||||
highlightedCells.value = [] // Réinitialiser la liste des cases surlignées
|
||||
|
||||
for (const [dx, dy] of directions) {
|
||||
if (dx < 0 || dx >= cellGrid.value[0].length || dy < 0 || dy >= cellGrid.value.length) continue
|
||||
if (cellGrid.value[dy][dx] === '/sUnknown.png') {
|
||||
cellGrid.value[dy][dx] = '/sHighlight.png'
|
||||
highlightedCells.value.push([dx, dy])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Écoute des événements de déplacement de la souris
|
||||
onMounted(() => document.addEventListener('mousemove', handleGlobalMouseMove))
|
||||
onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMove))
|
||||
</script>
|
||||
@@ -62,6 +126,7 @@ onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMov
|
||||
<template>
|
||||
<div class="main">
|
||||
<h1>Solo</h1>
|
||||
<div class="timer" :gameStatus>{{ timer }}</div>
|
||||
<div class="grid">
|
||||
<div v-for="(row, rowIndex) in cellGrid" :key="rowIndex" class="row">
|
||||
<div v-for="(cell, cellIndex) in row" :key="cellIndex">
|
||||
@@ -77,6 +142,13 @@ onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMov
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<div v-for="(row, rowIndex) in cellGrid" :key="rowIndex" class="row">
|
||||
<div v-for="(cell, cellIndex) in row" :key="cellIndex">
|
||||
<img class="cell" :src="mineGrid.some(mine => mine[0] === cellIndex && mine[1] === rowIndex) ? '/sMine.png' : '/sEmpty.png'" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user