Package generator

Source Code of generator.BlocksGenerator

package generator;

import java.util.Random;

import engine.Board;
import engine.Scheme;

/**
* Class is used to generate blocks on the board.
*/
public final class BlocksGenerator {
 
  private static final int NUM_COMBINATIONS = 5;
 
  private static final int COMBINATION_2H = 0;
  private static final int COMBINATION_2V = 1;
  private static final int COMBINATION_3LV = 2;
  private static final int COMBINATION_3RV = 3;
  private static final int COMBINATION_3H = 4;
 
  private static Random rand = new Random();
 
  /**
   * Generate a one configuration of new blocks and moves, which execution
   * lead to the given board. The configuration of blocks is random.
   *
   * @param destinationBoard
   * @return the scheme with generated blocks
   */
  public static Scheme generateBlocks(Board destinationBoard) {
    Scheme s = new Scheme(new Board(destinationBoard));
    int mix = rand.nextInt(NUM_COMBINATIONS);
    mix = COMBINATION_2H;
    generateBlock(mix, s);
    return s;
  }
 
  /*
   * Generates a one configuration of new blocks and moves, which execution
   * leads to the given board. The configuration of the blocks is given. 
   *
   * @param mix - the configuration of the new blocks
   * @param s - the given scheme
   */
  private static void generateBlock(int mix, Scheme s) {
    int width = s.start.width, height = s.start.height;
 
    int[][] goodPositions = new int[width][height];
    int total = 0;
    for (int i=0; i<width; i++)
      for (int j=0; j<height; j++)
        if ((goodPositions[i][j] = goodPosition(mix,i,j, s)) >= 0total++;
      
    if (total > 0) {
      int n = rand.nextInt(total);
      for (int i=0; i<width; i++)
        for (int j=0; j<height; j++)
          if (goodPositions[i][j] >= 0) {
            if (n==0) { addMix(mix,i,j,goodPositions[i][j],s); i = width; break; }
            n--;
          }
    }
  }
 
  /*
   * Adds a new blocks of the given configuration and color in fixed fields.
   *
   * @param mix - the configuration of the blocks
   * @param x - coordinate of the field
   * @param y - coordinate of the field
   * @param color - the color of the blocks
   * @param s - scheme, it is returned with new blocks
   */
  private static void addMix(int mix, int x, int y, int color, Scheme s) {
    Board board = s.start;
   
    switch (mix) {
    case COMBINATION_2H:
      insertBlock(x, y, color, board);
      insertBlock(x+1, y, color, board);
      MixGenerator.moveBlock(x,y,true,s);
      MixGenerator.moveBlock(x+1,y,true,s);
      break;   
    case COMBINATION_2V:
      insertBlock(x, y, color, board);
      insertBlock(x, y-1, color, board)
      MixGenerator.moveBlock(x, y-1, true, s);
      break;     
    case COMBINATION_3LV:
      insertBlock(x, y, color, board);
      insertBlock(x, y-1, color, board);
      insertBlock(x-1, y-1, color, board);
      MixGenerator.moveBlock(x, y-1, true, s);
      break;     
    case COMBINATION_3RV:      
      insertBlock(x, y, color, board);
      insertBlock(x, y-1, color, board);
      insertBlock(x+1, y-1, color, board);
      MixGenerator.moveBlock(x, y-1, true, s);
      break;
    case COMBINATION_3H:
      insertBlock(x, y, color, board);
      insertBlock(x+1, y, color, board);
      insertBlock(x+2, y, color, board);
      MixGenerator.moveBlock(x+1, y, true, s);
      break;
    default:
      assert false;
      break;
    }
  }

  /*
   * Checks if the blocks of given configuration can be inserted in the fixed
   * fields and return possible color of the blocks.
   *
   * @param mix - the configuration of blocks
   * @param x - coordinate of the field
   * @param y - coordinate of the field
   * @param s - scheme
   * @return the color of blocks which can be add in the fixed fields or -1 if
   * the blocks can't be inserted.
   */
  private static int goodPosition(int mix, int x, int y, Scheme s) {
    Board board = s.start; int color=-1;
   
    switch (mix) {
    case COMBINATION_2H: {      
      if (board.getType(x, y)   == Board.CONCRETE) color = board.getColor(x, y);
      if (board.getType(x+1, y) == Board.CONCRETE)
        if (color==-1 || board.getColor(x+1, y)==color) color = board.getColor(x+1, y);
        else return -1;
      if (color==-1) color = rand.nextInt(Board.NUM_COLORS);
     
      boolean canMove = false;
      boolean block1 = canInsertBlock(x,y,color, true, board, new int[]{0,0,0,0});
      if (block1) insertBlock(x, y, color, board);
      boolean block2 = canInsertBlock(x+1,y,color, true, board, new int[]{0,0,0,1});
      if (block2) insertBlock(x+1, y, color, board);
      if (block1 && block2)
        canMove = MixGenerator.canMoveBlock(x, y, true, s) ||
          MixGenerator.canMoveBlock(x+1, y, true, s);
      if (block2) deleteBlock(x+1,y, board);
      if (block1) deleteBlock(x,y, board);
     
      if (canMove) return color;
      else return -1;
    }
   
    case COMBINATION_2V: {
      if (board.getType(x, y)   == Board.CONCRETE) color = board.getColor(x, y);
      if (board.getType(x, y-1) == Board.CONCRETE)
        if (color==-1 || board.getColor(x, y-1)==color) color = board.getColor(x, y-1);
        else return -1;
      if (color==-1) color = rand.nextInt(Board.NUM_COLORS);
     
      boolean canMove = false;
      boolean block1 = canInsertBlock(x,y,color, false, board, new int[]{0,0,0,0});
      if (block1) insertBlock(x, y, color, board);
      boolean block2 = canInsertBlock(x,y-1,color, false, board, new int[]{0,0,1,0});
      if (block2) insertBlock(x, y-1, color, board);
      if (block1 && block2)
        canMove = MixGenerator.canMoveBlock(x, y-1, true, s);
      if (block2) deleteBlock(x,y-1, board);
      if (block1) deleteBlock(x,y, board);
     
      if (canMove) return color;
      else return -1;
    }
   
    case COMBINATION_3LV:
      if (board.getType(x, y)   == Board.CONCRETE) color = board.getColor(x, y);
      if (board.getType(x, y-1) == Board.CONCRETE)
        if (color==-1 || board.getColor(x, y-1)==color) color = board.getColor(x, y-1);
        else return -1;
      if (board.getType(x-1, y-1) == Board.CONCRETE)
        if (color==-1 || board.getColor(x-1, y-1)==color) color = board.getColor(x-1, y-1);
        else return -1;
      if (color==-1) color = rand.nextInt(Board.NUM_COLORS);
     
      boolean canMove = false;
      boolean block1 = canInsertBlock(x,y,color, false, board, new int[]{0,0,0,0});
      if (block1) insertBlock(x, y, color, board);
      boolean block2 = canInsertBlock(x,y-1,color, false, board, new int[]{0,0,1,0});
      if (block2) insertBlock(x, y-1, color, board);
      boolean block3 = canInsertBlock(x-1,y-1,color, true, board, new int[]{0,1,0,0});
      if (block3) insertBlock(x-1, y-1, color, board);
      if (block1 && block2 && block3)
        canMove = MixGenerator.canMoveBlock(x, y-1, true, s);
      if (block3) deleteBlock(x-1,y-1, board);
      if (block2) deleteBlock(x,y-1, board);
      if (block1) deleteBlock(x,y, board);
     
      if (canMove) return color;
      return -1;
    }
   
    case COMBINATION_3RV: {    
      if (board.getType(x, y)   == Board.CONCRETE) color = board.getColor(x, y);
      if (board.getType(x, y-1) == Board.CONCRETE)
        if (color==-1 || board.getColor(x, y-1)==color) color = board.getColor(x, y-1);
        else return -1;
      if (board.getType(x+1, y-1) == Board.CONCRETE)
        if (color==-1 || board.getColor(x+1, y-1)==color) color = board.getColor(x+1, y-1);
        else return -1;
      if (color==-1) color = rand.nextInt(Board.NUM_COLORS);
    
      boolean canMove = false;
      boolean block1 = canInsertBlock(x,y,color, false, board, new int[]{0,0,0,0});
      if (block1) insertBlock(x, y, color, board);
      boolean block2 = canInsertBlock(x,y-1,color, false, board, new int[]{0,0,1,0});
      if (block2) insertBlock(x, y-1, color, board);
      boolean block3 = canInsertBlock(x+1,y-1,color, true, board, new int[]{0,0,0,1});
      if (block3) insertBlock(x+1, y-1, color, board);
      if (block1 && block2 && block3)
        canMove = MixGenerator.canMoveBlock(x, y-1, true, s);
      if (block3) deleteBlock(x+1,y-1, board);
      if (block2) deleteBlock(x,y-1, board);
      if (block1) deleteBlock(x,y, board);
     
      if (canMove) return color;
      else return -1;
    }
   
    case COMBINATION_3H: {  
      if (board.getType(x, y)   == Board.CONCRETE) color = board.getColor(x, y);
      if (board.getType(x+1, y) == Board.CONCRETE)
        if (color==-1 || board.getColor(x+1, y)==color) color = board.getColor(x+1, y);
        else return -1;
      if (board.getType(x+2, y) == Board.CONCRETE)
        if (color==-1 || board.getColor(x+2, y)==color) color = board.getColor(x+2, y);
        else return -1;
      if (color==-1) color = rand.nextInt(Board.NUM_COLORS);
   
     
      boolean canMove = false;
      boolean block1 = canInsertBlock(x,y,color, true, board, new int[]{0,0,0,0});
      if (block1) insertBlock(x, y, color, board);
      boolean block2 = canInsertBlock(x+1,y,color, false, board, new int[]{0,0,0,1});
      if (block2) insertBlock(x+1, y, color, board);
      boolean block3 = canInsertBlock(x+2,y,color, true, board, new int[]{0,0,0,1});
      if (block3) insertBlock(x+2, y, color, board);
      if (block1 && block2 && block3)
        canMove = MixGenerator.canMoveBlock(x+1, y, true, s);
      if (block3) deleteBlock(x+2,y, board);
      if (block2) deleteBlock(x+1,y, board);
      if (block1) deleteBlock(x,y, board);

      if (canMove) return color;
      else return -1;
    }   
    }
   
    assert false;
    return -1;
  }


