之前用C#在VS上写了个2048小游戏的核心代码,许多小伙伴不是很清楚具体效果,这不,Unity可视化2048小游戏来了
具体效果图如下,通过上下左右键来控制数字移动,右上角是维度输入(也可以叫难度吧,我这里限制了范围,感兴趣的可以调整),点击确定就可以开始游戏了。
1、新建场景和UI界面,大概有个样子就行。
2、新建一个简单的预制体(Image+Text)
3、将InputField的ContentType设置为int类型。
4、新建CoreFun脚本。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using Random = UnityEngine.Random;
//没有注释,掉完不少头发后还是不懂评论留言
public class CoreFun : MonoBehaviour
{
public Button sureBtn;
public InputField inputNumIF;
private int inputNum;
private int[,] coreArr;
public GameObject blockPrefab;
public Transform blockPar;
public Text[,] blocksArr;
private void Start()
{
sureBtn.onClick.AddListener(ClickSureBtn);
}
public void ClickSureBtn()
{
if (inputNumIF.text == null || Convert.ToInt32(inputNumIF.text) <= 4 || Convert.ToInt32(inputNumIF.text) > 8)
{
Debug.Log("超出设定范围");
return;
}
inputNum = Convert.ToInt32(inputNumIF.text);
coreArr = new int[inputNum, inputNum];
blocksArr = new Text[inputNum, inputNum];
blockPar.GetComponent<GridLayoutGroup>().constraintCount = inputNum;
RandomCreateNum();
for (int i = 0; i < blocksArr.GetLength(0); i++)
{
for (int j = 0; j < blocksArr.GetLength(1); j++)
{
GameObject go = GameObject.Instantiate(blockPrefab, blockPar);
go.transform.GetChild(0).GetComponent<Text>().text = coreArr[i, j].ToString();
blocksArr[i, j] = go.transform.GetChild(0).GetComponent<Text>();
}
}
Print(coreArr);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Move(coreArr, MoveDirection.Up);
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Move(coreArr, MoveDirection.Down);
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
Move(coreArr, MoveDirection.Left);
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
Move(coreArr, MoveDirection.Right);
}
}
private void RandomCreateNum()
{
for (int i = 0; i < coreArr.GetLength(0); i++)
{
for (int j = 0; j < coreArr.GetLength(1); j++)
{
int num = Random.Range(0, 8);
switch (num)
{
case 0:
case 1:
coreArr[i, j] = 0;
break;
case 2:
case 3:
coreArr[i, j] = 2;
break;
case 4:
case 5:
coreArr[i, j] = 4;
break;
case 6:
case 7:
coreArr[i, j] = 8;
break;
}
}
}
}
/// <summary>
/// 上移
/// </summary>
/// <param name="map"></param>
/// <returns></returns>
private int[,] Up(int[,] map)
{
for (int j = 0; j < map.GetLength(1); j++)
{
int[] array = new int[map.GetLength(0)];
for (int i = 0; i < map.GetLength(0); i++)
{
array[i] = map[i, j];
}
array = Merge(array);
for (int i = 0; i < map.GetLength(0); i++)
{
map[i, j] = array[i];
}
}
return map;
}
/// <summary>
/// 下移
/// </summary>
/// <param name="map"></param>
/// <returns></returns>
private int[,] Down(int[,] map)
{
for (int j = 0; j < map.GetLength(1); j++)
{
int[] array = new int[map.GetLength(0)];
for (int i = map.GetLength(0) - 1; i >= 0; i--)
{
array[map.GetLength(0) - 1 - i] = map[i, j];
}
array = Merge(array);
for (int i = map.GetLength(0) - 1; i >= 0; i--)
{
map[i, j] = array[map.GetLength(0) - 1 - i];
}
}
return map;
}
/// <summary>
/// 左移
/// </summary>
/// <param name="map"></param>
/// <returns></returns>
private int[,] Left(int[,] map)
{
int[] arr = new int[map.GetLength(0)];
for (int j = 0; j < map.GetLength(1); j++)
{
for (int i = 0; i < map.GetLength(1); i++)
{
arr[i] = map[j, i];
}
arr = Merge(arr);
for (int i = 0; i < map.GetLength(1); i++)
{
map[j, i] = arr[i];
}
}
return map;
}
/// <summary>
/// 右移
/// </summary>
/// <param name="map"></param>
/// <returns></returns>
private int[,] Right(int[,] map)
{
int[] arr = new int[map.GetLength(1)];
for (int i = 0; i < map.GetLength(0); i++)
{
for (int j = map.GetLength(1) - 1; j >= 0; j--)
{
arr[map.GetLength(1) - 1 - j] = map[i, j];
}
arr = Merge(arr);
for (int j = map.GetLength(1) - 1; j >= 0; j--)
{
map[i, j] = arr[map.GetLength(1) - 1 - j];
}
}
return map;
}
/// <summary>
/// 去0
/// </summary>
/// <param name="arr"></param>
/// <returns></returns>
private int[] RemoveZero(int[] arr)
{
int k = 0;
int[] array = new int[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] != 0)
{
array[k] = arr[i];
k++;
}
}
return array;
}
/// <summary>
/// 合并
/// </summary>
/// <param name="arr"></param>
/// <returns></returns>
private int[] Merge(int[] arr)
{
arr = RemoveZero(arr);
for (int i = 0; i < arr.Length - 1; i++)
{
if (arr[i] != 0 && arr[i] == arr[i + 1]) //可加一个判断是否为0;不加也一样
{
arr[i] *= 2;
arr[i + 1] = 0;
i++;
}
}
arr = RemoveZero(arr);
return arr;
}
private void Print(int[,] map)
{
for (int i = 0; i < map.GetLength(0); i++) //GetLength(0)拿行长度;GetLength(1)拿列长度
{
for (int j = 0; j < map.GetLength(1); j++)
{
blocksArr[i, j].text = map[i, j].ToString();
}
}
}
private void Move(int[,] map, MoveDirection moveDirection)
{
switch (moveDirection)
{
case MoveDirection.Up:
Up(map);
Debug.Log("上");
break;
case MoveDirection.Down:
Down(map);
Debug.Log("下");
break;
case MoveDirection.Left:
Left(map);
Debug.Log("左");
break;
case MoveDirection.Right:
Debug.Log("右");
Right(map);
break;
}
Print(map);
}
}
5、将CoreFun脚本随便放一个物体下。按下图拖入赋值。
6、总结
试过的小伙伴就会发现许多不足,像移动的时候没有新的数字生成(这个好解决,在Move下写一个方法判断coreArr是否发生了变化,有变化就在coreArr中为0的位置随机生成一个数字);生成coreArr的时候没有填满整个蓝色地图(可以通过inputNum计算GridLayoutGroup的CellSize和Spacing就行)。其实我是故意的,这些优化就需要留给各位了,脑洞大开的玩家也可以为2048发明新型玩法,这样也可以提升一下代码能力。好吧,说这么多,我就是懒☺。