五子棋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; } }