  /*
   * Removes block from given field.
   *
   * @param x - coordinate of the field
   * @param y - coordinate of the field
   * @param board
   */
  private static void deleteBlock(int x, int y, Board board) {
    int color = board.getColor(x, y);
    if (board.getType(x, y) == Board.BLOCK_CONCRETE)
      board.setElement(x, y, Board.CONCRETE, color);
    else {
      board.setElement(x, y, Board.EMPTY);
      int h = y;
      while (board.isBlock(x,h-1)) {
        if (board.getType(x, h-1) == Board.BLOCK_BALLOON) {
          int t = h-1;
          while (board.getType(x, t-1) == Board.BLOCK_BALLOON) t--;
          if (!board.isBlock(x, t-1)) break;
        }
        board.setElement(x, h, board.getType(x, h-1), board.getColor(x, h-1));
        h--;
      }
      board.setElement(x, h, Board.EMPTY);
    }
  }

  /*
   * Inserts a block in the given field.
   *
   * @param x - coordinate of the field
   * @param y - coordinate of the field
   * @param color - color of the block
   * @param board
   */
  private static void insertBlock(int x, int y, int color, Board board) {
    if (board.isEmpty(x, y)) board.setElement(x, y, Board.BLOCK_SPHERE, (byte) color);
    else if (board.getType(x, y) == Board.CONCRETE)
      board.setElement(x, y, Board.BLOCK_CONCRETE, (byte) color);
    else {
      int h = y;
      while (h>0 && board.isBlock(x, h-1)) h--;
      while (h <= y) {
        board.setElement(x, h-1, board.getType(x, h),board.getColor(x, h));
        h++;
      }    
      board.setElement(x, y, Board.BLOCK_SPHERE, (byte) color);
    }
  }
 
 
  /*
   * Checks if a block can be inserted in the given field.
   *
   * @param x - coordinate of the field
   * @param y - coordinate of the field
   * @param color - color of the block
   * @param canBeBlock - true if block from the field can be raised
   * @param board
   * @param tab - define where blocks of the same color can be
   * @return true if the block can be inserted
   */
  private static boolean canInsertBlock(int x, int y, int color, boolean canBeBlock,
      Board board, int[] tab) {
   
    if (!(board.isEmpty(x, y) || board.isBlock(x, y) && canBeBlock
        || board.getType(x, y) == Board.CONCRETE)) return false;

    if (board.getType(x, y) == Board.CONCRETE && color != board.getColor(x, y) ||
        board.isBlock(x, y) && board.getColor(x, y) == color)
      return false;
       
    if (tab[2] == 0 && board.isBlock(x, y+1) && board.getColor(x, y+1) == color ||
        !(board.isSolid(x, y+1) || board.isBlock(x, y+1) ||
            board.getType(x, y+1) == Board.CONCRETE)) return false;

    if (tab[3] == 0 && board.isBlock(x-1, y) && board.getColor(x-1, y) == color ||
        tab[1] == 0 && board.isBlock(x+1, y) && board.getColor(x+1, y) == color ||
        tab[0] == 0 && board.isBlock(x, y-1) && board.getColor(x, y-1) == color)
      return false;

    if (board.isBlock(x, y)) {
      int h = y;
      while (h>0 && board.isBlock(x, h-1)) h--;
      if (!board.isEmpty(x, h-1)) return false;
      while (h <= y && MixGenerator.correctMove(x, h-1, x, h, -1, -1, board, true))
        h++;       
      if (h != y+1) return false;
    }

    return true;
  }
 
 
 
}
TOP

Related Classes of generator.BlocksGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.