This commit is contained in:
Simon Cambier 2022-02-16 22:48:04 +01:00
parent ba01bba5dc
commit 93e8da4ab4
7 changed files with 93 additions and 38 deletions

View File

@ -1,8 +1,5 @@
import { reactive, ref, watch } from 'vue'
import { operators, pool } from './globals'
import { Operation, OperatorType, Plaquette } from './types'
import { randRange } from './utils'
import { operators } from './globals'
import { Operation, OperatorType } from './types'
type HistoryType = { a: number; b: number; op: OperatorType }[]

View File

@ -72,11 +72,11 @@ import {
isOperationResultValid,
operate,
} from '@/algo'
import { operations, plaquettes } from '@/game-state'
import { GameState, gameState } from '@/globals'
import { operations, plaquettes } from '@/store'
import { Operation } from '@/types'
import IconSad from '~icons/bx/bx-sad'
import IconUndo from '~icons/bx/bx-undo'
import IconSad from '~icons/ph/smiley-sad'
import PlaquetteBox from './common/PlaquetteBox.vue'

View File

@ -13,7 +13,7 @@
import { ref, watch } from 'vue'
const props = withDefaults(
defineProps<{ dynamicSize: boolean; is?: string }>(),
defineProps<{ dynamicSize?: boolean; is?: string }>(),
{
is: 'div',
dynamicSize: false,

View File

@ -1,9 +1,9 @@
import { computed, reactive, ref } from 'vue'
import { isOperationReady } from './algo'
import { getEmptyOperation, isOperationReady } from './algo'
import { Operation, Plaquette } from './types'
export const operations = reactive<Operation[]>([])
export const operations = reactive<Operation[]>([getEmptyOperation()])
export const plaquettes = ref<Plaquette[]>([])
export const result = ref(0)
@ -13,9 +13,11 @@ export const currentOperation = computed(
)
export const isEndGame = computed(
() => operations.length === 5 && isOperationReady(currentOperation.value),
() =>
(operations.length === 5 && isOperationReady(currentOperation.value)) ||
isResultPerfect.value,
)
export const isResultPerfect = computed(
() => currentOperation.value.result!.value === result.value,
() => !!operations.some(o => o.result?.value === result.value),
)

View File

@ -1,9 +1,16 @@
import { ref } from 'vue'
export const operators = ['+', '-', 'x', '/'] as const
export const pool = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100,
] as const
export const pools = {
1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25],
2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75],
3: [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75,
100,
],
4: [2, 2, 3, 3, 5, 5, 7, 11, 13, 17, 19, 23],
} as const
export enum GameState {
Undefined = 0,

View File

@ -1,6 +1,10 @@
{
"playAgain": "Rejouer",
"endGame.victoryLabel": "Bien joué !",
"endGame.failureLabel": "Presque",
"startGame": "Démarrer"
"endGame.victoryLabel": "Le compte est bon !",
"endGame.failureLabel": "Dommage...<br>Une autre partie ?",
"startGame": "Démarrer",
"easy": "facile",
"medium": "moyen",
"hard": "difficile",
"impossible": "☠"
}

View File

@ -10,7 +10,8 @@
:class="{
'text-green-400': difficultyLevel === 1,
'text-amber-400': difficultyLevel === 2,
'text-red-400': difficultyLevel === 3,
'text-orange-400': difficultyLevel === 3,
'text-red-500': difficultyLevel === 4,
}">
{{ result }}
</NumberBox>
@ -24,8 +25,23 @@
<div>
Combinez les nombres imposés afin de trouver le résultat ci-dessus, ou
de vous en approcher le plus possible.<br>
Le compteur démarre quand vous cliquez sur le bouton.<br>Partagez vos
meilleurs temps !
Le compteur démarre quand vous cliquez sur le bouton.<br>Partagez
vos meilleurs temps !
</div>
<div
class="my-4 font-bold"
:class="{
'text-green-400': difficultyLevel === 1,
'text-amber-400': difficultyLevel === 2,
'text-orange-400': difficultyLevel === 3,
'text-red-500': difficultyLevel === 4,
}">
Niveau de difficulté :
<span v-if="difficultyLevel < 4">{{ difficultyLabel }}</span>
<IconSkull
class="inline"
v-else />
</div>
<button
@ -58,13 +74,14 @@
<Transition name="slide_up">
<div v-if="gameIsRunning">
<div class="flex gap-2 justify-center my-4">
<NumberBox
<PlaquetteBox
is="button"
class="aspect-square w-[1.5em] text-2xl"
@click="selectOperator(item)"
v-for="(item, i) in operators"
:key="i">
{{ item }}
</NumberBox>
</PlaquetteBox>
</div>
<!-- Divider -->
@ -78,9 +95,13 @@
<Transition name="slide_up">
<div
v-if="isEndGame"
class="flex flex-row justify-evenly items-center mt-8">
<span v-if="isResultPerfect">{{ t('endGame.victoryLabel') }}</span>
<span v-else>{{ t('endGame.failureLabel') }}</span>
class="flex flex-row justify-evenly items-center mx-auto mt-8 max-w-sm">
<span
v-if="isResultPerfect"
v-html="t('endGame.victoryLabel')" />
<span
v-else
v-html="t('endGame.failureLabel')" />
<button
class="p-2 rounded border"
@click="reboot">
@ -105,7 +126,6 @@ import {
import NumberBox from '@/components/common/NumberBox.vue'
import PlaquetteBox from '@/components/common/PlaquetteBox.vue'
import OperationsList from '@/components/OperationsList.vue'
import { GameState, gameState, operators, pool } from '@/globals'
import {
currentOperation,
isEndGame,
@ -113,9 +133,11 @@ import {
operations,
plaquettes,
result,
} from '@/store'
} from '@/game-state'
import { GameState, gameState, operators, pools } from '@/globals'
import { OperatorType, Plaquette } from '@/types'
import { randItem, randRange } from '@/utils'
import IconSkull from '~icons/ph/skull'
const { t } = useI18n() // call `useI18n`, and spread `t` from `useI18n` returning
@ -132,6 +154,7 @@ const shownPlaquettes = computed(() =>
onMounted(() => {
reboot()
gameState.value = GameState.Waiting
})
watch(
@ -142,7 +165,7 @@ watch(
free: true,
value: operate(op.operator!, op.left!.value, op.right!.value),
}
if (operations.length < 5) {
if (operations.length < 5 && !isEndGame.value) {
plaquettes.value.push(op.result)
operations.push(getEmptyOperation())
}
@ -157,6 +180,7 @@ function startGame(): void {
}
function selectNumber(p: Plaquette): void {
if (isEndGame.value) return
initDelay.value = 0
const op = currentOperation.value
@ -173,39 +197,60 @@ function selectNumber(p: Plaquette): void {
}
function selectOperator(o: OperatorType): void {
if (gameState.value !== GameState.Playing) return
if (isEndGame.value) return
currentOperation.value.operator = o
}
const difficultyLevel = randItem([1, 1, 1, 1, 1, 1, 2, 2, 2, 3])
const difficultyLevel = ref<1 | 2 | 3 | 4>(1)
const difficultyLabel = computed(() => {
switch (difficultyLevel.value) {
case 1:
return t('easy')
case 2:
return t('medium')
case 3:
return t('hard')
default:
return t('impossible')
}
})
function reboot(): void {
gameState.value = GameState.Waiting
gameState.value = GameState.Playing
do {
// Find a problem
// result.value = randRange(101, 1000)
difficultyLevel.value = randItem([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4])
result.value = (() => {
switch (difficultyLevel) {
switch (difficultyLevel.value) {
case 1:
return randRange(101, 25)
return randRange(80, 200)
case 2:
return randRange(251, 500)
default:
return randRange(501, 1000)
return randRange(201, 400)
case 3:
return randRange(401, 1000)
case 4:
return randRange(50, 1000)
}
})()
// result.value = 29
// Reset Operations list
operations.splice(0)
operations.push(getEmptyOperation())
// Generate result and plaquettes
plaquettes.value = []
const poolCopy = [...pool]
const poolCopy = [...pools[difficultyLevel.value]]
for (let i = 0; i < 6; ++i) {
const random = Math.floor(Math.random() * poolCopy.length)
const el = poolCopy.splice(random, 1)[0]
plaquettes.value.push({ value: el, free: true })
}
// plaquettes.value = [4, 8, 10, 25, 50, 100].map(value => ({
// free: true,
// value,
// }))
// Solve it
} while (
!isSolvable(