五子棋1 - 基本操作和胜负判断

效果

 

胜负的判断直接用的暴力的方式,以落子为中心水平方向前后4个,垂直方向上下4个,2个对角线斜角前后4个 这样判断的,这个数量是固定的,不会随着棋盘的变大而变大,所以还好。

 

public class GoBangTest : MonoBehaviour
    , IPointerClickHandler
{
    public Text m_TimeBlack;
    public Text m_TimeWhite;

    public RectTransform m_GridDotTemplate; //棋盘格子分隔点
    public RectTransform m_ChessTemplate; //棋子

    public RectTransform m_BoardTrans; //棋盘
    public RectTransform m_BoardBgTrans; //棋盘背景
    public RectTransform m_ChessDownHintTrans; //落子提示

    private int m_GridNum = 15; //棋盘格子数量
    private int m_GridSize = 35; //棋盘格子像素大小

    private Queue<RectTransform> m_ChessObjPool = new Queue<RectTransform>(); //对象缓冲池

    private int[][] m_GridChess; //棋盘落子数据
    private int m_ChessDownRow = -1; //落子位置
    private int m_ChessDownCol = -1;
    private int m_ChessCount = 0; //已落子数量

    private int m_LastChessDownRow = -1; //上一步落子位置
    private int m_LastChessDownCol = -1;

    private int m_Status = 1; // 0_未开始, 1_进行中, 2_结果展示
    private int m_TurnFlag = 1; //1_黑色, 2_白色
    private float m_LeftTime = 15;

    private int m_MyChessColor = 1;

    public GameObject m_ResultLayer; //结果界面
    public Text m_ResultMsg;
    public Button m_BtnRestart;

    void Start()
    {
        m_BtnRestart.onClick.AddListener(OnClick_Restart);

        MoveOutChessDownHint();

        m_GridChess = new int[m_GridNum][];
        for (int row = 0; row < m_GridNum; ++row)
        {
            m_GridChess[row] = new int[m_GridNum];
        }

        int boardSize = m_GridNum * m_GridSize;
        m_BoardTrans.sizeDelta = new Vector2(boardSize, boardSize);
        float gridStartPos = boardSize * 0.5f - m_GridSize * 0.5f;

        Vector2 pos = Vector2.zero;
        for (int row = 0; row < m_GridNum; ++row)
        {
            pos.y = gridStartPos - row * m_GridSize;
            for (int col = 0; col < m_GridNum; ++col)
            {
                pos.x = -gridStartPos + col * m_GridSize;

                var gridDot = GameObject.Instantiate(m_GridDotTemplate);
                gridDot.gameObject.SetActive(true);
                gridDot.SetParent(m_BoardBgTrans, false);
                gridDot.anchoredPosition = pos;
            }
        }
    }

    //重新开始
    private void OnClick_Restart()
    {
        m_ResultLayer.SetActive(false);

        for (int i = 0; i < m_BoardTrans.childCount; ++i)
        {
            var childTrans = m_BoardTrans.GetChild(i);
            if (childTrans.name == "BoardBg" || childTrans.name == "ChessDownHint")
                continue;

            childTrans.gameObject.SetActive(false);
            m_ChessObjPool.Enqueue((RectTransform) childTrans);
        }

        for (int row = 0; row < m_GridNum; ++row)
        {
            for (int col = 0; col < m_GridNum; ++col)
            {
                m_GridChess[row][col] = 0;
            }
        }
        MoveOutChessDownHint();
        m_ChessCount = 0;
        m_LastChessDownRow = -1;
        m_LastChessDownCol = -1;

        m_Status = 1;
        m_TurnFlag = 1;
        m_LeftTime = 15;
    }

    void Update()
    {
        switch (m_Status)
        {
        case 1:
        {
            float leftTime = m_LeftTime - Time.deltaTime;
            m_LeftTime = leftTime;

            int turnFlag = m_TurnFlag;
            if (leftTime <= 0)
            {
                leftTime = 0;
                //m_LeftTime = 15;
            }

            if (1 == turnFlag)
            {
                m_TimeBlack.text = $"{Mathf.Ceil(leftTime)}s";
            }
            else if (2 == turnFlag)
            {
                m_TimeWhite.text = $"{Mathf.Ceil(leftTime)}s";
            }
        }
        break;

        }
    }

    private void MoveOutChessDownHint()
    {
        m_ChessDownRow = -1;
        m_ChessDownCol = -1;
        m_ChessDownHintTrans.anchoredPosition = new Vector2(-1200, -1200);
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (1 != m_Status) return;

        RectTransformUtility.ScreenPointToLocalPointInRectangle(m_BoardBgTrans, eventData.position, eventData.pressEventCamera, out var localPos);
        int boardSize = m_GridNum * m_GridSize;
        float boardHalfSize = boardSize * 0.5f;
        localPos.x += boardHalfSize;
        localPos.y = boardHalfSize - localPos.y;
        int row = Mathf.FloorToInt(localPos.y / m_GridSize);
        int col = Mathf.FloorToInt(localPos.x / m_GridSize);
        Debug.Log($"row:{row}, col:{col}");
        if (row < 0 || row >= m_GridNum || col < 0 || col >= m_GridNum)
        {
            Debug.LogWarning($"exceed row or col: {row}, {col}");
            MoveOutChessDownHint();
            return;
        }

        if (row != m_ChessDownRow || col != m_ChessDownCol)
        {
            float gridStartPos = boardHalfSize - m_GridSize * 0.5f;
            m_ChessDownRow = row;
            m_ChessDownCol = col;
            m_ChessDownHintTrans.anchoredPosition = new Vector2(-gridStartPos + col * m_GridSize, gridStartPos - row * m_GridSize);
        }
        else //落子
        {
            if (0 != m_GridChess[row][col])
            {
                Debug.LogWarning($"have chess: {row}, {col}");
                return;
            }

            MoveOutChessDownHint();

            DownChess(row, col);
        }
    }

    private void DownChess(int row, int col)
    {
        m_LastChessDownRow = row;
        m_LastChessDownCol = col;

        int boardSize = m_GridNum * m_GridSize;
        float boardHalfSize = boardSize * 0.5f;

        RectTransform chessTrans = null;
        if (m_ChessObjPool.Count > 0)
            chessTrans = m_ChessObjPool.Dequeue();
        else
            chessTrans = GameObject.Instantiate(m_ChessTemplate);

        chessTrans.gameObject.SetActive(true);
        chessTrans.SetParent(m_BoardTrans, false);
        float gridStartPos = boardHalfSize - m_GridSize * 0.5f;
        chessTrans.anchoredPosition = new Vector2(-gridStartPos + col * m_GridSize, gridStartPos - row * m_GridSize);
        m_GridChess[row][col] = m_TurnFlag;
        if (1 == m_TurnFlag)
            chessTrans.GetComponent<Graphic>().color = Color.black;
        else if (2 == m_TurnFlag)
            chessTrans.GetComponent<Graphic>().color = Color.white;
        m_ChessCount++;
        if (m_ChessCount >= m_GridNum * m_GridNum) //格子满了, 平局
        {
            m_Status = 2;
            m_ResultLayer.SetActive(true);
            m_ResultMsg.text = "平局";
            return;
        }

        if (CheckIsWin(row, col))
            return;

        m_TurnFlag = 3 - m_TurnFlag;

        //落子后重新计时
        m_LeftTime = 15;
    }

    //检查是否有人赢了
    private bool CheckIsWin(int row, int col)
    {
        //检查水平, 垂直, 对角1, 对角2, 是否有5个子连在一起的
        if (CheckSameChessColorNum(m_TurnFlag, row, col, 1, 0, out var emptyBreakNum) >= 4 //水平
            || CheckSameChessColorNum(m_TurnFlag, row, col, 0, 1, out emptyBreakNum) >= 4 //垂直
            || CheckSameChessColorNum(m_TurnFlag, row, col, 1, 1, out emptyBreakNum) >= 4 //对角1
            || CheckSameChessColorNum(m_TurnFlag, row, col, -1, 1, out emptyBreakNum) >= 4 //对角2
        )
        {
            m_Status = 2;
            Debug.Log($"{m_TurnFlag} win !!!");
            m_ResultLayer.SetActive(true);
            if (1 == m_TurnFlag)
                m_ResultMsg.text = "黑棋胜";
            else
                m_ResultMsg.text = "白棋胜";
            return true;
        }

        return false;
    }

    //检查某个方向连续同色数量
    private int CheckSameChessColorNum(int chessColor, int rowStart, int colStart, int xDir, int yDir, out int emptyBreakNum)
    {
        emptyBreakNum = 0;
        int sameColorNum = 0; //连续同色数量
        //正向
        for (int i = 1; i <= 4; ++i)
        {
            int row = rowStart + xDir * i;
            if (row < 0 || row >= m_GridNum) continue;
            int col = colStart + yDir * i;
            if (col < 0 || col >= m_GridNum) continue;

            if (m_GridChess[row][col] == chessColor)
            {
                sameColorNum++;
                if (sameColorNum >= 4)
                    return sameColorNum;
            }
            else
            {
                if (0 == m_GridChess[row][col]) //遇到没有落子的grid结束
                    emptyBreakNum++;

                break;
            }
        }

        //反向
        for (int i = -1; i >= -4; --i)
        {
            int row = rowStart + xDir * i;
            if (row < 0 || row >= m_GridNum) continue;
            int col = colStart + yDir * i;
            if (col < 0 || col >= m_GridNum) continue;

            if (m_GridChess[row][col] == chessColor)
            {
                sameColorNum++;
                if (sameColorNum >= 4)
                    return sameColorNum;
            }
            else
            {
                if (0 == m_GridChess[row][col]) //遇到没有落子的grid结束
                    emptyBreakNum++;

                break;
            }
        }

        return sameColorNum;
    }

}

 

posted @ 2024-01-18 23:38  yanghui01  阅读(25)  评论(0编辑  收藏  举报