Gameplay loop ok
This commit is contained in:
parent
6232c2f682
commit
aa3c4dfcfc
|
@ -6,9 +6,6 @@ import { randRange } from './utils'
|
||||||
|
|
||||||
type HistoryType = { a: number; b: number; op: OperatorType }[]
|
type HistoryType = { a: number; b: number; op: OperatorType }[]
|
||||||
|
|
||||||
export const operations = reactive<Operation[]>([])
|
|
||||||
export const plaquettes = ref<Plaquette[]>([])
|
|
||||||
|
|
||||||
export function isOperationResultValid(op: Operation): boolean {
|
export function isOperationResultValid(op: Operation): boolean {
|
||||||
return (
|
return (
|
||||||
!!op.operator &&
|
!!op.operator &&
|
||||||
|
@ -24,11 +21,7 @@ export function isOperationInvalid(op: Operation): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isOperationReady(op: Operation): boolean {
|
export function isOperationReady(op: Operation): boolean {
|
||||||
return (
|
return !!op.operator && !!op.left && !!op.right
|
||||||
!!op.operator &&
|
|
||||||
!!op.left &&
|
|
||||||
!!op.right
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEmptyOperation(): Operation {
|
export function getEmptyOperation(): Operation {
|
||||||
|
|
|
@ -29,7 +29,9 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- RESULT -->
|
<!-- RESULT -->
|
||||||
<PlaquetteBox :dynamic-size="true" class="w-[3.2em] border-none">
|
<PlaquetteBox
|
||||||
|
:dynamic-size="true"
|
||||||
|
class="w-[3.2em] h-8 border-none">
|
||||||
<IconSad v-if="isOperationInvalid(op)" />
|
<IconSad v-if="isOperationInvalid(op)" />
|
||||||
<span
|
<span
|
||||||
v-else-if="
|
v-else-if="
|
||||||
|
@ -37,8 +39,10 @@
|
||||||
">
|
">
|
||||||
{{ operate(op.operator, op.left.value, op.right.value) }}
|
{{ operate(op.operator, op.left.value, op.right.value) }}
|
||||||
</span>
|
</span>
|
||||||
<IconQuestion v-else />
|
<span v-else>?</span>
|
||||||
</PlaquetteBox>
|
</PlaquetteBox>
|
||||||
|
|
||||||
|
<!-- UNDO -->
|
||||||
<button
|
<button
|
||||||
class="ml-8"
|
class="ml-8"
|
||||||
@click="undoOperation(i)">
|
@click="undoOperation(i)">
|
||||||
|
@ -60,15 +64,13 @@ import {
|
||||||
isOperationInvalid,
|
isOperationInvalid,
|
||||||
isOperationResultValid,
|
isOperationResultValid,
|
||||||
operate,
|
operate,
|
||||||
operations,
|
|
||||||
plaquettes,
|
|
||||||
} from '@/algo'
|
} from '@/algo'
|
||||||
|
import { GameState, gameState } from '@/globals'
|
||||||
|
import { operations, plaquettes } from '@/store'
|
||||||
import { Operation } from '@/types'
|
import { Operation } from '@/types'
|
||||||
import IconQuestion from '~icons/bx/bx-question-mark'
|
|
||||||
import IconSad from '~icons/bx/bx-sad'
|
import IconSad from '~icons/bx/bx-sad'
|
||||||
import IconUndo from '~icons/bx/bx-undo'
|
import IconUndo from '~icons/bx/bx-undo'
|
||||||
|
|
||||||
import NumberBox from './common/NumberBox.vue'
|
|
||||||
import PlaquetteBox from './common/PlaquetteBox.vue'
|
import PlaquetteBox from './common/PlaquetteBox.vue'
|
||||||
|
|
||||||
const transDelay = 100
|
const transDelay = 100
|
||||||
|
@ -78,9 +80,9 @@ function canOperationBeDeleted(op: Operation): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
function undoOperation(index: number): void {
|
function undoOperation(index: number): void {
|
||||||
|
if (gameState.value !== GameState.Playing) return
|
||||||
const l = operations.length
|
const l = operations.length
|
||||||
for (let i = operations.length - 1; i >= index; --i) {
|
for (let i = operations.length - 1; i >= index; --i) {
|
||||||
console.log(i)
|
|
||||||
let popped: Operation
|
let popped: Operation
|
||||||
if (i === index) {
|
if (i === index) {
|
||||||
popped = operations[index]
|
popped = operations[index]
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<Component
|
||||||
|
:is="is"
|
||||||
class="flex overflow-hidden justify-center font-bold rounded border border-stone-600 transition-all"
|
class="flex overflow-hidden justify-center font-bold rounded border border-stone-600 transition-all"
|
||||||
:class="[textSize]">
|
:class="[textSize]">
|
||||||
<span
|
<span
|
||||||
class="self-center text-center"
|
class="self-center text-center"
|
||||||
ref="content"><slot /></span>
|
ref="content"><slot /></span>
|
||||||
</div>
|
</Component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{ dynamicSize: boolean }>(),
|
defineProps<{ dynamicSize: boolean; is?: string }>(),
|
||||||
{
|
{
|
||||||
|
is: 'div',
|
||||||
dynamicSize: false,
|
dynamicSize: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
export const operators = ['+', '-', 'x', '/'] as const
|
export const operators = ['+', '-', 'x', '/'] as const
|
||||||
export const pool = [
|
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,
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100,
|
||||||
|
@ -8,3 +10,5 @@ export enum GameState {
|
||||||
Lost,
|
Lost,
|
||||||
Won,
|
Won,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const gameState = ref(GameState.Playing)
|
||||||
|
|
6
src/store.ts
Normal file
6
src/store.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { reactive, ref } from 'vue'
|
||||||
|
|
||||||
|
import { Operation, Plaquette } from './types'
|
||||||
|
|
||||||
|
export const operations = reactive<Operation[]>([])
|
||||||
|
export const plaquettes = ref<Plaquette[]>([])
|
|
@ -20,11 +20,12 @@
|
||||||
class="grid grid-cols-6 grid-rows-2 gap-2 justify-center px-2 mx-auto max-w-sm">
|
class="grid grid-cols-6 grid-rows-2 gap-2 justify-center px-2 mx-auto max-w-sm">
|
||||||
<TransitionGroup name="slide_left">
|
<TransitionGroup name="slide_left">
|
||||||
<PlaquetteBox
|
<PlaquetteBox
|
||||||
|
is="button"
|
||||||
|
@click="selectNumber(item)"
|
||||||
:dynamic-size="true"
|
:dynamic-size="true"
|
||||||
class="col-start-auto h-11"
|
class="h-11"
|
||||||
:class="{ 'text-stone-600 border-stone-600': !item.free }"
|
:class="{ 'text-stone-600 border-stone-600': !item.free }"
|
||||||
:style="{ transitionDelay: `${initDelay * i}ms` }"
|
:style="{ transitionDelay: `${initDelay * i}ms` }"
|
||||||
@click="selectNumber(item)"
|
|
||||||
v-for="(item, i) in plaquettes"
|
v-for="(item, i) in plaquettes"
|
||||||
:key="i">
|
:key="i">
|
||||||
{{ item.value }}
|
{{ item.value }}
|
||||||
|
@ -45,7 +46,19 @@
|
||||||
|
|
||||||
<div class="my-4 mx-auto max-w-sm border-b" />
|
<div class="my-4 mx-auto max-w-sm border-b" />
|
||||||
|
|
||||||
|
<!-- List of Operations -->
|
||||||
<OperationsList />
|
<OperationsList />
|
||||||
|
|
||||||
|
<div class="flex justify-evenly items-center mt-8">
|
||||||
|
<Transition name="slide_up">
|
||||||
|
<button
|
||||||
|
v-if="gameState === GameState.Won"
|
||||||
|
class="p-2 rounded border"
|
||||||
|
@click="reboot">
|
||||||
|
Rejouer
|
||||||
|
</button>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -58,21 +71,17 @@ import {
|
||||||
isOperationResultValid,
|
isOperationResultValid,
|
||||||
isSolvable,
|
isSolvable,
|
||||||
operate,
|
operate,
|
||||||
operations,
|
|
||||||
plaquettes,
|
|
||||||
} from '@/algo'
|
} from '@/algo'
|
||||||
import NumberBox from '@/components/common/NumberBox.vue'
|
import NumberBox from '@/components/common/NumberBox.vue'
|
||||||
import PlaquetteBox from '@/components/common/PlaquetteBox.vue'
|
import PlaquetteBox from '@/components/common/PlaquetteBox.vue'
|
||||||
import OperationsList from '@/components/OperationsList.vue'
|
import OperationsList from '@/components/OperationsList.vue'
|
||||||
import { GameState, operators, pool } from '@/globals'
|
import { GameState, gameState, operators, pool } from '@/globals'
|
||||||
|
import { operations, plaquettes } from '@/store'
|
||||||
import { OperatorType, Plaquette } from '@/types'
|
import { OperatorType, Plaquette } from '@/types'
|
||||||
import { randItem, randRange } from '@/utils'
|
import { randItem, randRange } from '@/utils'
|
||||||
|
|
||||||
const result = ref(0)
|
const result = ref(0)
|
||||||
const initDelay = ref(100)
|
const initDelay = ref(100)
|
||||||
const currentState = ref(GameState.Playing)
|
|
||||||
|
|
||||||
operations.push(getEmptyOperation())
|
|
||||||
|
|
||||||
const currentOperation = computed(() => operations[operations.length - 1])
|
const currentOperation = computed(() => operations[operations.length - 1])
|
||||||
|
|
||||||
|
@ -84,11 +93,12 @@ watch(
|
||||||
free: true,
|
free: true,
|
||||||
value: operate(op.operator!, op.left!.value, op.right!.value),
|
value: operate(op.operator!, op.left!.value, op.right!.value),
|
||||||
}
|
}
|
||||||
plaquettes.value.push(op.result)
|
|
||||||
if (op.result.value === result.value) {
|
if (op.result.value === result.value) {
|
||||||
// Winner
|
// Winner
|
||||||
|
gameState.value = GameState.Won
|
||||||
}
|
}
|
||||||
else {
|
else if (operations.length < 5) {
|
||||||
|
plaquettes.value.push(op.result)
|
||||||
operations.push(getEmptyOperation())
|
operations.push(getEmptyOperation())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,12 +123,14 @@ function selectNumber(p: Plaquette): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectOperator(o: OperatorType): void {
|
function selectOperator(o: OperatorType): void {
|
||||||
|
if (gameState.value !== GameState.Playing) return
|
||||||
currentOperation.value.operator = o
|
currentOperation.value.operator = o
|
||||||
}
|
}
|
||||||
|
|
||||||
const difficultyLevel = randItem([1, 1, 1, 1, 1, 1, 2, 2, 2, 3])
|
const difficultyLevel = randItem([1, 1, 1, 1, 1, 1, 2, 2, 2, 3])
|
||||||
|
|
||||||
onMounted(() => {
|
function reboot(): void {
|
||||||
|
gameState.value = GameState.Playing
|
||||||
do {
|
do {
|
||||||
// Find a problem
|
// Find a problem
|
||||||
// result.value = randRange(101, 1000)
|
// result.value = randRange(101, 1000)
|
||||||
|
@ -132,6 +144,11 @@ onMounted(() => {
|
||||||
return randRange(250, 1000)
|
return randRange(250, 1000)
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
// Reset Operations list
|
||||||
|
operations.splice(0)
|
||||||
|
operations.push(getEmptyOperation())
|
||||||
|
|
||||||
|
// Generate result and plaquettes
|
||||||
plaquettes.value = []
|
plaquettes.value = []
|
||||||
const poolCopy = [...pool]
|
const poolCopy = [...pool]
|
||||||
for (let i = 0; i < 6; ++i) {
|
for (let i = 0; i < 6; ++i) {
|
||||||
|
@ -147,5 +164,9 @@ onMounted(() => {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
plaquettes.value.sort((a, b) => a.value - b.value)
|
plaquettes.value.sort((a, b) => a.value - b.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
reboot()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user