Используйте vue3 для воссоздания пазлов, действительно ароматный!

Vue.js

предисловие

Два дня ушло на воссоздание головоломки (также известной как Digital Huarong Road) в проекте, который для удобства использования был разделен на независимые компоненты.Эффект следующий:

онлайн опыт

Адрес исходного кода в конце статьи!

Основные моменты рефакторинга

Первоначальная головоломка была преобразована с помощью открытого исходного кода с использованиемvue2. В реальных проектах все работает нормально, но все же есть следующие болевые точки

  • Исходный код раздут и выставленных элементов конфигурации недостаточно, особенно в сочетании с существующей логикой проекта это более очевидно
  • Сгенерированная игра может не иметь решения.Чтобы избежать отсутствия решения, несколько ситуаций должны быть записаны до смерти, а затем сгенерированы случайным образом.
  • исходный кодvue2версия, не поддерживаетсяvue3

В итоге решил использоватьvue3Переработана головоломка с упором на следующие детали.

  1. Компоненты достаточно просты в использовании
  2. Сложность игры можно настроить
  3. Поддерживает режимы изображения и массива

Реализовать идеи

Будь то часть головоломки или число, принцип состоит в том, чтобы перевести исходный зашифрованный массив в упорядоченное состояние. Алгоритмов реализации цифрового хуаронга в Интернете также существует множество, основная проблема алгоритма заключается в том, как сгенерировать наборслучайный и разрешимыйМассив , у некоторых людей могут возникнуть сомнения, является ли массив Huarong Road все еще неразрешимым?

Если сгенерированная игра подобна приведенной выше, она неразрешима. Принцип тот же, что и при игре в кубик Рубика: в нормальных условиях, как бы мы ни запутались, мы можем его восстановить, но если поставитьНекоторые блоки выдвигаются и меняются местами, восстановить не получится

В Интернете также есть много алгоритмов, которые могут избежать генерации решения, но написание относительно продвинутое, а возможность чтения алгоритма ограничена, поэтому я, наконец, решил реализовать его в соответствии со своими собственными идеями.

Моя идея на самом деле относительно проста, краткое изложение одного предложения逆向推理法, мы можем начать с переставленного массива, а затем случайным образом пройти черезпереехатьПеретасовывая порядок, вы обязательно убедитесь, что сгенерированные проблемы имеют решения, и в то же время вы можете контролировать сложность игры в зависимости от количества перетасованных шагов, что действительно является идеалом, который убивает двух зайцев одним. камень.

реализация исходного кода

хранилище данных

Первое, о чем я подумал, это использовать одномерный массив для хранения данных.

let arr = [1,2,3,4,5,6,7,8,0]  // 0 代表空白

Но на этом пути будет проблема, то есть логика становится довольно хлопотной при перемещении, потому что одномерные массивы могут записывать только данные и не могут записывать положение по вертикали.В это время мы, естественно, думаем об использовании двумерных массивов , Например, когда нам нужно сгенерировать3*3Данные игры выглядят так:

let arr [
    [1,2,3],
    [4,5,6],
    [7,8,0]
]

Таким образом, мы можем смоделироватьx,yось для представления положения каждой цифры. Например0Расположение(2,2),6Расположение(1,2), если я хочу двигаться6和0положение, просто поменяйте их координаты.

функция перемещения

Наиболее важным взаимодействием Digital Huarong Road является то, что пользователь щелкает блок, чтобы переместить блок, но следует отметить, что только0Ближайшие массивы можно перемещать. Теперь давайте сначала завершим функцию перемещения

  function move(x, y, moveX, moveY) {
    const num = state.arr[x][y];
    state.arr[x][y] = state.arr[moveX][moveY];
    state.arr[moveX][moveY] = num;
  }

Это очень просто, на самом деле, это поменять местами индексы двух чисел, которые нужно переместить.

С помощью функции перемещения мы можем достичь上,下,左,右взолнованный

// 上移动
  function moveTop(x, y) {
    if (x <= 0) return -1;
    //   开始交换位置
    const okx = x - 1;
    move(x, y, okx, y);
    return {
      x: okx,
      y,
    };
  }
  //下移动
  function moveDown(x, y) {
    if (x >= level - 1) return -1;
    const okx = x + 1;
    move(x, y, okx, y);
    return {
      x: okx,
      y,
    };
  }
  // 左移动

  function moveLeft(x, y) {
    if (y <= 0) return -1;
    const oky = y - 1;
    move(x, y, x, oky);
    return {
      x,
      y: oky,
    };
  }

  // 右移动
  function moveRight(x, y) {
    if (y >= level - 1) return -1;
    const oky = y + 1;
    move(x, y, x, oky);
    return {
      x,
      y: oky,
    };
  }

