首页 > 其他分享 >五子棋1 - 基本操作和胜负判断

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

时间:2024-01-18 23:44:29浏览次数:29  
标签:GridNum int 胜负 五子棋 private TurnFlag 基本操作 col row

效果

 

胜负的判断直接用的暴力的方式,以落子为中心水平方向前后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;
    }

}

 

标签:GridNum,int,胜负,五子棋,private,TurnFlag,基本操作,col,row
From: https://www.cnblogs.com/sailJs/p/17973690

相关文章

  • 计价软件教程-鹏业云计价i20(江苏)审核基本操作
    鹏业云计价i20(江苏)审核基础操作一、审核的概念与目标工程造价审核的概念:是指对建设项目全部成本的真实性、合法性进行的审查和评价;工程造价审核的目标主要包括:检查工程价格结算与实际完成的投资额的真实性、合法性;检查是否存在虚列工程、套取资金、弄虚作假、高估冒算的行为;二、......
  • git的常见基本操作
    一:概述git是开源的、免费的分布式版本控制系统,可以有效的高速的处理,从很小到非常大的项目版本管理。它的一些基本操作,需要使用者去掌握。二:具体说明<1>gitclone这个命令的作用是克隆远程版本到本地。gitcloneurl克隆远程版本仓库<2>gitcheckout-bdev克隆完之后,如果需要新建......
  • python实现五子棋
    1:效果图2:代码"""五子棋之人机对战"""importsysimportrandomimportpygamefrompygame.localsimport*importpygame.gfxdrawfromcollectionsimportnamedtupleChessman=namedtuple('Chessman','NameValueColor')P......
  • Hive基本操作
     Hive的基本操作很简单,与SQL的写法很类似,总结如下:  进入Hive环境     $HIVE_HOME/bin/hive  数据库操作       CREATE(DATABASE|SCHEMA)[IFNOTEXISTS]database_name[COMMENTdatabase_comment][LOCATIONhdfs_path][WITHDBPROPERTIE......
  • 【数据结构】C语言实现双链表的基本操作
    双链表导言大家好,很高兴又和大家见面啦!!!经过前面几个篇章的内容分享,相信大家对顺序表和单链表的基本操作都已经熟练掌握了。今天咱们将继续分享线性表的链式存储的第二种形式——双链表。在今天的内容中,咱们将介绍双链表的创建以及一些基本操作,接下来跟我一起来看看吧!一、单链表与双......
  • 【数据结构】C语言实现单链表的基本操作
    单链表基本操作的实现导言大家好,很高兴又和大家见面啦!!!在上一篇中,我们详细介绍了单链表的两种创建方式——头插法与尾插法,相信大家现在对这两种方式都已经掌握了。今天咱们将继续介绍单链表的基本操作——查找、插入与删除。在开始今天的内容之前,我们先通过尾插法创建一个单链表,如......
  • 2数据库之Mysql基本操作
                                                                                                      数据库基本类型、基本操作一.......
  • redis简介,基本操作
    reids简介 redis官网:https://redis.ioredis中文网:https://www.redis.net.cn  端口号默认6379退出:exit,ctrl+credis-server.exeredis.windows.confredis-cli.exe连接其他地方的redis,指定端口,位置redis-cli.exe-hlocalhost-p6379keys*  //查看......
  • Django ORM 基本操作
    本次sql大部分习题出自知乎以为网友,对原sql感兴趣的各位朋友,可以去参考知乎上的这位朋友:https://www.zhihu.com/tardis/bd/art/38354000?source_id=1001我们在他的基础上,进行sql改造,成为我们DjangoORM机制下的ORM语法。本次教程的面向人群:我们默认你会使用Django,至少能够自己......
  • 图像处理的基本操作
    图像处理最基本的操作,包括读取图像、显示图像、保存图像、获取图像属性等。下面将依次讲解这4个内容。1 读取图像OpenCV提供了用于读取图像的imread()方法,其语法格式如下:image=cv2.imread(filename,flags)参数说明:l image:是imread()方法的返回值,返回的是读......