Slider Puzzle Example Code

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

using UnityEngine;

using Gamelogic;
using Gamelogic.Grids;

/**
  This example shows how the Grids library work with normal Unity Planes.
*/
public class SliderPuzzle : GLMonoBehaviour
{
  private class SliderCell
  {
    public RectPoint originalGridPoint;
    public GameObject cellObject;
  }

  public GameObject cellPrefab;
  public GameObject root;
  public int puzzleSize;
  public Texture2D puzzleImage;

  private RectGrid grid;
  private IMap3D map;
  private Vector2 cellDimensions = new Vector2(200, 200);

  private RectPoint emptyCell;

  public void Start()
  {
    BuildGrid();
    StartCoroutine(InitPuzzle());
  }

  public void Update()
  {
    HandleCell();

    if (IsGameFinished())
    {
      Debug.Log("Game finished: you solved the puzzle!");
    }
  }

  private bool IsGameFinished()
  {
    return grid
      .Where(gridPoint => gridPoint != emptyCell)
      .All(gridPoint => grid[gridPoint].originalGridPoint == gridPoint);
  }

  private void HandleCell()
  {
    if (Input.GetMouseButtonDown(0))
    {
      Vector3 worldPosition = ExampleUtils.ScreenToWorld(Input.mousePosition);
      RectPoint gridPosition = map[worldPosition];

      if (grid.Contains(gridPosition))
      {
        if (grid.GetNeighbors(gridPosition).Contains(emptyCell))
        {
          SwapWithEmpty(gridPosition);
        }
      }
    }
  }

  private void SwapWithEmpty(RectPoint gridPosition)
  {
    grid[emptyCell] = grid[gridPosition];
    grid[emptyCell].cellObject.transform.localPosition = map[emptyCell];
    grid[gridPosition] = null;
    emptyCell = gridPosition;
  }

  private void BuildGrid()
  {
    grid = RectGrid.Rectangle(puzzleSize, puzzleSize);

    map = new RectMap(cellDimensions)
      .AnchorCellMiddelCenter()
      .WithWindow(ExampleUtils.ScreenRect)
      .AlignMiddelCenter(grid)
      .To3DXY();

    float textureScale = 1f / puzzleSize;
    Vector2 textureScaleVector = new Vector2(textureScale, textureScale);

    foreach (RectPoint point in grid)
    {
      GameObject cellObject = Instantiate(cellPrefab);

      cellObject.transform.parent = root.transform;
      cellObject.transform.localPosition = map[point];

      cellObject.renderer.material.mainTexture = puzzleImage;
      cellObject.renderer.material.mainTextureScale = textureScaleVector;
      cellObject.renderer.material.mainTextureOffset = new Vector2(-textureScale * (point.X + 1), textureScale * point.Y);

      SliderCell cell = new SliderCell();
      cell.cellObject = cellObject;
      cell.originalGridPoint = point;

      grid[point] = cell;      
    }

    emptyCell = RectPoint.Zero;
    grid[emptyCell].cellObject.renderer.enabled = false;

  }

  private IEnumerator InitPuzzle2()
  {
    RectPoint lastPoint = emptyCell;
    RectPoint lastLastPoint = emptyCell;

    for (int i = 0; i < 2 * puzzleSize * puzzleSize; i++)    
    {
       RectPoint randomNeighbor = grid.GetNeighbors(emptyCell)
         .Where(point => (point != lastLastPoint))
         .SampleRandom(1)
         .First();

      lastLastPoint = lastPoint;
      lastPoint = randomNeighbor;
      SwapWithEmpty(randomNeighbor);
      yield return new WaitForSeconds(0.2f);
    }
  }

  private IEnumerator InitPuzzle()
  {
    Queue memory = new Queue();

    memory.Enqueue(emptyCell);
    memory.Enqueue(emptyCell);

    for (int i = 0; i < 2 * puzzleSize * puzzleSize; i++)
    {
       RectPoint oldPath = memory.Dequeue();
       RectPoint randomNeighbor = grid.GetNeighbors(emptyCell)
         .Where(point => (point != oldPath))
         .SampleRandom(1)
         .First();

      memory.Enqueue(randomNeighbor);
      SwapWithEmpty(randomNeighbor);

      yield return new WaitForSeconds(0.2f); //Let us see the shuffle!
    }
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top