扫雷游戏

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

//public enum GameState
//{
//    NormalState,
//    MineState,
//}
//坐标数据
// 这个类主要是用来存储当前方格的状态和是否有雷
public class Point
{
    public int x;
    public int y;
    public int flag;// 0 表示未翻开,1表示以翻开 2表示标记为雷
    public int state;//0 表示没有雷 1表示有地雷
    //private int nabar; //周围的炸弹数量
    public Point(int _x, int _y)
    {
        this.x = _x;
        this.y = _y;
        this.flag = 0;
        this.state = 0;
    }
    public int Flag
    {
        get{return flag;}
        set{flag = value;}
    }
}
public class GamePlayScript : MonoBehaviour {

    public Texture2D bg;
    public Texture2D mine;
    public Texture2D[] number;
    public Texture2D flagImage;
    public Texture2D error;
    public GUISkin skin;// GUI皮肤
    public int row;// 地图的行数
    public int col;// 地图的列数
    public int countMine;//输入随机的雷数
    
    const int GameWidth = 320;// 游戏窗体的宽
    const int GameHeight = 480;
    const int blankWidth = 32;// 方块的宽
    const int blankHeight = 32;
    
    static int clearMines = 0;  //成功清除炸弹数量
    static int gameTime = 0;
    static int sec = 0;
    static int minute = 0;
//    public float updateInterval = 0.5F;
//    private double lastInterval;
//    private int frames = 0;
//    private float fps;
    
    float secTime;// 定时器
    float mouseX;// 鼠标点击的x坐标
    float mouseY;// 鼠标点击的y坐标
    Texture2D[,] tempImage;
    int[,] isMine;// 存放随机数据的 0没有1是有雷
    Point[,] point;// 存储当前方格的状态和是否有雷
    bool isWin;
    bool isOver;
    float tempTime;// 2秒后跳转界面

    
    // Use this for initialization
    void Awake () {
        mouseX = 0f;
        mouseY = 0f;
        isWin = false;
        isOver = false;
        tempTime = 0f;
        secTime = 0f;
//        lastInterval = Time.realtimeSinceStartup;
//        frames = 0;
        RandomMine();
        InitDatas();
    }
    
    // Update is called once per frame
    void Update () {
        if(!isWin && !isOver)
        {
            MouseListener(); //鼠标监听事件
            if( secTime > 1f )
            {
                secTime = 0;
                sec = ++gameTime;
                sec %= 60;
                if( 0 == gameTime % 60 )
                {
                    minute += 1;
                    if(0 == gameTime % 3600)
                    {
                        minute = 0;
                    }
                }
            }
            else{
                secTime += Time.deltaTime;
            }
        }
    }
//    void ClockTime()//一个FPs计时器
//    {
//        ++frames;
//        float timeNow = Time.realtimeSinceStartup;
//        if (timeNow > lastInterval + updateInterval) {
//            fps = frames / (timeNow - (float)lastInterval);
//            frames = 0;
//            lastInterval = timeNow;
//        }
//    }
    void OnGUI()
    {
        GUI.skin = skin;
        GUI.Window( 1,new Rect(((Screen.width - (int)GameWidth) >> 1)+15,(Screen.height - (int)GameHeight) >> 1, GameWidth, GameHeight ),WindowFun,"扫雷" );
        for(int i = 1; i < row; ++i)
        {
            for(int j = 1; j < col; ++j)
            {
                GUI.Button(new Rect( j * blankWidth + ((Screen.width - blankWidth * col ) >> 1), i * blankHeight + ((Screen.height - blankHeight * row) >> 1) ,blankWidth,blankHeight),tempImage[i,j]);
            }
        }
        GUI.skin.label.alignment = TextAnchor.MiddleCenter;
        GUI.skin.label.normal.textColor = Color.red;
        GUI.skin.label.fontSize = 18;
        GUI.Label( new Rect(((Screen.width - (int)GameWidth) >> 1)+20,(Screen.height - (int)GameHeight) >> 1,100f,20f ), minute.ToString() + ":" + sec.ToString());//
        if( isWin )
        {
            
            GUI.skin.label.fontSize = 40;
            GUI.skin.label.normal.textColor = Color.red;
            GUI.Label(new Rect( 0f,0f,Screen.width, Screen.height),string.Format("您胜利了"));
            if( tempTime > 4f )
            {
                Application.LoadLevel("Menu");
            }
            else
                tempTime += Time.deltaTime;
        }
        if( isOver )
        {
            //GUI.skin.label.alignment = TextAnchor.MiddleCenter;
            GUI.skin.label.fontSize = 40;
            GUI.skin.label.normal.textColor = Color.red;
            GUI.Label(new Rect( 0f,0f,Screen.width, Screen.height),string.Format("您失败了"));
            if( tempTime > 4f )
            {
                Application.LoadLevel("Menu");
            }
            else
                tempTime += Time.deltaTime;
        }
    }
    public void RandomMine()
    {
        tempImage = new Texture2D[row+1,col+1];
        isMine = new int[row+1,col+1];
        for(int i = 1; i < row; ++i)
        {
            for(int j = 1; j < col; ++j)
            {
                isMine[i,j] = 0;//没有雷
                tempImage[i,j] = bg;
            }
        }
        int count = 0;
        while(count < countMine)
        {
            int i = Random.Range(1,row);
            int j = Random.Range(1,col);
            if( 0 == isMine[i,j] )
            {
                isMine[i,j] = 1;//放置雷
                count++;
                //tempImage[i,j] = mine;//测试查看地雷位置
            }
        }
    }
    public void InitDatas()
    {
        point = new Point[row+1,col+1];
        for(int i = 1; i < row; ++i)
        {
            for(int j = 1; j < col; ++j)
            {
                point[i,j] = new Point(i,j);
                point[i,j].state = isMine[i,j];
            }
        }
    }
    public void MouseListener()
    {
        mouseX = Input.mousePosition.x;
        mouseY = Screen.height - Input.mousePosition.y;
        int r = (int)(mouseY - ((Screen.height - blankHeight * row) >> 1)) / blankHeight;
        int c = (int)(mouseX - ((Screen.width - blankWidth * col) >> 1)) / blankWidth;
        if(Input.GetMouseButtonDown(0))
        {
            if( 1 == isMine[r,c] )//点中雷 gameover
            {
                tempImage[r,c] = mine;
                isOver = true;
            }
            else
            {
                int count = MineCount(r,c);
                
                if( 0 == count ) //如果该砖块周围没有地雷就进打开周围砖块
                {
                    Clear(r,c);
                }
                else{
                    point[r,c].flag = 1;
                }
                CheckGame();
            }
        }
        if(Input.GetMouseButtonDown(1))//右键插红旗
        {
            RightBtnMine(r,c);
        }
    }
    //计算周围地雷的数量并根据地雷数量在该砖块上添加相应数值图片
    public int MineCount(int i, int j)
    {
        int row = i;
        int col = j;
        int countMine = 0;
                // right
                if( 1 == isMine[i,j+1] )
                {
                    countMine++;            
                }//bottom
                
                if( 1 == isMine[i+1,j] )
                {
                    countMine++;        
                }
                // left
                if( 1 == isMine[i,j-1])
                {
                    countMine++;
                }
                // top
                if(1 == isMine[i-1,j])
                {
                    countMine++;
                }//left top 
                if(1 == isMine[i-1,j-1])
                {
                    countMine++;
                }//left bottom
                if(1 == isMine[i+1,j-1])
                {
                    countMine++;
                }//right top
                if(1 == isMine[i-1,j+1])
                {
                    countMine++;
                }
                if(1 == isMine[i+1,j+1])
                {
                    countMine++;
                }

        //Debug.Log( countMine.ToString() );
        
        tempImage[row,col] = number[countMine];
        return countMine;
    }
    
