Stop objects from going out of bounds in Tetris game

338 views Asked by At

I'd like to stop my shapes from being able to move so far left or right that they go off the screen, but my outOfBounds method which I've implemented in my KeyHandler is receiving this error:

1 error found: File: .../Tetris.java [line: 46] Error: The method outOfBounds(int, int) is undefined for the type package.Tetromino

Here are my classes

import javax.swing.*; 
import java.awt.event.*; 
import java.awt.*; 


class BigBang extends JComponent implements KeyListener, ActionListener {
  Timer timer; 
  World world; 
  int score = 0;
  JLabel statusbar = new JLabel("Score: " + score);

  BigBang(int delay, World world) {
    timer = new Timer(delay, this); 
    this.world = world;
    JFrame frame = new JFrame("Tetris"); 
    frame.add(statusbar, BorderLayout.SOUTH);
    statusbar.setVisible(true);
    frame.getContentPane().add(this ); 
    frame.addKeyListener(this); 
    frame.setVisible(true); 
    frame.setSize(Tetris.COLUMNS * Block.SIZE + 27, Tetris.ROWS * Block.SIZE + 60); 
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 
  }

  public void start() {
    timer.start();  
  }
  BigBang(World world) {
    this(1000, world);  
  }
  public void paintComponent(Graphics g) {
    world.draw(g);  
  }
  public void actionPerformed(ActionEvent e) {
    world.update(); 
    if (world.hasEnded())
      timer.stop(); 
    this.repaint(); 
    score += 5;
    statusbar.setText("Score: " + score);
  }
  public void keyPressed(KeyEvent e) { 
    world.keyPressed(e); 
    this.repaint(); 
  } 
  public void keyTyped(KeyEvent e) { } 
  public void keyReleased(KeyEvent e) { } 
}

__

import java.awt.*; 

class Block {
  final static int SIZE = 20; 
  int x, y;
  Color color; 
  Block(int x, int y, Color c) {
    this.x = x;
    this.y = y;
    this.color = c; 
  }
  void outOfBounds(int left, int right)
  {
    if (this.x > right)
      this.x = right;
    else if (this.x < left)
      this.x = left;
  }
  void draw(Graphics g) {
    int xp = this.x * SIZE,
        yp = this.y * SIZE;
    g.setColor(this.color);     
    g.fillRect(xp + 85, yp, SIZE, SIZE); 
    g.setColor(Color.BLACK); 
    g.drawRect(xp + 85, yp, SIZE, SIZE); 
  }
  void move(int dx, int dy) {
    this.x += dx; 
    this.y += dy; 
  }  
  public String toString() {
    return "[" + this.x + ", " + this.y + "]"; 
  }
  void rotateCW(Point c) {
    int newX, newY;
    newX = c.x + c.y - this.y;
    newY = c.y + this.x - c.x; 
    this.x = newX; 
    this.y = newY; 
  }
  boolean equals(Block other) {
    return this.x == other.x && this.y == other.y;  
  }
  void setColor(Color c) {
    this.color = c;  
  }
}


class Point { 
  int x, y;
  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }
  void move(int dx, int dy) {
    this.x += dx; 
    this.y += dy; 
  }

  public String toString() {
    return "(" + this.x + ", " + this.y + ")";  
  }
}

__

import java.awt.*; 
import java.util.*; 

