<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BlockController : MonoBehaviour
{
    public int x, y;
    private Vector3 firtTouchPosition;
    private Vector3 finalTouchPoition;
    private float swipeAngle;
    private bool canMove;
    private bool canLerp;

    private Vector3 startPosition;
    private Vector3 endPosition;

    LerpController theLerp;
    public float moveLenght = 2.0f;

    public int number = 0;
    public Text numberText;

    LevelController theLevel;
    void Start()
    {
        theLevel = FindObjectOfType<LevelController>();
        theLerp = GetComponent<LerpController>();
    }

    void Update()
    {
        if (canLerp)
            canLerp = theLerp.LerpObject(startPosition, endPosition, 0.4f);
    }

    void OnMouseDown()
    {
        firtTouchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    }

    void OnMouseUp()
    {
        if (theLevel.currentGameState == LevelController.GameState.Playing || theLevel.currentGameState == LevelController.GameState.MainMenu)
        {
            finalTouchPoition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            CalculateAngle();
            float swipeRangeX = Mathf.Abs(firtTouchPosition.x - finalTouchPoition.x);
            float swipeRangeY = Mathf.Abs(firtTouchPosition.y - finalTouchPoition.y);
            if (swipeRangeX > 0.2f || swipeRangeY > 0.2f)
                MoveBlock();
        }
    }

    void CalculateAngle()
    {
        swipeAngle = Mathf.Atan2(finalTouchPoition.y - firtTouchPosition.y, finalTouchPoition.x - firtTouchPosition.x) * 180 / Mathf.PI;
    }

    void MoveBlock()
    {
        int lastX = x;
        int lastY = y;
        if (swipeAngle > -45 && swipeAngle <= 45 && theLevel.GetGrid(x + 1, y) != null && theLevel.GetGrid(x + 1, y).number == 0)  //Right
        {
            x++;
            startPosition = new Vector2(transform.position.x, transform.position.y); ;
            endPosition = new Vector2(transform.position.x + moveLenght, transform.position.y); ;
            canLerp = true;
        }
        else if (swipeAngle > 45 && swipeAngle <= 135 && theLevel.GetGrid(x, y - 1) != null && theLevel.GetGrid(x, y - 1).number == 0) //Up
        {
            y--;
            startPosition = new Vector2(transform.position.x, transform.position.y); ;
            endPosition = new Vector2(transform.position.x, transform.position.y + moveLenght); ;
            canLerp = true;
        }
        else if ((swipeAngle > 135 || swipeAngle <= -135) && theLevel.GetGrid(x - 1, y) != null && theLevel.GetGrid(x - 1, y).number == 0) //Left
        {
            x--;
            startPosition = new Vector2(transform.position.x, transform.position.y); ;
            endPosition = new Vector2(transform.position.x - moveLenght, transform.position.y); ;
            canLerp = true;
        }
        else if (swipeAngle < -45 && swipeAngle >= -135 && theLevel.GetGrid(x, y + 1) != null && theLevel.GetGrid(x, y + 1).number == 0) //Down
        {
            y++;
            startPosition = new Vector2(transform.position.x, transform.position.y); ;
            endPosition = new Vector2(transform.position.x, transform.position.y - moveLenght); ;
            canLerp = true;
        }

        if (canLerp)
        {
            if (theLevel.currentGameState == LevelController.GameState.MainMenu)
                theLevel.currentGameState = LevelController.GameState.Playing;
            theLevel.IncreaseMoveCount();
            SetGrid(lastX, lastY, 0);
            SetGrid(x, y, number);
            theLevel.CheckWin();
        }
    }

    public void UpdateText(int number)
    {
        numberText.text = number + "";
    }

    void SetGrid(int x, int y, int number)
    {
        theLevel.GetGrid(x, y).number = number;
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LevelController : MonoBehaviour
{
    public enum GameState
    {
        MainMenu, Playing, Wining
    }
    public GameState currentGameState = GameState.MainMenu;
    const int GRID_WIDTH = 4;
    const int GRID_HEIGHT = 4;
    float girdLenght = 2.0f;
    Grid[,] allGrid;
    List<int> allNumber;
    List<BlockController> allBlock;
    int count = 0;
    public GameObject BlockPrefabs;
    public int moveCount;
    public Text moveCountText;

    public float TimeCount;
    public Text timeCountText;

    public Text minMoveCountText;
    public Text minTimeCountText;
    private float minTime;
    private int minMove;

    void Start()
    {
        minTime = int.MaxValue;
        minMove = int.MaxValue;
        InitBlock();
    }

    void Update()
    {
        if (currentGameState == GameState.Playing)
        {
            TimeCount += Time.fixedDeltaTime;
            UpdateTimeCountText(timeCountText);
        }
    }

    void UpdateTimeCountText(Text theText)
    {
        int minute = (int)TimeCount / 60;
        int second = (int)TimeCount % 60;
        int fraction = (int)(TimeCount * 100);
        fraction = fraction % 100;
        theText.text = "Time : " + minute.ToString("00") + ":" + second.ToString("00") + ":" + fraction.ToString("00");
    }

    void ShowAllGrid()
    {
        for (int y = 0; y < GRID_WIDTH; y++)
            for (int x = 0; x < GRID_HEIGHT; x++)
                Debug.Log(allGrid[x, y].number);
    }

    public void CheckWin()
    {
        int count = 1;
        int correctPosition = 0;
        for (int y = 0; y < GRID_WIDTH; y++)
            for (int x = 0; x < GRID_HEIGHT; x++)
            {
                if (allGrid[x, y].number == count)
                    correctPosition++;
                count++;
            }
        if (correctPosition == GRID_WIDTH * GRID_HEIGHT - 1)
            Win();
    }

    public void Win()
    {
        if (TimeCount < minTime)
        {
            minTime = TimeCount;
            UpdateTimeCountText(minTimeCountText);
        }

        if (moveCount < minMove)
        {
            minMove = moveCount;
            UpdateMoveCountText(minMoveCountText);
        }

        currentGameState = GameState.Wining;
    }

    public Grid GetGrid(int x, int y)
    {
        if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT)
            return allGrid[x, y];
        return null;
    }

    void InitBlock()
    {
        allGrid = new Grid[GRID_WIDTH, GRID_HEIGHT];
        allBlock = new List<BlockController>();
        allNumber = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
        for (int y = 0; y < GRID_WIDTH; y++)
            for (int x = 0; x < GRID_HEIGHT; x++)
            {
                if (x == (GRID_WIDTH - 1) && y == (GRID_HEIGHT - 1))
                {
                    allGrid[x, y] = new Grid(x, y, 0);
                    allGrid[x, y].number = 0;
                    continue;
                }

                int index = Random.Range(0, allNumber.Count);
                int randomNumber = allNumber[index];
                allGrid[x, y] = new Grid(x, y, randomNumber);
                allNumber.RemoveAt(index);

                BlockController theBlock = Instantiate(BlockPrefabs, new Vector3(-3 + x * girdLenght, 3 - y * girdLenght, transform.position.z), Quaternion.identity).GetComponent<BlockController>();
                theBlock.UpdateText(randomNumber);
                theBlock.x = x;
                theBlock.y = y;
                theBlock.number = randomNumber;
                allBlock.Add(theBlock);
                allGrid[x, y].number = randomNumber;
            }
    }

    void RemoveBlock()
    {
        for (int i = 0; i < allBlock.Count; i++)
            Destroy(allBlock[i].gameObject);
    }

    public void Reset()
    {
        moveCount = 0;
        UpdateMoveCountText(moveCountText);
        TimeCount = 0;
        UpdateTimeCountText(timeCountText);
        RemoveBlock();
        InitBlock();
        currentGameState = GameState.MainMenu;
    }

    public void IncreaseMoveCount()
    {
        moveCount++;
        UpdateMoveCountText(moveCountText);
    }

    void UpdateMoveCountText(Text theText)
    {
        theText.text = "Move : " + moveCount;
    }
}<file_sep>﻿using UnityEngine;

public class LerpController : MonoBehaviour
{
    [Header("Lerp")]
    public AnimationCurve lerpCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1));
    private float progress;
    private float currentLerpTime;

    public bool LerpObject(Vector3 startPosition, Vector3 endPosition, float objectCooldown)
    {
        currentLerpTime += Time.fixedDeltaTime;
        if (currentLerpTime > objectCooldown)
        {
            currentLerpTime = objectCooldown;
        }
        progress = currentLerpTime / objectCooldown;
        transform.position = Vector3.Lerp(startPosition, endPosition, lerpCurve.Evaluate(progress));
        if (transform.position == new Vector3(endPosition.x, endPosition.y, transform.position.z))
        {
            currentLerpTime = 0;
            return false;
        }
        return true;
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Grid
{
    public int x, y, number;

    public Grid(int x, int y, int number)
    {
        this.x = x;
        this.y = y;
        this.number = number;
    }
}
