vue3 を使用したジグソーパズルゲームのリファクタリングの例

vue3 を使用したジグソーパズルゲームのリファクタリングの例

序文

プロジェクト内のパズルゲーム(デジタル華容路とも呼ばれる)を再構築するのに 2 日かかりました。使いやすさを考慮して、独立したコンポーネントに抽出されました。効果は次のとおりです。

オンライン体験

ソースコードのアドレスは記事の最後にあります!

主な再建ポイント

オリジナルのジグソーパズル ゲームは、vue2 を使用してオープン ソース コードを通じて変更されました。実際のプロジェクトではすべてうまく機能しますが、次のような問題点が残っています。

  • ソース コードは肥大化しており、公開されている構成項目は、特にプロジェクトの既存のロジックと組み合わせると不十分です。
  • 生成されたゲームには解決できない状況が含まれる場合があります。解決できない状況を回避するには、いくつかの状況を記述し、それらをランダムに生成する必要があります。
  • ソースコードはvue2バージョンであり、vue3をサポートしていません

最終的に、次の詳細に注意しながら、vue3を使用してジグソーパズルゲームを再実装することにしました。

  • コンポーネントは使いやすいほどシンプルです
  • カスタマイズ可能なゲーム難易度
  • 画像モードと配列モードの両方をサポート

実装のアイデア

パズルの絵でもパズルの数字でも、元々シャッフルされていた配列を整列した状態に移動するのが原則です。インターネット上には、デジタル華容を実装するアルゴリズムも多数あります。アルゴリズムが解決する必要がある主な問題は、ランダムかつ解ける配列のセットを生成する方法です。華容配列が解けない可能性はあるのだろうかと疑問に思う人もいるかもしれません。

生成されたゲームが上記のようなものである場合、解決策はありません。原理はルービックキューブで遊ぶのと同じです。通常、どんなにぐちゃぐちゃになっても元に戻すことができます。しかし、いくつかのブロックを取り出して位置を変えると、元に戻せなくなる場合があります。

インターネット上には解決不可能な問題の発生を回避できるアルゴリズムが多数存在しますが、いずれも比較的高度なものです。また、アルゴリズムを読む能力にも限界があるため、最終的には自分のアイデアで実装することにしました。

私のアイデアは実はとてもシンプルです。一文で「逆推論」と要約できます。まずは整列した配列から始めて、それを移動することでランダムに順序を乱します。こうすることで、生成された質問に必ず解答があることが保証されます。同時に、乱れたステップの数に応じてゲームの難易度を制御できます。これはまさに一石二鳥のアイデアです。

ソースコードの実装

データストレージ

まず、データを格納するために 1 次元配列を使用することを検討しました。

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

しかし、1次元配列ではデータしか記録できず、垂直位置を記録できないため、移動時にロジックがかなり面倒になるという問題があります。このとき、自然に2次元配列の使用を考えます。たとえば、3×3のゲームを生成する必要がある場合、データは次のようになります。

アーレ [
  [1,2,3],
  [4,5,6],
  [7,8,0]
]

このようにして、x 軸と y 軸をシミュレートして、各数字の位置を示すことができます。たとえば、0 の位置は (2,2) で、6 の位置は (1,2) です。6 と 0 の位置を移動したい場合は、それらの座標を入れ替えるだけです。

移動機能

デジタル華龍島の最も重要なインタラクションは、ユーザーがクリックしたブロックを移動することですが、0 に近い配列のみを移動できることに注意してください。次に移動関数を完成させます

 関数move(x, y, moveX, moveY) {
  定数num = state.arr[x][y];
  state.arr[x][y] = state.arr[moveX][moveY];
  state.arr[moveX][moveY] = 数値;
 }

とても簡単ではないでしょうか。実際には、移動する 2 つの数字の添え字を交換するだけです。移動関数を使用すると、上下左右への移動を実現できます。

