diff --git a/src/assets/main.css b/src/assets/main.css index ef4840b..7c62f56 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -49,7 +49,7 @@ a, .sidenav { position: fixed; z-index: 1; - width: 203px; /* 200px is the width of the header vl position */ + width: 203px; /* 200px is the width of the header vl position + half the bar */ background-color: #111; } @@ -67,16 +67,132 @@ a, /* PAGE CONTENT */ .main { - margin-top: 40px; /* 60px is the height of the header navbar */ - height: calc(100% - 40px); - padding: 2rem 2rem; display: flex; flex-direction: column; - align-items: center; justify-content: center; - gap: 10px; + align-items: center; + overflow-x: auto; + width: 100%; + height: calc(100% - 40px); + margin-top: 40px; /* 40px is the height of the header navbar */ + padding: 2rem; + gap: 20px; } +/* GAME BOARD */ +.space { + display: flex; + justify-content: end; /* Centre les deux éléments horizontalement */ + width: 100%; + gap: 20px; /* Ajoute un espacement entre le h1 et le timer */ +} + +.space h1 { + font-weight: bold; + font-size: 20px; +} + +.timer { + text-align: center; + width: 135px; + border-radius: 10px; + border: 2px solid #555; + background-color: #333; + color: white; + font-weight: bold; + font-size: 22px; +} + +.menu { + display: flex; + justify-content: space-between; /* Aligne les deux groupes à gauche et à droite */ + width: 100%; /* Prend toute la largeur disponible */ + margin-top: -5px; + margin-bottom: 10px; +} + +.menu button { + cursor: pointer; + height: 36px; + color: white; + border-radius: 10px; + font-size: 16px; +} + +.presets { + flex: auto; + display: flex; + align-items: center; + gap: 10px; /* Ajoute un espacement entre les boutons */ +} + +.presets button { + width: 75px; + height: 50px; + background-color: #3f77ff; + border: 2px solid #7aa0ff; +} + +.presets button:hover { + background-color: #1c5dff; +} + +.inputs { + display: flex; + align-items: center; + gap: 10px; /* Ajoute un espacement entre les inputs */ + margin-right: 20px; +} + +.inputs div { + display: flex; + flex-direction: column; + align-items: center; +} + +.inputs label { + font-weight: bold; + font-size: 14px; +} + +.inputs input { + text-align: center; + width: 80px; + padding: 5px; + border: 1px solid #ccc; + border-radius: 5px; +} + +.newgame { + width: 135px; + margin-top: 15px; + background-color: #4CAF50; + border: 2px solid #6bdf6f; +} + +.newgame:hover { + background-color: #3b8a3f; +} + +.grid { + display: grid; + border: 4px solid rgb(65, 65, 65); +} + +.row { + display: flex; +} + +.cell { + background-color: #f1f1f1; + text-align: center; + color: black; + width: 32px; + height: 32px; + user-select: none; +} + +/* FORMATTING AND EFFECTS */ .rounded { border-radius: 20%; } diff --git a/src/utils/game.ts b/src/utils/game.ts index 1afab9d..e496205 100644 --- a/src/utils/game.ts +++ b/src/utils/game.ts @@ -69,8 +69,12 @@ function checkCell(cellGrid: CellGrid, mineGrid: MineGrid, x: number, y: number) } // Si la cellule a des mines adjacentes, afficher le nombre de mines - if (minesAdjacentes > 0) cellGrid[y][x] = `/s${minesAdjacentes}.png` - else { + if (minesAdjacentes > 0) { + cellGrid[y][x] = `/s${minesAdjacentes}.png` + + const result = revealCell(cellGrid, mineGrid, x, y) + if (result !== 0) return result + } else { cellGrid[y][x] = '/sEmpty.png' for (const [dx, dy] of directions) { if (dx >= 0 && dx < cellGrid[0].length && dy >= 0 && dy < cellGrid.length && cellGrid[dy][dx] === '/sUnknown.png') { @@ -100,7 +104,7 @@ function revealCell(cellGrid: CellGrid, mineGrid: MineGrid, x: number, y: number const cellValue = parseInt(cellGrid[y][x].match(/\/s(\d)\.png$/)?.[1] || '0') if (flagCount === cellValue) { for (const [dx, dy] of directions) { - if (dx >= 0 && dx < cellGrid[0].length && dy >= 0 && dy < cellGrid.length && cellGrid[dy][dx] === '/sHighlight.png') { + if (dx >= 0 && dx < cellGrid[0].length && dy >= 0 && dy < cellGrid.length && (cellGrid[dy][dx] === '/sHighlight.png' || cellGrid[dy][dx] === '/sUnknown.png')) { cellGrid[dy][dx] = '/sUnknown.png' const result = checkCell(cellGrid, mineGrid, dx, dy) diff --git a/src/views/Game/SoloView.vue b/src/views/Game/SoloView.vue index 190d2a9..0001b3c 100644 --- a/src/views/Game/SoloView.vue +++ b/src/views/Game/SoloView.vue @@ -6,7 +6,7 @@ import type { CellGrid, MineGrid } from '@/utils/game' // Variables du jeu const width = ref(10) const length = ref(15) -const nbMines = ref(25) +const nbMines = ref(20) // Création grille des cases const cellGrid = ref([]) @@ -18,11 +18,39 @@ let mineGrid: MineGrid = [] // É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 +let timerInterval: number | null = null +// Fonction pour démarrer une nouvelle partie +const startNewGame = () => { + gameStatus.value = 0 + timer.value = 0 + cellGrid.value = genCellGrid(width.value, length.value) +} + +// Formater le timer en heure:minute:seconde +const formatTime = (seconds: number) => { + const hours = Math.floor(seconds / 3600) + const minutes = Math.floor((seconds % 3600) / 60) + const secs = seconds % 60 + + // Si les heures sont 0, ne pas les afficher + const hoursDisplay = hours > 0 ? `${hours}:` : '' + // Afficher les minutes sans padding de 0 + const minutesDisplay = `${minutes}:` + // Toujours afficher les secondes avec un padding de 0 + const secondsDisplay = String(secs).padStart(2, '0') + + return `${hoursDisplay}${minutesDisplay}${secondsDisplay}` +} + +// Watch pour démarrer ou arrêter le timer selon l'état du jeu watch(gameStatus, async (status) => { + if (status === 0) { + timer.value = 0 + cellGrid.value = genCellGrid(width.value, length.value) + } if (status === 1) timerInterval = setInterval(() => timer.value++, 1000) - else clearInterval(timerInterval) + else if (timerInterval) clearInterval(timerInterval) }) // État pour gérer le clic et la position de la cellule @@ -46,7 +74,7 @@ const handleMouseDown = (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 - if (!mineGrid.length) { + if (!gameStatus.value) { mineGrid = genMineGrid(width.value, length.value, nbMines.value, cellIndex, rowIndex) gameStatus.value = 1 } @@ -122,14 +150,33 @@ onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMov

Solo

-
Timer : {{ timer }}
+
{{ formatTime(timer) }}
+
- +
Vous avez gagné !
Vous avez perdu !
@@ -153,38 +201,7 @@ onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMov \ No newline at end of file