RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1227586
Accepted
Максим Фисман
Максим Фисман
Asked:2022-01-06 02:05:19 +0000 UTC2022-01-06 02:05:19 +0000 UTC 2022-01-06 02:05:19 +0000 UTC

如何在 3x3 数组中查找 T、L 或 + 类型的连接

  • 772

制作游戏“三连冠”遇到了这样一个问题。我需要像这样销毁组:

Буква T:          Буква L:          Знак +:
1 1 1             1 0 0             0 1 0
0 1 0             1 0 0             1 1 1
0 1 0             1 1 1             0 1 0

其中一个是相同颜色的块,而零是其他一些。而且,这些字母可以旋转 90、-90、180 度。

到目前为止,我已经能够让程序明白,某个组合是这样一个字母:

// Определяем, сколько точек есть на одной линии при определенном X и Y
// conn - это массив Vector2Int единичек
        Dictionary<int, int> dictX, dictY;
        dictX = dictY = new Dictionary<int, int>();
        for (int i = 0; i < conn.Length; i++)
        {
            if (!dictX.ContainsKey(conn[i].x))
                dictX.Add(conn[i].x, 1);
            else dictX[conn[i].x]++;

            if (!dictY.ContainsKey(conn[i].y))
                dictY.Add(conn[i].y, 1);
            else dictY[conn[i].y]++;
        }

        if (dictX.ContainsValue(3) && dictY.ContainsValue(3))
            return true;
        else return false;

如果 3x3 数组包含一列 3 个 1 + 一行 3 个 1,则此函数返回 true。

不过,除了简单的破坏之外,我还想加一个特殊的加成,激活时会爆炸——这现在不那么重要了。我希望在这些线和一列 3 条线的交汇处形成这个奖金。那是:

2 : 1 1 1
1 : 1 0 0
0 :1 0 0
__ 0_1_2 _

奖金应出现在坐标 (0,2) 中 - 在交叉点处。

所以,我不明白如何找到这个交叉路口。为了不毫无根据和“没有自己的意识形态”,我可以说有一个想法来考虑那个(X,Y)的交集,在
(X,1) == 1 && (X, 2) == 1 && (X, 3) == 1... && (1, Y) == 1 && (2, y) == 1 && (3, Y) == 1...

但我不知道如何确切地实施它。我将添加我将列表提供给我指定的函数的输入。我用递归填充它。它存储了与我开始查看的与它直接接触或通过直接接触的那些间接接触的块相同颜色的所有块的位置;那些与那些直接接触的人接触的人,等等。简而言之,对于这样的数组:

1 1 0 0
0 1 0 1
0 1 0 0
1 1 0 0

conn = { (0,0), (0,3), (1,0), (1,1), (1,2), (1,3) } 如果从左下角开始搜索。



更新: conn 数组不必是 3x3。例如,它可以是这样的:

1 0 0 0
1 0 1 1
1 1 1 0

在这种情况下,必须再次删除字母 L,以便我们得到:

* 0 0 0
* 0 1 1
* * * 0

* 标记那些已被删除的块,因为它们组成了字母 L。