// 上に移動する function moveTop(x, y) {
  x <= 0 の場合は -1 を返します。
  // 位置の交換を開始します const okx = x - 1;
  移動(x, y, okx, y);
  戻る {
   x: わかりました、
   はい、
  };
 }
 //下へ移動 function moveDown(x, y) {
  (x >= レベル - 1) の場合は -1 を返します。
  定数okx = x + 1;
  移動(x, y, okx, y);
  戻る {
   x: わかりました、
   はい、
  };
 }
 // 左に移動する function moveLeft(x, y) {
  y <= 0 の場合は -1 を返します。
  定数 oky = y - 1;
  移動(x, y, x, ok);
  戻る {
   ×、
   y: わかったよ
  };
 }

 // 右に移動する function moveRight(x, y) {
  y >= レベル - 1 の場合は -1 を返します。
  定数 oky = y + 1;
  移動(x, y, x, ok);
  戻る {
   ×、
   y: わかったよ
  };
 }

次に、以下に示すように、移動方向を決定するメソッドを実装します。

 関数 shouldMove(x, y) {
  // 移動先を決定します const { emptyX, emptyY } = seekEmpty();
  (x === emptyX && y !== emptyY && Math.abs(y - emptyY) === 1) の場合 {
   // 水平線上で左または右に移動する可能性があることを示します if (y > emptyY) {
    左へ移動(x, y);
   } それ以外 {
    右へ移動(x, y);
   }
  }
  (y === emptyY && x !== emptyX && Math.abs(x - emptyX) === 1)の場合{
   // 上下に移動する必要があることを示します if (x > emptyX) {
    上へ移動(x, y);
   } それ以外 {
    下へ移動します(x, y);
   }
  }
 }

if の判断は、クリックしたブロックが空白ブロックであるか、空白ブロックに隣接していない場合は何もしないことを意味します。

ゲームボードを生成する

実際には、上、下、左、右のシフト関数をランダムに呼び出して配列を混乱させるのです。

 // ランダムにシャッフルする function moveInit(diffic) {
  状態.arr = createArr(レベル);
  const num = diffic ? diffic: state.diffec;
  const fns = [上へ移動、下へ移動、左へ移動、右へ移動];
  インデックスを null にします。
  fn にします。
  (i = 0; i < num; i++ とします) {
   インデックス = Math.floor(Math.random() * fns.length);
   // コンソールを移動します(インデックス);
   fn = fns[インデックス](開始X、開始Y);
   (fn!=-1)の場合{
    定数 { x, y } = fn;
    開始X = x;
    開始Y = y;
   }
  }
 }

ほんの数個の関数でコアロジックが完成します。ゲームの完了判定や、空きブロックの位置の検索、2次元配列の作成など、まだ紹介していない関数がいくつかあります。ソースコードは自分で読んでみてください。

vue3 によるリファクタリング

上記のロジックはvue3とは関係ないように思えますが、最も重要な点を見落としています。つまり、配列を変更すると、ビューも変更されます。これはレスポンシブではありませんか?vue3を使用すると、ゲームに関するすべてのロジックをjsにまとめることができ、コードの結合が大幅に削減されます。

const { arr、shouldMove、moveInit } = useCreateGame(
 ゲームデータレベル、
 ゲームデータ難易度、
 ゲーム終了コールバック
);

疑問に思う方もいるかもしれません。ロジックをすべて抽出するのが普通ではないでしょうか?vue2 を使用する場合、抽出は不可能でしょうか?
ただし、配列はレスポンシブである必要があることを忘れないでください。ロジックを個別に抽出した場合、js ファイル内の配列を変更しても、レスポンシブになりますか?

しかし、vue3のcomposition-apiを使用すると、jsファイルでレスポンシブ変数を宣言することができ、コンポーネントで使用してもレスポンシブになります。

デフォルト関数 useCreateGame() をエクスポートします。
// レスポンシブ変数を宣言します...
 定数状態 = リアクティブ({
  編曲: [],
 });
...
 戻る {
 ...toRefs(状態)
 ...
 }
 }
const { arr、shouldMove、moveInit } = useCreateGame(
 ゲームデータレベル、
 ゲームデータ.難易度、
 ゲーム終了コールバック
);
// 現時点では、arr はまだ応答します

これがcomposition-apiの威力です。composition-apiを使用すると、ロジックコードを任意に組み立てることができます。

vue2では、レスポンシブ変数を維持したい場合、コードの結合度が増すvuexのような状態マネージャを使用する必要がありますか?

vite2について

現在、vite は vite2 バージョンに到達しており、公式バージョンはまだ急速に更新されています。vite2 で作成されたプロジェクトは、デフォルトで新しいセットアップ機能を使用できます。たとえば、次のように記述できます。