class SetOfBlocks extends ArrayList<Block> {
  void draw(Graphics g) {
    for (Block b : this) 
      b.draw(g); 
  }
  void move(int dx, int dy) {
    for (Block b : this) 
      b.move(dx, dy); 
  }
  void rotateCW(Point center) {
    for (Block b : this)
      b.rotateCW(center); 
  }
  boolean contains(Block block) {
    if (this.size() != 0) 
      for (Block b : this)
        if (b.equals(block))
          return true;
    return false; 
  }
  boolean subset(SetOfBlocks blocks) {
    if (this.size() != 0)
      for (Block b : this)
        if (! blocks.contains(b))
          return false; 
    return true; 
  }
  boolean equals(SetOfBlocks blocks) {
    return this.subset(blocks) && blocks.subset(this);  
  }
  SetOfBlocks intersect(SetOfBlocks other) {
    SetOfBlocks result = new SetOfBlocks(); 
    for (Block b : this)
      if (other.contains(b))
        result.add(b); 
    return result; 
  }
  SetOfBlocks union(SetOfBlocks other) {
    SetOfBlocks result = new SetOfBlocks(); 
    for (Block b : this)
      if (! result.contains(b) )
        result.add(b); 
    for (Block b : other)
      if (! result.contains(b) )
        result.add(b); 
    return result; 
  }
  int count() {
    return this.size(); 
  }
  int maxY() {
    int result = 0; 
    for (Block b : this)
      if (b.y > result) 
        result = b.y; 
    return result; 
  }
  int minX() {
    int result = Tetris.COLUMNS; 
    for (Block b : this)
      if (b.x < result)
        result = b.x; 
    return result; 
  }
  int maxX() {
    int result = 0; 
    for (Block b : this)
      if (b.x > result)
        result = b.x; 
    return result; 
  }
  void changeColor(Color color) {
    for (Block b : this) 
      b.setColor(color); 
  }
  boolean overflow() {
    for (Block b : this)
      if (b.y <= 0)
        return true;
    return false;
  }
  SetOfBlocks row(int row) {
    SetOfBlocks result = new SetOfBlocks(); 
    for (Block b : this)
      if (b.y == Tetris.ROWS - row)
        result.add(b); 
    return result; 
  }
  boolean fullRow(int row) {
    int a = this.row(row).count(); 
    int b = Tetris.COLUMNS; 
    // System.out.println( a + " vs " + b ); 
    return a == b; 
  }
  void eliminateRow(int i) { // i == 0 indicates bottom row 
    SetOfBlocks row = new SetOfBlocks(); 
    for (Block b : this) 
      if (b.y == (Tetris.ROWS - i))
        row.add(b); 
    for (Block b : row)
      this.remove(b); 
    for (Block b : this) 
      if (b.y < (Tetris.ROWS - i))
        b.move(0, 1); 
  }
  void eliminateFullRows() {
    for (int i = 0; i < Tetris.ROWS;    ) {
      if (this.fullRow(i)) {
        // System.out.println("Eliminating: " + i); 
        this.eliminateRow(i); 
      } else i++; 
    }
  }
}

__

import java.awt.*; 
import java.awt.event.*; 

class Tetris implements World {
  static final int ROWS = 20; 
  static final int COLUMNS = 10; 
  Tetromino t; 
  SetOfBlocks blocks; 
  Tetris(Tetromino t, SetOfBlocks s) {
    this.t = t;
    this.blocks = s; 
  }
  public void draw(Graphics g) { 
    t.draw(g); 
    blocks.draw(g); 
    g.drawRect(5, 0, Tetris.COLUMNS * Block.SIZE, Tetris.ROWS * Block.SIZE); 

    for (int i = 0; i < COLUMNS; i++)
      g.drawLine((20*i) + 5, 400, (20*i) + 5, 0);

    for (int i = 0; i < ROWS; i++)
      g.drawLine(5, 20*i, 205, 20*i); 

  } 
  public void update() { 

    if (this.landed())
      this.touchdown(); 
    else 
      this.t.move(0, 1); 
  }
  public boolean hasEnded() { return false; }

  public void keyPressed(KeyEvent e) { 


    if (this.landed())
      this.touchdown(); 

    int keycode = e.getKeyCode();
     switch (keycode) {
             case KeyEvent.VK_LEFT:               
                  { this.t.move(-1,  0);
             this.t.outOfBounds(0, 400);}
                 break;
             case KeyEvent.VK_RIGHT:
                 { this.t.move( 1,  0); } 
                 break;
             case KeyEvent.VK_DOWN:
                 { this.t.move( 0,  1); } 
                 break;
       case 'r':
                 { this.t.rotateCW(); } 
                 break;
             case KeyEvent.VK_SPACE:
                 { this.jumpDown(); }
                 break;

     }
  }


