MVP ok
This commit is contained in:
		
							parent
							
								
									ba01bba5dc
								
							
						
					
					
						commit
						93e8da4ab4
					
				| 
						 | 
				
			
			@ -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 }[]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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": "☠"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user