Unity制作扫雷游戏

曾经在网上看了一篇扫雷教程,链接如下:https://noobtuts.com/unity/2d-minesweeper-game

但是照着做出来有点问题,后来自己尝试的做了一个,效果如图:

Unity制作扫雷游戏_第1张图片


主要有三个代码,一个是排序代码,一个是管理脚本,还有一个是子物体属性脚本,脚本内容如下:


GridTransform.cs

using UnityEngine;
using System.Collections;

public class GridTransform : MonoBehaviour
{

    //排序的列数
    public int column = 1;

    //间距的宽和高
    public float space_w;
    public float space_h;

    //组件对象的宽和高
    public float width;
    public float Height;

    //排序对象的数目
    public int itemNumber;

    public bool Direction;

    //字段封装实时排序
    public bool repositionNow
    {
        set
        {
            _repositionNow = value;
            if (value)
            {
                Sort();
                _repositionNow = false;
            }
        }

        get
        {
            return _repositionNow;
        }
    }
    private bool _repositionNow;

    //排序方法
    void Sort()
    {
        itemNumber = transform.childCount; ;
        for (int i = 0; i < itemNumber; i++)
        {
            transform.GetChild(i).localPosition = new Vector3((width + space_w) * ((i) % (column)), (Direction?1:-1)*((i) / column) * (Height + space_h), 0);
        }
    }
}

Element.cs

using UnityEngine;
using System.Collections;


public enum MineState
{
    Empty = 0,
    Mine = 1,
    Num = 2,
    MaybeMine = 3
}

public class Element : MonoBehaviour
{

    /// 
    /// current box mine state
    /// 
    public MineState mine;

    public Sprite[] emptyTextures;
    public Sprite mineTexture;

    public void loadTexture(int mineCount = 0)
    {
        if ((int)mine == 1)
            GetComponent().sprite = mineTexture;
        else
            GetComponent().sprite = emptyTextures[mineCount];
    }


    public bool isCovered()
    {
        return GetComponent().sprite.texture.name == "default";
    }

    void OnMouseUpAsButton()
    {
        Debug.Log(transform.localPosition.x + "   " + transform.localPosition.y+"    "+mine);

        if ((int)mine == 1)
        {
            MineManager.Instance.uncoverMines();

            print("you lose");
        }
        else
        {
            int x = (int)transform.localPosition.x;
            int y = (int)transform.localPosition.y;
            loadTexture(MineManager.Instance.MineCount(x, y));

            MineManager.Instance.FFuncover(x, y, new bool[MineManager.Instance.width, MineManager.Instance.height]);

            if (MineManager.Instance.isFinished())
            {
                print("you win");
            }

        }
    }


}

MineManager.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MineManager : MonoBehaviour
{

    public GameObject elementPrefab;
    public GridTransform grid;

    public int width;
    public int height;

    public Element[,] elements;

    public int mineNumber;

    public ArrayList MineLocation;

    public static MineManager Instance;

    // Use this for initialization
    void Start()
    {
        Instance = this;

        elements = new Element[width, height];

        MineLocation = new ArrayList();

        Init();
    }

    void Init()
    {

        //create element
        for (int j = 0; j < height; j++)
        {
            for (int i = 0; i < width; i++)
            {
                elements[i, j] = CreateElement();
                elements[i, j].mine = MineState.Empty;
            }
        }

        //reset position
        grid.repositionNow = true;


        //random mine in the current elements
        for (int n = 0; n < mineNumber; n++)
        {
            int k = Random.Range(0, width);
            int m = Random.Range(0, height);

            Vector2 temp = new Vector2(k, m);

            if (MineLocation.Contains(temp))
            {
                n--;
                continue;
            }
            elements[k, m].mine = MineState.Mine;

            Debug.Log(elements[k, m].mine);

            //elements[k, m].loadTexture();

            var c = new Vector2(k, m);

            Debug.Log(c);
            MineLocation.Add(c);
        }

        //set numbers near mine
        foreach (var item in MineLocation)
        {
            Vector2 t = (Vector2)item;
            int x = (int)t.x;
            int y = (int)t.y;
            JudegeMinesNear(x - 1, y + 1);
            JudegeMinesNear(x, y + 1);
            JudegeMinesNear(x + 1, y + 1);
            JudegeMinesNear(x - 1, y);
            JudegeMinesNear(x + 1, y);
            JudegeMinesNear(x - 1, y - 1);
            JudegeMinesNear(x, y - 1);
            JudegeMinesNear(x + 1, y - 1);
        }

    }

    // Find out if a mine is at the coordinates
    public bool mineAt(int x, int y)
    {
        // Coordinates in range? Then check for mine.
        if (x >= 0 && y >= 0 && x < width && y < height)
            return (int)elements[x, y].mine == 1;
        return false;
    }


    public bool IsInclude(int x, int y)
    {
        if (x >= 0 && y >= 0 && x < width && y < height)
            return true;
        return false;
    }

    public void JudegeMinesNear(int x, int y)
    {
        if (IsInclude(x, y) == false)
            return;

        if ((int)elements[x, y].mine != 1)
        {
            elements[x, y].mine = MineState.Num;
            //elements[x, y].loadTexture(MineCount(x, y));
        }

    }

    // Count adjacent mines for an element
    public int MineCount(int x, int y)
    {
        int count = 0;

        if (mineAt(x, y + 1)) ++count; // top
        if (mineAt(x + 1, y + 1)) ++count; // top-right
        if (mineAt(x + 1, y)) ++count; // right
        if (mineAt(x + 1, y - 1)) ++count; // bottom-right
        if (mineAt(x, y - 1)) ++count; // bottom
        if (mineAt(x - 1, y - 1)) ++count; // bottom-left
        if (mineAt(x - 1, y)) ++count; // left
        if (mineAt(x - 1, y + 1)) ++count; // top-left
        return count;
    }

    // Flood Fill empty elements
    public void FFuncover(int x, int y, bool[,] visited)
    {
        // Coordinates in Range?
        if (IsInclude(x,y))
        {
            // visited already?
            if (visited[x, y])
                return;

            // uncover element
            elements[x, y].loadTexture(MineCount(x, y));
            Debug.Log("            " + x + "   " + y);
            // close to a mine? then no more work needed here
            if (MineCount(x, y) > 0)
                return;

            // set visited flag
            visited[x, y] = true;

            // recursion
            FFuncover(x - 1, y + 1, visited);
            FFuncover(x, y + 1, visited);
            FFuncover(x + 1, y + 1, visited);
            FFuncover(x - 1, y, visited);
            FFuncover(x + 1, y, visited);
            FFuncover(x - 1, y - 1, visited);
            FFuncover(x, y - 1, visited);
            FFuncover(x + 1, y - 1, visited);
            Debug.Log("----------------------------------------");
        }
    }

    // Uncover all Mines
    public void uncoverMines()
    {
        foreach (Element elem in elements)
            if (elem.mine == MineState.Mine)
                elem.loadTexture(0);
    }

    Element CreateElement()
    {
        GameObject temp = Instantiate(elementPrefab) as GameObject;
        temp.transform.parent = grid.transform;
        temp.transform.position = Vector3.zero;

        return temp.GetComponent();
    }

    public bool isFinished()
    {
        // Try to find a covered element that is no mine
        foreach (Element elem in elements)
            if (elem.isCovered() && (int)elem.mine != 1)
                return false;
        // There are none => all are mines => game won.
        return true;
    }
}


最终运行起来有点卡,也许MineManager还能优化,有建议的告诉我哈!


工程下载

你可能感兴趣的:(Unity3d)