Undo ok
This commit is contained in:
		
							parent
							
								
									efcab7b77b
								
							
						
					
					
						commit
						725cbd0dbe
					
				| 
						 | 
				
			
			@ -11,7 +11,6 @@
 | 
			
		|||
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "pinia": "^2.0.11",
 | 
			
		||||
    "vue": "^3.2.30",
 | 
			
		||||
    "vue-router": "^4.0.12"
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								src/algo.ts
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/algo.ts
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1,12 +1,13 @@
 | 
			
		|||
import { reactive, ref, watch } from 'vue'
 | 
			
		||||
 | 
			
		||||
import { operators, pool } from './globals'
 | 
			
		||||
import { Operation, OperatorType } from './types'
 | 
			
		||||
import { Operation, OperatorType, Plaquette } from './types'
 | 
			
		||||
import { randRange } from './utils'
 | 
			
		||||
 | 
			
		||||
type HistoryType = { a: number; b: number; op: OperatorType }[]
 | 
			
		||||
 | 
			
		||||
export const operations = reactive<Operation[]>([])
 | 
			
		||||
export const plaquettes = ref<Plaquette[]>([])
 | 
			
		||||
 | 
			
		||||
export function isOperationResultValid(op: Operation): boolean {
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -30,13 +31,13 @@ export function isOperationReady(op: Operation): boolean {
 | 
			
		|||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function pushEmptyOperation(): void {
 | 
			
		||||
  operations.push({
 | 
			
		||||
export function getEmptyOperation(): Operation {
 | 
			
		||||
  return {
 | 
			
		||||
    left: null,
 | 
			
		||||
    right: null,
 | 
			
		||||
    operator: null,
 | 
			
		||||
    executed: false,
 | 
			
		||||
  })
 | 
			
		||||
    result: null,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function operate(
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +65,6 @@ export function isSolvable(result: number, plaquettes: number[]): boolean {
 | 
			
		|||
        `${item.a} ${item.op} ${item.b} = ${operate(item.op, item.a, item.b)}`,
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
    console.log()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function loopOperations(plaquettes: number[], history: HistoryType): void {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,8 +135,6 @@ export function isSolvable(result: number, plaquettes: number[]): boolean {
 | 
			
		|||
  if (histories.length) {
 | 
			
		||||
    printHistory(histories[0])
 | 
			
		||||
  }
 | 
			
		||||
  console.log(new Date().getTime() - startTime.getTime() + 'ms')
 | 
			
		||||
  console.log(found)
 | 
			
		||||
  return found
 | 
			
		||||
 | 
			
		||||
  // histories.sort((a, b) => a.length - b.length)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
    <div
 | 
			
		||||
      class="mb-2 text-center"
 | 
			
		||||
      v-for="(op, i) in operations"
 | 
			
		||||
      :style="{ transitionDelay: `${transDelay * (operations.length - i)}ms` }"
 | 
			
		||||
      :key="i">
 | 
			
		||||
      <div class="inline-block relative text-xl">
 | 
			
		||||
        <!-- OPERATION -->
 | 
			
		||||
| 
						 | 
				
			
			@ -55,11 +56,12 @@
 | 
			
		|||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import {
 | 
			
		||||
  getEmptyOperation,
 | 
			
		||||
  isOperationInvalid,
 | 
			
		||||
  isOperationResultValid,
 | 
			
		||||
  operate,
 | 
			
		||||
  operations,
 | 
			
		||||
  pushEmptyOperation,
 | 
			
		||||
  plaquettes,
 | 
			
		||||
} from '@/algo'
 | 
			
		||||
import { Operation } from '@/types'
 | 
			
		||||
import IconQuestion from '~icons/bx/bx-question-mark'
 | 
			
		||||
| 
						 | 
				
			
			@ -68,12 +70,31 @@ import IconUndo from '~icons/bx/bx-undo'
 | 
			
		|||
 | 
			
		||||
import NumberBox from './common/NumberBox.vue'
 | 
			
		||||
 | 
			
		||||
const transDelay = 100
 | 
			
		||||
 | 
			
		||||
function canOperationBeDeleted(op: Operation): boolean {
 | 
			
		||||
  return !!op.left || !!op.right || !!op.operator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function undoOperation(index: number): void {
 | 
			
		||||
  while (operations.length > index) operations.pop()
 | 
			
		||||
  if (!operations.length) pushEmptyOperation()
 | 
			
		||||
  const l = operations.length
 | 
			
		||||
  for (let i = operations.length - 1; i >= index; --i) {
 | 
			
		||||
    console.log(i)
 | 
			
		||||
    let popped: Operation
 | 
			
		||||
    if (i === index) {
 | 
			
		||||
      popped = operations[index]
 | 
			
		||||
      setTimeout(() => {
 | 
			
		||||
        operations[index] = getEmptyOperation()
 | 
			
		||||
      }, transDelay * l)
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      popped = operations.pop()!
 | 
			
		||||
    }
 | 
			
		||||
    if (popped?.left) popped.left.free = true
 | 
			
		||||
    if (popped?.right) popped.right.free = true
 | 
			
		||||
    if (popped.result) {
 | 
			
		||||
      plaquettes.value = plaquettes.value.filter(p => p !== popped.result)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,3 +2,9 @@ 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 enum GameState {
 | 
			
		||||
  Playing,
 | 
			
		||||
  Lost,
 | 
			
		||||
  Won,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,5 +9,5 @@ export type Operation = {
 | 
			
		|||
  left: Plaquette | null
 | 
			
		||||
  right: Plaquette | null
 | 
			
		||||
  operator: OperatorType | null
 | 
			
		||||
  executed: boolean
 | 
			
		||||
  result: Plaquette | null
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,44 +49,46 @@
 | 
			
		|||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
 | 
			
		||||
import { computed, onMounted, ref, watch } from 'vue'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  isOperationInvalid,
 | 
			
		||||
  getEmptyOperation,
 | 
			
		||||
  isOperationReady,
 | 
			
		||||
  isOperationResultValid,
 | 
			
		||||
  isSolvable,
 | 
			
		||||
  operate,
 | 
			
		||||
  operations,
 | 
			
		||||
  pushEmptyOperation,
 | 
			
		||||
plaquettes,
 | 
			
		||||
} from '@/algo'
 | 
			
		||||
import NumberBox from '@/components/common/NumberBox.vue'
 | 
			
		||||
import OperationsList from '@/components/OperationsList.vue'
 | 
			
		||||
import { operators, pool } from '@/globals'
 | 
			
		||||
import { Operation, OperatorType, Plaquette } from '@/types'
 | 
			
		||||
import { GameState, operators, pool } from '@/globals'
 | 
			
		||||
import { OperatorType, Plaquette } from '@/types'
 | 
			
		||||
import { randItem, randRange } from '@/utils'
 | 
			
		||||
 | 
			
		||||
const result = ref(0)
 | 
			
		||||
const plaquettes = ref<Plaquette[]>([])
 | 
			
		||||
const initDelay = ref(100)
 | 
			
		||||
const currentState = ref(GameState.Playing)
 | 
			
		||||
 | 
			
		||||
pushEmptyOperation()
 | 
			
		||||
// pushEmptyOperation()
 | 
			
		||||
operations.push(getEmptyOperation())
 | 
			
		||||
 | 
			
		||||
const currentOperation = computed(
 | 
			
		||||
  () => operations[operations.length - 1],
 | 
			
		||||
)
 | 
			
		||||
const currentOperation = computed(() => operations[operations.length - 1])
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  currentOperation,
 | 
			
		||||
  op => {
 | 
			
		||||
    if (isOperationReady(op) && isOperationResultValid(op) && !op.executed) {
 | 
			
		||||
      op.executed = true
 | 
			
		||||
      plaquettes.value.push({
 | 
			
		||||
        value: operate(op.operator!, op.left!.value, op.right!.value),
 | 
			
		||||
    if (isOperationReady(op) && isOperationResultValid(op) && !op.result) {
 | 
			
		||||
      op.result = {
 | 
			
		||||
        free: true,
 | 
			
		||||
      })
 | 
			
		||||
      pushEmptyOperation()
 | 
			
		||||
        value: operate(op.operator!, op.left!.value, op.right!.value),
 | 
			
		||||
      }
 | 
			
		||||
      plaquettes.value.push(op.result)
 | 
			
		||||
      if (op.result.value === result.value) {
 | 
			
		||||
        // Winner
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        operations.push(getEmptyOperation())
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  { deep: true },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user