Теперь давайте реализуем другой метод для определения направления движения следующим образом:

  function shouldMove(x, y) {
    //   判断向哪移动
    const { emptyX, emptyY } = seekEmpty();
    if (x === emptyX && y !== emptyY && Math.abs(y - emptyY) === 1) {
      // 说明在一个水平线上 可能是左右移动
      if (y > emptyY) {
        moveLeft(x, y);
      } else {
        moveRight(x, y);
      }
    }
    if (y === emptyY && x !== emptyX && Math.abs(x - emptyX) === 1) {
      // 说明需要上下移动
      if (x > emptyX) {
        moveTop(x, y);
      } else {
        moveDown(x, y);
      }
    }
  }

ifСуждение внутри означает, что если блок, на который мы нажали, пуст или не рядом с пробелом, то мы ничего делать не будем.

Создать игровое поле

На самом деле это случайный звонок.上移,下移,左移,右移функция для перемешивания массива

  // 随机打乱
  function moveInit(diffic) {
    state.arr = creatArr(level);
    const num = diffic ? diffic : state.diffec;
    const fns = [moveTop, moveDown, moveLeft, moveRight];
    let Index = null;
    let fn;
    for (let i = 0; i < num; i++) {
      Index = Math.floor(Math.random() * fns.length);
      //   moveConsole(Index);
      fn = fns[Index](startX, startY);
      if (fn != -1) {
        const { x, y } = fn;
        startX = x;
        startY = y;
      }
    }
  }

Всего в нескольких функциях основная логика завершена, и есть еще несколько функций, которые не были введены, например判断游戏完成,寻找空白块的位置,创建二维数组Вы можете прочитать исходный код самостоятельно

использоватьvue3рефакторинг

Вышеприведенная логика кажетсяvue3Это не беда, но мы упустили из виду самый важный момент, а именноПосле смены массива вид тоже меняетсяРазве это не просто отзывчиво, используйтеvue3Тогда мы можем поместить всю логику об игре в одинjsВнутри связь кода значительно снижена

const { arr, shouldMove, moveInit } = useCreateGame(
  gamedata.level,
  gamedata.difficulty,
  gameEndCallback
);

У некоторых могут возникнуть сомнения, разве это не нормальная операция по извлечению всей логики?vue2Не можешь уйти с дороги?

Но не забывайте, наш массив должен быть响应式Да, если мы выделим логику, то мыjsИзменение массива в файле все еще реагирует?

Но когда мы используем vue3composition-apiтогда ты сможешьjsРеактивная переменная объявлена ​​в файле и является реактивной при использовании в компоненте.


export default function useCreateGame() {
//声明一个响应式变量
...
  const state = reactive({
    arr: [],
  });
...
  return {
  ...toRefs(state)
  ...
  }
 }
const { arr, shouldMove, moveInit } = useCreateGame(
  gamedata.level,
  gamedata.difficulty,
  gameEndCallback
);
// 这个时候 arr 还是响应式的

это точноcomposition-apiсила, сcomposition-apiМы можем собрать наш логический код произвольно

существуетvue2Если мы хотим поддерживать реактивную переменную, нужно ли нам использовать менеджер состояний, такой как vuex, который увеличивает связность кода?

оvite2

Сейчасviteприбылvite2версия, а официальная все еще находится в быстрой итерации, используяvite2Созданный проект доступен по умолчаниюsetupНапример, для новых функций мы можем написать:

<template>
  <div>
    {{ name }}
  </div>
</template>

<script setup>
import { ref } from "vue";
const name = ref('"公众号码不停息"');
</script>

эквивалентно написанию

<template>
  <div>
    {{ name }}
  </div>
</template>
<script>
import { ref } from "vue";
export default {
  setup() {
    const name = ref("公众号码不停息");
    return {
      name,
    };
  },
};
</script>

Это выглядит намного проще, иsetupв версииvueеще несколькоapi, Если вам интересно, вы можете зайти на официальный сайт, чтобы увидеть его.Лично он довольно ароматный. Этот рефакторинг кода не используется, поскольку новый синтаксис все еще является экспериментальным.

Адрес источника

Адрес источника:Цифровая головоломка Huarong RoadДобро пожаловать на старт😍

наконец

Вас может заинтересовать:

Если поможет, ставьте лайк 😁