コード例 #1
0
        // [SC] 1. Create lists of tiles where each list is a group of tiles with the same color or shape.
        // [SC] 2. For each group of tiles, create lists of tile sequences where each list contains a sequence of tiles in a unique order.
        // [SC] 3. For each tile sequence, create a combination of unique board positions.
        public CandidateTilePos calculateMoves(bool considerColor, bool considerShape, bool suboptiomal)
        {
            List <CandidateTileSeq> candTileSeqList = new List <CandidateTileSeq>(); // [TODO]

            //////////////////////////////////////////////////////////////////////////////
            // [2016.12.08] new code
            List <List <TileZeroTile> > colorTileLists = new List <List <TileZeroTile> >(); // [SC] each list contains player's tiles of the same color
            List <List <TileZeroTile> > shapeTileLists = new List <List <TileZeroTile> >(); // [SC] each list contains player's tiles of the same shape

            for (int index = 0; index < Cfg.MAX_VAL_INDEX; index++)
            {
                colorTileLists.Add(new List <TileZeroTile>());
                shapeTileLists.Add(new List <TileZeroTile>());
            }

            foreach (TileZeroTile tile in playerTiles)
            {
                colorTileLists[tile.getColorIndex()].Add(tile);
                shapeTileLists[tile.getShapeIndex()].Add(tile);
            }

            colorTileLists.RemoveAll(p => p.Count == 0);                    // [SC] remove empty tile combos
            shapeTileLists.RemoveAll(p => p.Count == 0);                    // [SC] remove empty tile combos

            colorTileLists = colorTileLists.OrderBy(p => p.Count).ToList(); // [SC] order by size of tile combos
            shapeTileLists = shapeTileLists.OrderBy(p => p.Count).ToList(); // [SC] order by size of tile combos

            if (considerColor)
            {
                // [SC] remove all color tile combos that are subsets of another color or shape combo
                for (int indexOne = 0; indexOne < colorTileLists.Count; indexOne++)
                {
                    List <TileZeroTile> tileComboOne = colorTileLists[indexOne];

                    for (int indexTwo = indexOne + 1; indexTwo < colorTileLists.Count; indexTwo++)
                    {
                        List <TileZeroTile> tileComboTwo = colorTileLists[indexTwo];

                        if (tileComboOne.All(p => tileComboTwo.Contains(p)))
                        {
                            tileComboOne.Clear();
                            continue;
                        }
                    }

                    if (tileComboOne.Count == 0)
                    {
                        continue;
                    }

                    if (considerShape)
                    {
                        for (int indexTwo = 0; indexTwo < shapeTileLists.Count; indexTwo++)
                        {
                            List <TileZeroTile> tileComboTwo = shapeTileLists[indexTwo];

                            // [SC] true if combo one is a subset of combo two
                            if (tileComboOne.Count <= tileComboTwo.Count && tileComboOne.All(p => tileComboTwo.Contains(p)))
                            {
                                tileComboOne.Clear();
                                continue;
                            }
                        }
                    }
                }
                colorTileLists.RemoveAll(p => p.Count == 0); // [SC] remove empty tile combos
            }

            if (considerShape)
            {
                // [SC] remove all shape tile combos that are subsets of another color or shape combo
                for (int indexOne = 0; indexOne < shapeTileLists.Count; indexOne++)
                {
                    List <TileZeroTile> tileComboOne = shapeTileLists[indexOne];

                    for (int indexTwo = indexOne + 1; indexTwo < shapeTileLists.Count; indexTwo++)
                    {
                        List <TileZeroTile> tileComboTwo = shapeTileLists[indexTwo];

                        if (tileComboOne.All(p => tileComboTwo.Contains(p)))
                        {
                            tileComboOne.Clear();
                            continue;
                        }
                    }

                    if (tileComboOne.Count == 0)
                    {
                        continue;
                    }

                    if (considerColor)
                    {
                        for (int indexTwo = 0; indexTwo < colorTileLists.Count; indexTwo++)
                        {
                            List <TileZeroTile> tileComboTwo = colorTileLists[indexTwo];

                            // [SC] true if combo one is a subset of combo two
                            if (tileComboOne.Count <= tileComboTwo.Count && tileComboOne.All(p => tileComboTwo.Contains(p)))
                            {
                                tileComboOne.Clear();
                                continue;
                            }
                        }
                    }
                }
                shapeTileLists.RemoveAll(p => p.Count == 0); // [SC] remove empty tile combos
            }
            //
            //////////////////////////////////////////////////////////////////////////////

            //////////////////////////////////////////////////////////////////////////////
            // [2016.12.08] new code
            if (considerColor)
            {
                // [SC] iterate through list of tiles with one particular color
                foreach (List <TileZeroTile> tileList in colorTileLists)
                {
                    int colorIndex = tileList[0].getColorIndex();

                    TreeNode rootNode = new TreeNode(null);
                    for (int tileIndex = 0; tileIndex < tileList.Count; tileIndex++)
                    {
                        tileListPermAddChildNodes(tileList, tileIndex, rootNode);
                    }

                    tileListPermTraverseTreePaths(rootNode, new List <TileZeroTile>(), colorIndex, Cfg.COLOR_ATTR, candTileSeqList);
                }
            }

            if (considerShape)
            {
                // [SC] iterate through list of tiles with one particular shape
                foreach (List <TileZeroTile> tileList in shapeTileLists)
                {
                    int shapeIndex = tileList[0].getShapeIndex();

                    TreeNode rootNode = new TreeNode(null);
                    for (int tileIndex = 0; tileIndex < tileList.Count; tileIndex++)
                    {
                        tileListPermAddChildNodes(tileList, tileIndex, rootNode);
                    }

                    tileListPermTraverseTreePaths(rootNode, new List <TileZeroTile>(), shapeIndex, Cfg.SHAPE_ATTR, candTileSeqList);
                }
            }
            //
            //////////////////////////////////////////////////////////////////////////////

            //////////////////////////////////////////////////////////////////////////////
            // [2016.12.08] new code
            int maxCTS = 10;

            if (candTileSeqList.Count > maxCTS)
            {
                candTileSeqList = candTileSeqList.OrderByDescending(p => p.getTileCount()).ToList();
                candTileSeqList.RemoveRange(maxCTS, candTileSeqList.Count - maxCTS);
            }
            //
            //////////////////////////////////////////////////////////////////////////////

            VirtualBoard virtualBoard = game.getVirtualBoard();

            TileZeroTile[,] tileArray = virtualBoard.getBoardCopy();

            List <CandidateTilePos> chosenPosComboList   = new List <CandidateTilePos>();
            List <CandidateTilePos> maxScorePosComboList = new List <CandidateTilePos>();

            foreach (CandidateTileSeq candTileSeq in candTileSeqList)
            {
                TreeNode rootNode = new TreeNode(null);

                boardPosPermAddChildNodes(candTileSeq, 0, rootNode, tileArray, virtualBoard);
                if (suboptiomal)
                {
                    boardPosPermTraverseTreePaths(rootNode, new List <AbstractPos>(), candTileSeq, 0, chosenPosComboList, maxScorePosComboList);
                }
                else
                {
                    boardPosPermTraverseTreePaths(rootNode, new List <AbstractPos>(), candTileSeq, 0, chosenPosComboList);
                }
            }

            return(chosenPosComboList.getRandomElement());
        }