Assemblage du menu du jeu et découverte cases améliorée
This commit is contained in:
@@ -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 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow-x: auto;
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
padding: 2rem 2rem;
|
||||
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;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.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%;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<CellGrid>([])
|
||||
@@ -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
|
||||
<div class="main">
|
||||
<div class="space">
|
||||
<h1>Solo</h1>
|
||||
<div class="timer" :gameStatus>Timer : {{ timer }}</div>
|
||||
<div class="timer" :gameStatus>{{ formatTime(timer) }}</div>
|
||||
</div>
|
||||
|
||||
<div class="menu">
|
||||
<input type="number" v-model="width" min="10" max="50" />Lignes (10-50)
|
||||
<input type="number" v-model="length" min="10" max="50" />Colonnes (10-50)
|
||||
<input type="number" v-model="nbMines" min="10" max="250" />Mines (10-250)
|
||||
<button @click="gameStatus = 0">Nouvelle partie</button>
|
||||
<div class="presets">
|
||||
<button class="rounded" @click="width = 10; length = 15; nbMines = 20">Facile</button>
|
||||
<button class="rounded" @click="width = 20; length = 50; nbMines = 180">Moyen</button>
|
||||
<button class="rounded" @click="width = 50; length = 80; nbMines = 800">Difficile</button>
|
||||
<button class="rounded" @click="width = 100; length = 100; nbMines = 2000">Extrême</button>
|
||||
</div>
|
||||
|
||||
<div class="inputs">
|
||||
<div>
|
||||
<label for="length">Colonnes</label>
|
||||
<input type="number" v-model="length" min="10" max="50" id="length" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="width">Lignes</label>
|
||||
<input type="number" v-model="width" min="10" max="50" id="width" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="nbMines">Mines</label>
|
||||
<input type="number" v-model="nbMines" min="10" max="250" id="nbMines" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="rounded newgame" @click="startNewGame">Nouvelle partie</button>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
@@ -145,6 +192,7 @@ onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMov
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<transition name="fade">
|
||||
<div v-if="gameStatus === 2" class="message">Vous avez gagné !</div>
|
||||
<div v-else-if="gameStatus === 3" class="message">Vous avez perdu !</div>
|
||||
@@ -153,38 +201,7 @@ onUnmounted(() => document.removeEventListener('mousemove', handleGlobalMouseMov
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.space {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
margin: 30px 60px;
|
||||
h1 {
|
||||
flex: 2;
|
||||
}
|
||||
}
|
||||
.menu {
|
||||
flex: 2;
|
||||
display: flex;
|
||||
input {
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
.grid {
|
||||
display: grid;
|
||||
border: 4px solid rgb(65, 65, 65);
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
height: 32px;
|
||||
}
|
||||
.cell {
|
||||
flex: 1;
|
||||
background-color: #f1f1f1;
|
||||
text-align: center;
|
||||
color: black;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
user-select: none;
|
||||
.main {
|
||||
gap: 0
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user