  public static void main(String[] args) {
    BigBang game = new BigBang(new Tetris(Tetromino.sQuare(), new SetOfBlocks())); 
    game.start(); 
  }
  public void touchdown() {
    this.blocks = this.blocks.union(this.t.blocks);
    this.blocks.eliminateFullRows(); 
    this.t = Tetromino.pickRandom(); 
  }
  void jumpDown() {
    if (! this.landed()) { 
      this.t.move(0, 1); 
      this.jumpDown(); 
    }      
  }
  boolean landedOnBlocks() {
    this.t.move(0, 1); 
    if (this.t.overlapsBlocks(this.blocks)) {
      this.t.move(0, -1); 
      return true; 
    } else {
      this.t.move(0, -1); 
      return false; 
    }
  }
  boolean landedOnFloor() {
    return this.t.blocks.maxY() == Tetris.ROWS - 1; 
  }
  boolean landed() {
    return this.landedOnFloor() || this.landedOnBlocks();  
  }
}

__

class Tetromino {
  static Tetromino sQuare()    { 
    return new Tetromino(new Point(0, -1), 
                         makeBlocks(new int[] {0, -1, 0, -2, 1, -1, 1, -2}, 
                         Color.GREEN   )); 
  } 
  static Tetromino liNe()      { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 3, -1}, 
                         Color.BLUE    )); 
  } 
  static Tetromino l()         { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 2, -2}, 
                         Color.MAGENTA )); 
  } 
  static Tetromino MirroredL() { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 0, -2}, 
                         Color.CYAN    )); 
  } 
  static Tetromino t()         { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 1, -2}, 
                         Color.ORANGE  )); 
  } 
  static Tetromino s()         { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 1, -2, 2, -2}, 
                         Color.RED     )); 
  } 
  static Tetromino z()         { 
    return new Tetromino(new Point(1, -2), 
                         makeBlocks(new int[] {0, -2, 1, -2, 1, -1, 2, -1}, 
                         Color.PINK    )); 
  } 

  static SetOfBlocks makeBlocks(int[] c, Color color) {
    SetOfBlocks a = new SetOfBlocks(); 
    a.add(new Block( c[0],  c[1], color)); 
    a.add(new Block( c[2],  c[3], color)); 
    a.add(new Block( c[4],  c[5], color)); 
    a.add(new Block( c[6],  c[7], color)); 
    return a;
  }
  Point center;
  SetOfBlocks blocks;
  Tetromino(Point center, SetOfBlocks blocks) {
    this.center = center; 
    this.blocks = blocks; 
  }
  void draw(Graphics g) {
    this.blocks.draw(g); 
  }
  void move(int dx, int dy) {
    this.center.move(dx, dy); 
    this.blocks.move(dx, dy); 
  }
  public String toString() {
    return this.center + " " + this.blocks ;  
  }
  void rotateCW() {
    this.blocks.rotateCW(this.center);  
  }
  boolean overlapsBlocks(SetOfBlocks blocks) {
    return this.blocks.intersect(blocks).count() > 0;  
  }
  void changeColor(Color color) {
    this.blocks.changeColor(color);  
  }
  static Tetromino pickRandom() {
    int value = (int)(Math.random() * 7);  
    if (value == 0) return Tetromino.sQuare();
    else if (value == 1) return Tetromino.liNe(); 
    else if (value == 2) return Tetromino.l(); 
    else if (value == 3) return Tetromino.MirroredL(); 
    else if (value == 4) return Tetromino.t(); 
    else if (value == 5) return Tetromino.s(); 
    else return Tetromino.z(); 
  }
}

__

import java.awt.*; 
import java.awt.event.*; 

interface World {
  public void draw(Graphics g);
  public void update(); 
  public boolean hasEnded();
  public void keyPressed(KeyEvent e); 

}
1

There are 1 answers

0
Adrian Sanguineti On

The error message is telling you the exact problem:

1 error found: File: .../Tetris.java [line: 46] Error: The method outOfBounds(int, int) is undefined for the type package.Tetromino

Your outOfBounds(int,int) method could not be found when you attempt to call it from your KeyHandler

Here is the snippet of the case statement where you are trying to call it.

case KeyEvent.VK_LEFT:               
 { this.t.move(-1,  0);
    this.t.outOfBounds(0, 400);}
 break;

You are calling the method on your poorly named t variable (variable names should be descriptive and appears to part of the cause of your woes), which is a variable of type Tetromino class. Your Tetromino class clearly does not have a method called outOfBounds(int, int) defined. And hence the error.

Your outOfBounds(int, int) is clearly defined on your Blocks class, but as a private method, meaning only the Blocks class its self can access it.