    //清除周围没有地雷砖块周围的砖块
    public void Clear(int x, int y)
    {
        int i = x;
        int j = y;
        // 如果不是未翻开状态,则退出
        if( 0 != point[i,j].flag )
            return;
        point[i,j].flag = 1;
        if(point[i,j].state == 0)
        {
            //当前的周围没有雷,就进行递归的排雷 
            if( 0 == isMine[i,j] )//
            {  
                if(j+1 < col && 0 == MineCount(i,j+1)){Clear(i,j+1);}
                if(i+1 < row && 0 == MineCount(i+1,j)){Clear(i+1,j);}
                if(j-1 >= 1 && 0 == MineCount(i,j-1)){Clear(i,j-1);}    
                if(i-1 >= 1 && 0 == MineCount(i-1,j)){Clear(i-1,j);}
                if(i-1 >= 1 && j-1 >= 1 && 0 == MineCount(i-1,j-1)){Clear(i-1,j-1);}
                if(i+1 < row && j-1 >= 1 && 0 == MineCount(i+1,j-1)){Clear(i+1,j-1);}
                if(i-1 >= 1 && j+1 < col && 0 == MineCount(i-1,j+1)){Clear(i-1,j+1);}
                if(i+1 < row && j+1 < col && 0 == MineCount(i+1,j+1)){ Clear(i+1,j+1);}
                
            }
        }
        CheckGame();
        
    }
    public void RightBtnMine(int x, int y)
    {
        int i = x;
        int j = y;
        // 已经翻开则不能右击
        if( 1 == point[i,j].flag)
            return;
        // 没有翻开则插红旗
        if( 0 == point[i,j].flag )
        {
            tempImage[i,j] = flagImage;
            if( 1 == point[i,j].state )
                clearMines++;//扫雷数增加
            
            point[i,j].flag = 2;
        }
        // 判断不是地雷则选回来
        else 
        {
            tempImage[i,j] = bg;
            if( 1 == point[i,j].state)
                clearMines--;
            
            point[i,j].flag = 0;
        }
        CheckGame();
    }
    public void CheckGame()
    {
        //清除所有雷 
        Debug.Log(string.Format("clerMines={0}",clearMines));
        if( clearMines == countMine )
        {
            for(int i = 1; i < row; ++i)
            {
                for(int j = 1; j < col; ++j)
                {
                    if( tempImage[i,j] == bg )
                    {
                        return;//还有没有翻开的
                    }
                }
            }
            Debug.Log(string.Format("nin win l"));
            isWin = true;
        }
    }
    public void WindowFun(int id)
    {
        
    }
}
原文地址:https://www.cnblogs.com/lihonglin2016/p/4321388.html