<テンプレート>
 <div>
  {{ 名前 }}
 </div>
</テンプレート>

<スクリプトの設定>
"vue" から { ref } をインポートします。
const name = ref('"公衆番号は止まりません"');
</スクリプト>

これは次のように書くのと同じである。

<テンプレート>
 <div>
  {{ 名前 }}
 </div>
</テンプレート>
<スクリプト>
"vue" から { ref } をインポートします。
エクスポートデフォルト{
 設定() {
  const name = ref("公衆番号は止まりません");
  戻る {
   名前、
  };
 },
};
</スクリプト>

見た目はかなりシンプルになり、Vue はセットアップ版でいくつかの API を公開しています。興味があれば、公式サイトに行って確認してみてください。個人的にはかなり良いと感じています。新しい構文はまだ実験段階であるため、このコード リファクタリングでは使用されませんでした。

ソースコードアドレス

ソースコードアドレス: デジタル華龍島パズルゲームへようこそ😍

やっと

あなたは興味があるかもしれません:

vue-routerの考え方に基づいて🕓 vue-routerのシンプルなバージョンを実装する
マルチページアプリケーションのWebpackパッケージングに基づくフロントエンドエンジニアリングについて考える

vue3 を使用したジグソーパズルゲームの再構築の実装例については、これで終了です。より関連性の高い vue3 再構築パズルコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き閲覧してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • vue3 でブロック崩しゲームを開発する方法をステップバイステップで教えます

<<:  MySQL 5.7.17 圧縮バージョンのインストールノート

>>:  Linux の crw、brw、lrw などのファイル属性は何ですか?

推薦する

CSS3 のフレックスレイアウト幅の無効性の解決策

2 列レイアウトはプロジェクトでよく使用されます。この効果を実現する方法はたくさんあります。 しかし...

【Webデザイン】E-WebTemplates の美しい海外の Web ページ テンプレート (FLASH+PSD ソース ファイル+HTML) を共有します

これらはすべて海外のE-WebTemplates WebサイトからのWebページテンプレートであり、...

nginx で HSTS を有効にしてブラウザを HTTPS アクセスにリダイレクトする方法の詳細な説明

前回の記事では、https を使用したローカルノードサービスアクセスを実装しました。前回の記事の効果...

Navicat 接続 MySQL エラーの説明分析

目次環境仮想マシンバージョンMySQL バージョン事前準備MySQLの実行ステータスを確認するルート...

Vueコンポーネント通信のさまざまな方法の詳細な説明

目次1. 父から息子へ2. 息子から父へ3. 親子関係のないコンポーネントの値の転送4. ヴュークス...

JavaScript インスタンス オブジェクトでプロトタイプ メソッドをオーバーライドする方法の詳細

目次JavaScriptでは、通常、次のコードのようにクラスを簡単に定義できます。 var サンプル...

MySQL 8.0はJSONを扱えるようになりました

目次1. 概要2. JSON基本ツール3. JSONパス式4. JSONを検索して変更する序文:長い...

Linuxでpyファイルを直接実行する方法

1. まずファイルを作成します(ファイルを配置するディレクトリにcdします) myTest.py を...

MySQLのexecute、executeUpdate、executeQueryの違い

execute、executeUpdate、executeQuery の違い (およびそれらの戻り値...

MySQL データ挿入効率の比較

データを挿入するとき、以前オフィス システムに取り組んでいたときにはデータベースのパフォーマンスにつ...

Alibaba CloudにMySQLをインストールする方法の詳細な説明

軽量のオープンソース データベースである MySQL は、エンタープライズ レベルのアプリケーション...

ローカル写真をアップロードする前にプレビューコード例を実装するための HTML5 と jQuery

HTML5 と jQuery はアップロード前にローカル画像のプレビューを実装しており、その効果は...

MySQL 5.7 における部分テーブルのデュアルマスター同期の実装プロセスの詳細な説明

序文最近、私はある要件に遭遇しました。会社の業務上、2 つのデータベース間の一部のテーブルは、リアル...

vuex での mapState の考え方の応用

目次1. マップ方式2. 応用背景:需要開発プロセス中に、一部のインターフェースは、ページに表示する...

CSV、Excel、SQL ファイルを MySQL にインポートするためのヒント

1. csvファイルをインポートする次のコマンドを使用します。 1.mysql> infile...