Arsalan Khalid
Arsalan Khalid

Reputation: 256

Tetris Shape Generation Algorithm in Java

I'm building a Tetris game in Java using some software design patterns. Basically, I created a factory algorithm that retrieves a string to figure out what type of tetris object to make when it's given a request by the main game loop, see code:

public class TVShapeFactory {

    protected TVShape tvShape = null;
    protected GameContainer gc;

    TVShapeFactory(GameContainer gc) {
        this.gc = gc;
    }

    public TVShape createShape(String shape) {
        if (shape=="TVIShape") {
            tvShape = new TVIShape(gc);
        }
        else if (shape=="TVOShape") {
            tvShape = new TVOShape(gc);
        }
        else if (shape=="TVLShape") {
            tvShape = new TVLShape(gc);
        }
        else if (shape=="TVZShape") {
            tvShape = new TVZShape(gc);
        }
        else if (shape=="TVJShape") {
            tvShape = new TVJShape(gc);
        }
        else if (shape=="TVSShape") {
            tvShape = new TVSShape(gc);
        }
        else if (shape=="TVTShape") {
            tvShape = new TVTShape(gc);
        }
        else {
            System.out.println("Error: invalid type of shape");
        }
        return tvShape;
    }
}

If you don't know what gc is, it's simply a part of Slick 2D's library and is used to work with the full game environment. Anyways, I created a few other methods to randomly generate a shape for the game (such that the main game loop receives a random shape every time, but I feel like RNG doesn't cut it, I want to make it harder. I noticed there's a famous tetris algorithm called Bastet tetris, but it didn't make sense to me. Any suggestions you guys have for making a HARD tetris shape generation algorithm? Here's my simple RNG algorithm:

public TVShape getRandomShape() {

    TVShape[] shapes = new TVShape[7];
    shapes[0] = createShape("TVIShape");
    shapes[1] = createShape("TVOShape");
    shapes[2] = createShape("TVLShape");
    shapes[3] = createShape("TVZShape");
    shapes[4] = createShape("TVJShape");
    shapes[5] = createShape("TVSShape");
    shapes[6] = createShape("TVTShape");

    int index = new Random().nextInt(shapes.length);
    return shapes[index];
}

Upvotes: 0

Views: 1315

Answers (2)

samgak
samgak

Reputation: 24427

Any suggestions you guys have for making a HARD tetris shape generation algorithm?

To make it harder, you need a way to evaluate which shapes the player needs the most and which shapes they need the least, and then bias your random number generation towards giving them the ones they don't need.

At a basic level, the 2x2 square shape and the long 4x1 shapes are the "easiest" because you can usually stack them more easily. So you could just make a random shape generator that returns them half as often as the other shapes:

public TVShape getRandomShape() {

    TVShape[] shapes = new TVShape[12];
    shapes[0] = createShape("TVIShape");
    shapes[1] = createShape("TVOShape");
    shapes[2] = createShape("TVLShape");
    shapes[3] = createShape("TVLShape");
    shapes[4] = createShape("TVZShape");
    shapes[5] = createShape("TVZShape");
    shapes[6] = createShape("TVJShape");
    shapes[7] = createShape("TVJShape");
    shapes[8] = createShape("TVSShape");
    shapes[9] = createShape("TVSShape");
    shapes[10] = createShape("TVTShape");
    shapes[11] = createShape("TVTShape");

    int index = new Random().nextInt(shapes.length);
    return shapes[index];
}

But if you want to make it really hard, you can evaluate at each step which shape is most and least helpful to the player given the current game state:

For each shape, iterate through all valid positions where it could be placed, and all possible rotations (1, 2 or 4 of them per shape), and score each possible placement based on several criteria:

  • Height of the stack at the tallest point after you place it. Negative score for each increase in height.
  • Whether the placement causes any rows to be completely filled in. Each completed row is a positive score.
  • How many holes there are in the stack (empty squares below the highest occupied square in a column). Each hole is a negative score.
  • anything else you can think of

The best possible placement score for a shape is that shape's score. Then rank the pieces according to their scores, and generate a random number. Make it so there is a high chance of getting the worst shape, a slightly lesser chance of getting the second worst shape etc.

So for e.g. you could generate a number between 0 and 27 and then choose based on that:

  • 0-6 worst shape
  • 7-12 second worst shape
  • 13-17 third worst shape
  • 18-21 fourth worst shape
  • 22-24 third best shape
  • 25-26 second best shape
  • 27 best shape

You can vary the distribution according to how hard you want to make it.

Upvotes: 1

Pallav
Pallav

Reputation: 165

Instead of "==" sign use .equals() function to compare the Strings. == is used to check whether the two strings have same reference or not. Whereas .equals() method is used to check whether the two string has same value or not. Instead of

(shape=="TVIShape")

use

(shape.equals("TVIShape")

Upvotes: 1

Related Questions