zoukankan      html  css  js  c++  java
  • AcWing 1324. 五子棋 模拟 (2016 年清华大学计算机系推研)

    地址 https://www.acwing.com/problem/content/description/1326/

    小 A 和小 B 在下五子棋。
    
    五子棋是在一个由网格构成的棋盘内进行的。
    
    网格有 1515 列,共有 225 个交叉点。
    
    小 A 先手执黑棋,小 B 后手执白棋。
    
    两人轮流下棋,每次下棋都将一个自己的棋子放在棋盘上一个空白的交叉点上。
    
    然而,由于小 A 和小 B 都不知道五子棋的胜利条件,所以即使有一方已经胜利了,他们仍然会继续下棋。
    
    现在想请你帮忙分析一下,所下的棋局是在第几步结束的。
    
    当然,也有可能他们最终仍然没有分出胜负,这时请判定他们平局。
    
    五子棋的胜利条件是这样的:当同一行或同一列或同一斜线(即与网格线成 45° 角的直线)上连续的五个或五个以上交叉点放有同色棋子的时候,立即判定使用该颜色棋子的玩家获得胜利,游戏结束。
    
    输入格式
    第一行输入一个正整数 n,表示双方总共下了多少步棋。
    
    接下来 n 行,每行两个正整数。其中,第 i 行的两个数 x,y 表示第 i 步的棋子下在了第 x 条横线和第 y 条竖线的交叉点上。若 i 为奇数,则这个棋子是黑棋,否则是白棋。
    
    输出格式
    若没有人获得胜利,你需要输出“Tie”(不含引号)。
    
    否则,若小 A 获胜,输出 “A”(不含引号),若小 B 获胜,输出 “B”(不含引号);并输出一个正整数 w 表示第 w 步下完后游戏应当结束,字母与整数间用一个空格隔开。
    
    数据范围
    对于 20% 的数据,游戏结果是平局。
    对于 30% 的数据,游戏在最后一手结束。
    对于 100% 的数据,0≤n≤2251≤x,y≤15。
    
    输入样例:
    9
    1 1
    2 1
    1 2
    2 2
    1 3
    2 3
    1 4
    2 4
    1 5
    输出样例:
    A 9

    算法1
    这是一道模拟题
    主要是代码要简洁。
    八个方向的检测是否连成五子可以精简成4个方向。
    4个方向的检测可以使用for循环减少重复代码。
    还需要一个检测x y是否在棋盘内的代码。

    有了以上函数 代码可以简短不少

    C++ 代码

    #include <iostream>
    
    using namespace std;
    
    const int N = 15;
    int board[N + 5][N + 5];
    int n;
    int winid = 0;
    
    //0右 1 左 2下  3上 4右下 5左上 6下左 7右上
    int xyAdd[8][2] = {
        {0,1},{0,-1},   //y+-
        {1,0},{-1,0},   //x+-
        {1,1},{-1,-1},  //xy+-
        {1,-1},{-1,1}   //x+- y-+
    };
    
    //检测是否是正确坐标 是则返回真
    bool IsValidCoordinatesXY(int x, int y)
    {
        if (x < 1 || x > N || y < 1 || y > N) return false;
        return true;
    }
    
    
    bool Check(int x, int y, int id)
    {
        bool ret = false;
    
        int count = 1;
        for (int i = 0; i < 4; i++) {
            int lx = x; int ly = y; int rx = x; int ry = y;
            count = 1;
            lx += xyAdd[i * 2][0]; ly += xyAdd[i * 2][1];
            while (IsValidCoordinatesXY(lx, ly) && board[lx][ly] == id) {
                count++; lx += xyAdd[i * 2][0]; ly += xyAdd[i * 2][1];
            }
            rx += xyAdd[i * 2 + 1][0]; ry += xyAdd[i * 2 + 1][1];
            while (IsValidCoordinatesXY(rx, ry) && board[rx][ry] == id) {
                rx += xyAdd[i * 2 + 1][0]; ry += xyAdd[i * 2 + 1][1]; count++;
            }
            if (count >= 5) return true;
        }
    
    
        return false;
    }
    
    int main()
    {
        cin >> n;
    
        for (int i = 1; i <= n; i++) {
            int x, y;
            cin >> x >> y;
            board[x][y] = i % 2 + 1;
            if (i > 8) {
                if (Check(x, y, i % 2 + 1)) {
                    if (i % 2 == 1) { cout << "A " << i << endl; }
                    else { cout << "B " << i << endl; }
                    return 0;
                }
            }
        }
    
        cout << "Tie" << endl;
        return 0;
    }
    
    作者:itdef
    链接:https://www.acwing.com/solution/content/19189/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Linux常用命令学习2---(文件搜索命令locate find、命令搜索命令whereis which、字符串搜索命令grep、帮助命令man)
    LeetCode Perfect Squares
    华为笔试 数字转中文拼音
    二位数组 顺时针打印矩阵
    LeetCode Interleaving String
    LeetCode Coins in a Line
    LeetCode Backpack
    LeetCode Unique Paths
    LeetCode Minimum Path Sum
    腾讯模拟笔试题
  • 原文地址:https://www.cnblogs.com/itdef/p/13554806.html
Copyright © 2011-2022 走看看