Esempio n. 1
0
    /**
     * #function SingleBot::GetSingleMove |
     * @author JavaComSci |
     * @desc need desc here TODO |
     * @header public override List<...> GetSingleMove(Board, List<Block>, bool) |
     * @param int[][] board : current enviornment |
     * @param List<Block> blocks : contains the list of all the blocks to try to fit in this location |
     * @returns List<...> bestPiecePlacementOfCurrentBlock : contains the list of the indicies
     * of where the piece would be on the board |
     */
    public List <Tuple <int, int> > GetSingleMove1(Board board, List <List <Block> > allBotBlocks, bool allRotations = false)
    {
        List <Block> blocks = allBotBlocks[0];

        Console.WriteLine("BOARD");
        botInfoPrinter.PrintMultiDimArr(board.board);
        Console.WriteLine("RECIEVED PIECE");
        botInfoPrinter.PrintJaggedArr(blocks[0].data);

        // get the max height of each column of the baord
        board.FindMaxHeights();

        // has the information about all the compatible pieces for a given block
        Dictionary <Block, List <Tuple <int, List <Tuple <int, int> >, int, int> > > allBlocksPossible = new Dictionary <Block, List <Tuple <int, List <Tuple <int, int> >, int, int> > >();

        int blockCount = 0;

        if (blocks.Count >= 1)
        {
            shapeColor = blocks[0].color;
        }

        // test out each of the pieces
        foreach (Block block in blocks)
        {
            // check to make sure that each block is valid
            bool blockValid = block.CheckValidity();

            // block is invalid
            if (!blockValid)
            {
                throw new Exception("Shape formation is incorrect");
            }

            // compatible pieces for a single block
            // has all the positions compatible for this piece with the rotation, location on board, area covered, and number of lines that can be cleared
            List <Tuple <int, List <Tuple <int, int> >, int, int> > compatiblePieces = new List <Tuple <int, List <Tuple <int, int> >, int, int> >();

            // get the fit of the board with the area and whether a piece can clear a line
            compatiblePieces.AddRange(getFit(board, block, 1));
            block.data = block.RotateMatrix();
            compatiblePieces.AddRange(getFit(board, block, 2));
            block.data = block.RotateMatrix();
            compatiblePieces.AddRange(getFit(board, block, 3));
            block.data = block.RotateMatrix();
            compatiblePieces.AddRange(getFit(board, block, 4));

            if (allRotations)
            {
                block.data = block.RotateMatrix();
            }

            // compatible pieces has all the pieces that are compatible with the board and has the information about the rotation, location on board, area covered, and if that piece can clear a line
            compatiblePieces.Sort((x, y) => {
                // sort by whether a line has been cleared and puts those first if there is
                int result = y.Item4.CompareTo(x.Item4);
                // sort by the area covered
                return(result == 0 ? y.Item3.CompareTo(x.Item3) : result);
            });

            // the current piece cannot even be placed so must return null
            if (compatiblePieces.Count == 0 && blockCount == 0)
            {
                return(null);
            }
            blockCount++;

            allBlocksPossible[block] = compatiblePieces;
        }

        // get the best piece of the block that is the first one
        Tuple <int, List <Tuple <int, int> >, int, int> bestPieceOfCurrentBlock = allBlocksPossible[blocks[0]][0];

        // placement of this block that is the best of the current block
        List <Tuple <int, int> > bestPiecePlacementOfCurrentBlock = bestPieceOfCurrentBlock.Item2;

        // if the best current piece doesnt clear any lines, need to find one that does clear lines
        if (bestPieceOfCurrentBlock.Item4 == 0 && blocks.Count > 1)
        {
            // does not clear any lines so need to look for another candidate and choose the next best spot for this block

            // find the next piece that clears lines
            Tuple <int, List <Tuple <int, int> >, int, int> bestPieceOfNextBlock = allBlocksPossible[blocks[1]][0];

            // next next piece that clears lines
            Tuple <int, List <Tuple <int, int> >, int, int> bestPieceOfNextNextBlock = allBlocksPossible.Count > 2 ? allBlocksPossible[blocks[2]][0] : null;
            // Console.WriteLine("NEXT PIECE " + bestPieceOfNextNextBlock.Item4);

            // the next piece is able to clear lines
            if (bestPieceOfNextBlock.Item4 > 0)
            {
                // Console.WriteLine("I AM HEREHEHEH LOOKING AT THE NEXT PIECE!\n");
                // create a new copy of the board so that it can run through the steps for clearing lines again
                int [,] copiedBoard = board.CopyBoard(board.board);

                // add the pieces to this board to where it has the new information
                copiedBoard = board.FillBoardWithPieceConsidered(copiedBoard, bestPieceOfNextBlock.Item2);

                // check to see if there is anything the current piece can place so do another search with the new info
                List <Tuple <int, List <Tuple <int, int> >, int, int> > compatiblePiecesForCurrentPieceAfterPiece1 = new List <Tuple <int, List <Tuple <int, int> >, int, int> >();

                // set up new board
                Board cBoard = new Board(board.board.GetLength(0), board.board.GetLength(1));
                cBoard.board = copiedBoard;
                cBoard.FindMaxHeights();

                // get the fit of the board with the area and whether a piece can clear a line
                compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 1));
                blocks[0].data = blocks[0].RotateMatrix();
                compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 2));
                blocks[0].data = blocks[0].RotateMatrix();
                compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 3));
                blocks[0].data = blocks[0].RotateMatrix();
                compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 4));

                if (allRotations)
                {
                    blocks[0].data = blocks[0].RotateMatrix();
                }

                // compatible pieces has all the pieces that are compatible with the board and has the information about the rotation, location on board, area covered, and if that piece can clear a line
                compatiblePiecesForCurrentPieceAfterPiece1.Sort((x, y) => {
                    // sort by whether a line has been cleared and puts those first if there is
                    int result = y.Item4.CompareTo(x.Item4);
                    // sort by the area covered
                    return(result == 0 ? y.Item3.CompareTo(x.Item3) : result);
                });

                // placement of this block that is the best of the current block
                bestPiecePlacementOfCurrentBlock = compatiblePiecesForCurrentPieceAfterPiece1[0].Item2;
            }
            else if (bestPieceOfNextNextBlock != null && bestPieceOfNextNextBlock.Item4 > 0)
            {
                // Console.WriteLine("I AM A NEXT NEXT SHAPE\n\n\n\n");

                // check 2 shapes from the current shape

                // create a new copy of the board so that it can run through the steps for clearing lines again
                int [,] copiedBoard = board.CopyBoard(board.board);

                // add the pieces to this board to where it has the new information
                copiedBoard = board.FillBoardWithPieceConsidered(copiedBoard, bestPieceOfNextNextBlock.Item2);

                // check to see if there is anything the current piece can place so do another search with the new info
                List <Tuple <int, List <Tuple <int, int> >, int, int> > compatiblePiecesForCurrentPieceAfterPiece2 = new List <Tuple <int, List <Tuple <int, int> >, int, int> >();

                // set up new board
                Board cBoard = new Board(board.board.GetLength(0), board.board.GetLength(1));
                cBoard.board = copiedBoard;
                cBoard.FindMaxHeights();

                // get the fit of the board with the area and whether a piece can clear a line
                compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 1));
                blocks[0].data = blocks[0].RotateMatrix();
                compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 2));
                blocks[0].data = blocks[0].RotateMatrix();
                compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 3));
                blocks[0].data = blocks[0].RotateMatrix();
                compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 4));

                if (allRotations)
                {
                    blocks[0].data = blocks[0].RotateMatrix();
                }

                // compatible pieces has all the pieces that are compatible with the board and has the information about the rotation, location on board, area covered, and if that piece can clear a line
                compatiblePiecesForCurrentPieceAfterPiece2.Sort((x, y) => {
                    // sort by whether a line has been cleared and puts those first if there is
                    int result = y.Item4.CompareTo(x.Item4);
                    // sort by the area covered
                    return(result == 0 ? y.Item3.CompareTo(x.Item3) : result);
                });

                // placement of this block that is the best of the current block
                bestPiecePlacementOfCurrentBlock = compatiblePiecesForCurrentPieceAfterPiece2[0].Item2;
            }
        }

        // Console.WriteLine("BEST PIECE FOR BOARD");
        // botInfoPrinter.PrintPositions(bestPiecePlacementOfCurrentBlock);
        Console.WriteLine("BOARD WITH PIECE");
        botInfoPrinter.PrintBoardWithPiece(board.board, bestPiecePlacementOfCurrentBlock);

        return(bestPiecePlacementOfCurrentBlock);
    }