c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Yaroslav
    2022-01-06T05:32:41Z2022-01-06T05:32:41Z

    将每个可能的选项描述为一个单独的选项既困难又毫无意义。

    找到所有 3+ 行!通过水平和垂直梳理整个阵列非常简单。您将找到的组写入对象Figure。

    我们得到List<Figure> Figures,它可以相交。我们将每个与每个进行比较,如果它们相交,我们将两个中的一个新图形写入一个数组,并在创建它的那些中List<Figure> CombineFigures留下指向这个新图形的链接( )。Contains

    public enum TileType { Red, Green, Blue };
    
    public class Figure {
        public TileType Type;
        public List<Vector2Int> Tiles;
        public Figure Contains;
    
        public Figure (TileType type) {
            Type = type;
        }
    
        public Figure (Figure figureA, Figure figureB) {
            Type = figureA.Type;
            Tiles.AddRange(figureA.Tiles);
            Tiles.AddRange(figureB.Tiles);
            Tiles = Tiles.Distinct();
            figureA.Contains = this;
            figureB.Contains = this;
        }
    
        public void Add (Figure figure) {
            Tiles.AddRange(figure.Tiles);
            Tiles = Tiles.Distinct();
            figure.Contains = this;
        }
    
        public bool Cross (Figure figure) {
            for (int i = 0; i < Tiles.Count; i++)
                for (int j = 0; j < figure.Tiles.Count; j++)
                    if (Tiles[i] == figure.Tiles[j])
                        return true;
            return false;
        }
    }
    

    for (int i = 0; i < Figures.Count-1; i++)
        for (int j = i+1; j < Figures.Count; j++)
            if (Figures[i].Type == Figures[j].Type && Figures[i].Cross(Figures[j]))
                if (Figures[i].Contains == null && Figures[j].Contains == null)
                    CombineFigures.Add(new Figure(Figures[i], Figures[j]));
                else if (Figures[i].Contains != Figures[j].Contains) {
                    if (Figures[i].Contains != null)
                        Figures[i].Contains.Add(Figures[j]);
                    else
                        Figures[j].Contains.Add(Figures[i]);
                }
    

    结果,结果将是 all CombineFiguresand allFigures没有组合 ( Contains == null)。

    一切都适用于任何组合,即使这样

    X X X . .
    . X . . .
    X X X X X
    . X . . .
    
    • 4
  2. Best Answer
    Sergey Skvortsov
    2022-01-06T03:30:03Z2022-01-06T03:30:03Z

    额头的解决方案之一。也许还有更优雅的方式。

    1. 我们写了一个小扩展来检查我们的conn搜索是否包含Vector2Int
    static class ExtendOfVector2IntArray
    {
        public static bool Contains(this Vector2Int[] array, Vector2Int value)
        {
            foreach (var currentVector in array)
            {
                if (currentVector == value)
                {
                    return true;
                }
            }
            // optimize: преобразование данных в настоящую матрицу ускорит эту операцию
            return false;
        }
    }
    
    1. 我们制定了一种查找水平匹配的方法:
       private List<Vector2Int> GetRow(Vector2Int[] conn, Vector2Int startFrom)
        {
            List<Vector2Int> result = new List<Vector2Int>();
    
            const int maxPointer = 3; //количевство рядов
            int currentPointer = startFrom.x;
            for (int i = currentPointer+1; i < maxPointer; i++) //+1 что бы не добавлять себя же
            {
                if (conn.Contains(new Vector2Int(i, startFrom.y)))
                {
                    result.Add(new Vector2Int(i, startFrom.y)); // todo: два одинаковых new не нужны
                }
                else
                {
                    return result;
                }
            }
    
            return result;
        }
    
    
    1. 我们对垂直方向做类似的方法
        private List<Vector2Int> GetСolumn(Vector2Int[] conn, Vector2Int startFrom)
        {
            List<Vector2Int> result = new List<Vector2Int>();
    
            const int maxPointer = 3; //количевство столбцов
            int currentPointer = startFrom.y;
            for (int i = currentPointer+1; i < maxPointer; i++)
            {
                if (conn.Contains(new Vector2Int(startFrom.x, i)))
                {
                    result.Add(new Vector2Int(startFrom.x, i)); // todo: два одинаковых new не нужны
                }
                else
                {
                    // или ещё проверить клетки сверху?
                    return result;
                }
            }
    
            return result;
        }
    
    1. 我们创建了一种方法来开始搜索特定点的图形 //conn - 以一种颜色绘制的单元格的坐标
       private Vector2Int[] findFigure(Vector2Int[] conn, Vector2Int checkIt)
        {
            bool isFigure = false;
            List<Vector2Int> result = new List<Vector2Int>();
            result.Add(checkIt);
    
            List<Vector2Int> row = GetRow(conn,checkIt);
    
            if (row.Count > 1) //3 в строке
            {
                isFigure = true;
            }
    
            result.AddRange(row);
    
            List<List<Vector2Int>> columns = new List<List<Vector2Int>>();
    
            foreach (var currentPointer in result)
            {
                columns.Add(GetСolumn(conn,currentPointer));
            }
    
            foreach (var currentColumn in columns)
            {
                if (currentColumn.Count > 1) // 3 в ряду
                {
                    isFigure = true;
                }
    
                result.AddRange(currentColumn);
            }
            // todo: возможно нужна рекурсия для ловли совсем сложных фигур типа буквы Ш
    
            if (isFigure)
            {
                return result.ToArray();
            }
            else
            {
                return null; //или не null, а (bool isFigure, Vector2Int[] coords) , что бы можно было вычеркнуть из поиска 
            }
        }
    
    1. 我们制作了一个辅助方法来查找特定点的邻居:
       /// <summary>
        /// Возвращает соседей точки point в массиве figure
        /// </summary>
        /// <param name="figure"></param>
        /// <param name="point"></param>
        private Vector2Int[] GetNeighbors(Vector2Int[] figure, Vector2Int point)
        {
            //todo: если мы точно знаем, что figure как-то отсортирован, то этим можно пользоваться
            List<Vector2Int> result = new List<Vector2Int>(4); //4 - максимальное кол-во соседей
            foreach (var currentPoint in figure)
            {
                if (currentPoint.x == point.x+1 && currentPoint.y == point.y) //сосед справа
                {
                    result.Add(currentPoint);
                }
                if (currentPoint.x == point.x-1 && currentPoint.y == point.y) //сосед слева
                {
                    result.Add(currentPoint);
                }
                if (currentPoint.x == point.x && currentPoint.y == point.y+1) //сосед сверху
                {
                    result.Add(currentPoint);
                }
                if (currentPoint.x == point.x && currentPoint.y == point.y-1) //сосед снизу
                {
                    result.Add(currentPoint);
                }
            }
    
            return result.ToArray();
        }
    
    1. 制作一种在图形中查找交点的方法
        private Vector2Int[] GetСrossings(Vector2Int[] figure)
        {
            //todo: если фигура меньше 5 элементов сразу возвращаем пустышку        
            List<Vector2Int> result = new List<Vector2Int>();
            foreach (var currentPoint in figure)
            {
                var neighbors = GetNeighbors(figure, currentPoint);
    
                if (neighbors.Length > 2) // 3 или 4 соседа, по любому пересечение
                {
                    result.Add(currentPoint);
                    continue;
                }
    
                // если не интересны пересечения типа буквы Г, то continue при одном соседе
                bool oneRow = true; //все соседи на одной строке
                bool oneСolumn = true; //все соседи на одном столбце
    
                for (var i = 0; i < neighbors.Length-1; i++)
                {
                    if (neighbors[i].x != neighbors[i + 1].x)
                    {
                        oneRow = false;
                    }
    
                    if (neighbors[i].y != neighbors[i + 1].y)
                    {
                        oneСolumn = false;
                    }
                }
    
                if (!oneRow && !oneСolumn)
                {
                    result.Add(currentPoint);
                }
            }
    
            return result.ToArray();
        }
    

    通过稍微扩展比较方法,您可以教这个东西不仅可以使用二进制数组,还可以使用 int 数组,以便一次搜索整个字段上的数字。

    • 3

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5