15パズル 移動とクリア判定が完成

2019/5/11更新

PushPieceメソッドを縮小できないか、と考えていて
ある事に気が付きました。

16ポジションから押したピースを探して、
0番ピースと隣接してるか判断していたのですが、

0番から4方向に押したピースが有るかを判断した方が、
手数が少なくなるのでは? と思いつきました。

ただ、ポジションから判断すると結局の所、
16ポジションの処理が必要になるので変化ありません。


そこで、座標位置から読み取る事ができれば、なんとかなるかも
と言う考えに至りまして、少し整理してみる事にしました。

・0番ピースと横並びならY座標が同じになる
・0番ピースと縦並びならX座標が同じになる
・0番と押したピースが並ぶと、ピースのピッチは上下左右同じ

コードを考えてみます。

0番と押したピースのポジションは取得してるので、
それを元にX座標が同じかを判断するなら、

if (Xp[Add0] == Xp[AddP]){}

これで判断できそうです。
Y座標も同じ文でいけそうです。

あとは隣接してるかの判断ですが、
ピースのピッチを160で取っているので、

if (Yp[Add0] - 160 == Yp[AddP] || Yp[Add0] + 160 == Yp[AddP])


これを元にコードを作ると

//0番ピースと押したピースが縦並びか
if (Xp[Add0] == Xp[AddP])
{
//上下に隣接してるか
if (Yp[Add0] - 160 == Yp[AddP] || Yp[Add0] + 160 == Yp[AddP])
{
PieceMove(PieceNo);
}

 //0番ピースと押したピースが横並びか
}else if (Yp[Add0] == Yp[AddP])
{
//左右に隣接してるか
if (Xp[Add0] - 160 == Xp[AddP] || Xp[Add0] + 160 == Xp[AddP])
{
PieceMove(PieceNo);
}
}

まだ重複してる部分があるので縮小できそうです。

縦横の判定を一つにまとめて、4方向に隣接してるか判断すれば…

//0番ピースと押したピースがX座標かY座標が同じか
if (Xp[Add0] == Xp[AddP] || Yp[Add0] == Yp[AddP])
{
//隣接してるか
if (Xp[Add0] - 160 == Xp[AddP] || Xp[Add0] + 160 == Xp[AddP]
|| Yp[Add0] - 160 == Yp[AddP] || Yp[Add0] + 160 == Yp[AddP])
{
PieceMove(PieceNo);
}
}

ピッチの数値を直接書いてる事と、
ピース間のピッチを判定内で計算してるのが不細工なので、

//ピース間の距離
private const int PiecePitch=160;


   //ピース間の距離を計算
int Xpitch = Xp[Add0] - Xp[AddP];
int Ypitch = Yp[Add0] - Yp[AddP];


//0番ピースと押したピースがX座標かY座標が同じか
if (Xp[Add0] == Xp[AddP] || Yp[Add0] == Yp[AddP])
{
//隣接してるか
if (Xpitch == PiecePitch || Xpitch == -PiecePitch
|| Ypitch == PiecePitch || Ypitch == -PiecePitch)
{
PieceMove(PieceNo);
}
}

ピッチは絶対値にしたいので const int で宣言です。

0番ピースと押したピースの距離を計算して、その差から判定してみました。


switchで16ポジション分書いていたのが、かなり短くなりました。(^ー^* )
でもコードは読みにくくなったかも… (´`;)

頭が悪いので、ここら辺が限界です。
これ以上は逆さになっても出てきませんヾ(´▽`;)ゝ

こうすればいいのに!
みたいなのがあれば、コメントに一言頂けるとありがたいです。


あとは、ピースが正規位置に並んだらゲームクリアです。
位置判定用のメソッドは

void Judge()
{
//判定用変数
bool Ju = false;

for(int i = 0; i < 16; i++)
{
if (Pos[i] == i)
{
Ju = true;
}
else
{
return;
}
}

//ピースが正規の位置に並んだら
if (Ju == true)
{
//ここにクリア時のイベントを書く
}
}

これでいいか…
コードが読みにくいのは流して下さい。f(^_^;



上のコードを加えて最終的にできたのがこちら


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class PieceManager : MonoBehaviour {

//ピースオブジェクト
public GameObject[] Piece;

//トランスホーム用変数
private RectTransform []rect=new RectTransform[16];

//ポジション変数
private int[] Pos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

//座標変数
private int[] Xp = { -240, -80, 80, 240,
-240, -80, 80, 240,
-240, -80, 80, 240,
-240, -80, 80, 240 };

private int[] Yp = { 240, 240, 240, 240,
80, 80, 80, 80,
-80, -80, -80, -80,
-240, -240, -240, -240, };

//空きマスと押したピースの座標取得用変数
private int Add0;
private int AddP;


//ピースのピッチ
private const int PiecePitch=160;


// Use this for initialization
void Start()
{

//ピースオブジェクトのトランスホーム取得
for (int i = 0; i < 16; i++)
{
rect[i] = Piece[i].GetComponent();
}

}


// Update is called once per frame
void Update () {

}


//ピースボタンを押した処理
public void PushPiece(int PieceNo)
{

PieceSearch(PieceNo);


//ピース間の距離を計算
int Xpitch = Xp[Add0] - Xp[AddP];
int Ypitch = Yp[Add0] - Yp[AddP];


//0番ピースと押したピースがX座標かY座標が同じか
if (Xp[Add0] == Xp[AddP] || Yp[Add0] == Yp[AddP])
{
//隣接してるか
if (Xpitch == PiecePitch || Xpitch == -PiecePitch
|| Ypitch == PiecePitch || Ypitch == -PiecePitch)
{
PieceMove(PieceNo);
}
}

Judge();
}



//0番ピースと押したピースのポジション確認
void PieceSearch(int PieceNo)
{
for (int i = 0; i < 16; i++)
{
if (Pos[i] == 0)
{
Add0 = i;
}
if (Pos[i] == PieceNo)
{
AddP = i;
}
}
}



//0番ピースと押したピースを入れ替える
void PieceMove(int PieceNo)
{
rect[PieceNo].DOLocalMove(new Vector3(Xp[Add0], Yp[Add0], 0f), 0.2f);
rect[0].DOLocalMove(new Vector3(Xp[AddP], Yp[AddP], 0f), 0.2f);
Pos[AddP] = 0;
Pos[Add0] = PieceNo;
}


//ピースが正規の位置に並んでいるか判定する
void Judge()
{
//判定用変数
bool Ju = false;

for(int i = 0; i < 16; i++)
{
if (Pos[i] == i)
{
Ju = true;
}
else
{
return;
}
}

//ピースが正規の位置に並んだら
if (Ju == true)
{
//ここにクリア時のイベントを書く
}
}
}


しかし改めて見ると読みにくい(TωT)

独学なので、これでいいのか分かりません。
作法的なものがあれば、誰でもいいので教えて~ うーん (+_+)


この記事へのコメント