Jump to content

  • Log In with Google      Sign In   
  • Create Account


Putting pieces inside a board


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
22 replies to this topic

#1 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 17 February 2013 - 01:34 PM

To fill in the board square covered by a piece, it
would be helpful to have a method similar to the one above that copies
the non-zero entries from the given array into the corresponding board
squares.


I need to implement this now, but I have the following questions:

where do I put the contents array? I don't see a board array in the program

do
i need to put the contents array inside the board once it was laid down
or once it appears? and how do i know a piece was laid down? what if
statement should i use for that?

 

 

Code:

 

import java.awt.*;

public class Board extends Grid {
    public static final int COLUMNS = 16;
    public static final int ROWS = 32;
    public static final Color BLUE = new Color(0,0,128,40);
    
    public Board() {
        super(new int[ROWS][COLUMNS]);
        setSize(COLUMNS*Tetris.SQUARE_SIZE,
                ROWS*Tetris.SQUARE_SIZE);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(BLUE);
        paintStripes(g);
    }
    
    void paintStripes(Graphics g) {
        for (int i = 0; i < COLUMNS; i += 4) {
            g.fillRect(i*Tetris.SQUARE_SIZE,0,
                Tetris.SQUARE_SIZE*2,Tetris.SQUARE_SIZE*ROWS);
        }
    }
    

}

 

 

 

Code:


 

public class PieceFactory {

    public static final int[][] L1 =
        {{1,1,0,0},
         {0,1,0,0},
         {0,1,0,0},
         {0,0,0,0},
        };

    public static final int[][] L2 =
        {{0,1,0,0},
         {0,1,0,0},
         {1,1,0,0},
         {0,0,0,0},
        };

    public static final int[][] T =
        {{0,1,0,0},
         {1,1,0,0},
         {0,1,0,0},
         {0,0,0,0},
        };

    public static final int[][] BOX =
        {{1,1,0,0},
         {1,1,0,0},
         {0,0,0,0},
         {0,0,0,0},
        };

    public static final int[][] BAR =
        {{1,1,1,1},
         {0,0,0,0},
         {0,0,0,0},
         {0,0,0,0},
        };

    public static final int[][] STEP1 =
        {{1,0,0,0},
         {1,1,0,0},
         {0,1,0,0},
         {0,0,0,0},
        };

    public static final int[][] STEP2 =
        {{0,1,0,0},
         {1,1,0,0},
         {1,0,0,0},
         {0,0,0,0},
        };

    public static final int[][][] SHAPES = {L1,L2,T,BOX,BAR,STEP1,STEP2};

    public static Piece createPiece() {
        int[][] s = SHAPES[(int) (Math.random()*SHAPES.length)];
        switch ((int) (Math.random()*10)) {
            case 0:
            case 1:
            case 2:
            case 3:
            default: return new Piece(s);
        }


    }




}

 

 

Code:


 

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

public class Tetris extends JFrame implements KeyListener {
    public static final int SQUARE_SIZE = 10; // 10 by 10 pixels

    static Board board;
    static Tetris game;

    JPanel mainPanel;
    public Piece currentPiece;
    int score = 0;
    JButton scoreButton;

    public Tetris() {
        super("Tetris");
        game = this;
        Container pane = getContentPane();
        pane.setLayout(new BorderLayout());

        scoreButton = new JButton("0");
        scoreButton.setEnabled(false);
        pane.add(scoreButton,BorderLayout.NORTH);

        board = new Board();
        mainPanel = new JPanel();
        mainPanel.setLayout(null);
        mainPanel.add(board);
        mainPanel.setPreferredSize
            (new Dimension(Board.COLUMNS*SQUARE_SIZE,
                           Board.ROWS*SQUARE_SIZE));
        pane.add(mainPanel);

        addKeyListener(this);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                System.exit(0);
            }
        });
        pack();
        show();
        setResizable(false);
    }


    public void addToScore(int v) {
        score += v;
        scoreButton.setText(""+score);
    }

    public int getScore() {
        return score;
    }

    static Board getBoard() {
        return board;
    }

    static Tetris getGame() {
        return game;
    }

    static void sleep(int milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException ie) {
        }
    }

    public static void main(String[] args) {
        Tetris game = new Tetris();
        while (true) {
            game.dropPiece();
        }
    }

    void dropPiece() {
        currentPiece = PieceFactory.createPiece();
        mainPanel.add(currentPiece);
        currentPiece.repaint();
        currentPiece.fall();
        //mainPanel.remove(currentPiece);
        board.repaint();
        addToScore(1);
    }

    public void keyPressed(KeyEvent event) {
        int key = event.getKeyCode();
        switch (key) {
        case KeyEvent.VK_UP:  // up arrow
        case KeyEvent.VK_KP_UP:
            currentPiece.rotateCounterclockwise();
            break;
        case KeyEvent.VK_DOWN:  // down arrow
        case KeyEvent.VK_KP_DOWN:
            currentPiece.rotateClockwise();
            break;
        case KeyEvent.VK_LEFT:  // left arrow
        case KeyEvent.VK_KP_LEFT:
            currentPiece.moveLeft();
            break;
        case KeyEvent.VK_RIGHT:  // right arrow
        case KeyEvent.VK_KP_RIGHT:
            currentPiece.moveRight();
            break;
        case KeyEvent.VK_SPACE:  //  space bar
            currentPiece.drop();
        }
    }

    public void keyReleased(KeyEvent arg0) {
    }

    public void keyTyped(KeyEvent arg0) {
    }


}
 

 


Code:
 

 

public class Piece extends Grid {
    int currentX;     // current X location on the board
    double currentY;  // current Y location on the board


    public Piece(int shape[][]) {
        super(shape);
        currentX = 7;
        currentY = 2;
        updateLocation();
    }

    public Piece(int shape[][], currentX, currentY) {
        super(shape);
        this.currentX = currentX;
        this.currentY = currentY;
        updateLocation()
    }



    void updateSize() {
        setSize(Tetris.SQUARE_SIZE*getColumns(),
                Tetris.SQUARE_SIZE*getRows());
    }

    void updateLocation() {
        setLocation(Tetris.SQUARE_SIZE*currentX,
                    (int) (Tetris.SQUARE_SIZE*currentY));
    }

    synchronized void moveDown() {

    }

    synchronized void moveLeft() {
        currentX--;
        updateLocation();
    }

    synchronized void moveRight() {
        currentX++;
        updateLocation();
    }

    synchronized void rotateClockwise() {
        int x = currentX;
        int y = currentY;

        currentPiece = new Piece(s, x, y);

        updateLocation();
    }




    synchronized void rotateCounterclockwise() {
    }

    void fall() {
        // replace the following by your code
        Tetris.sleep(2000);
    }

    synchronized void drop() {
        currentY++;
        updateLocation();
    }

  public static int [][] multiplyMatrix(int [][] m1)
  {
          int [][] m2 =
        {{0,0,0,1},
         {0,0,1,0},
         {0,1,0,0},
         {1,0,0,0},
        };


    int[][] result = new int[4][4];

    // multiply
    for (int i=0; i<4; i++)
      for (int j=0; j<4; j++)
        for (int k=0; k<4; k++)
        if (m1[i][k] * m2[k][j] > 0)
        {
            result[i][j] = 1;
        }
        else
        {
            result[i][j] = 0;
        }


    return result;
  }

    }
 

 



Sponsor:

#2 ultramailman   Prime Members   -  Reputation: 1561

Like
0Likes
Like

Posted 17 February 2013 - 03:13 PM

Can you explain how this works? The code is lacking comments, and (for me) it is hard to understand how it works. I do know this is tetris though. Is the bold text the assignment criteria you have to follow?

#3 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 17 February 2013 - 05:59 PM

Yup, but the problem is I didn't write the code, so I too have difficulty parsing it. As far as I know contents = the pieces that falls from the top and the constructor in Grid prints it.



#4 concepts   Members   -  Reputation: 122

Like
1Likes
Like

Posted 17 February 2013 - 06:04 PM

 

  1. Study the provided code to get a feel for what it does. Some
    of the graphics details (for example, how graphics components are
    created, added to containers, and painted) haven't been covered in
    CSE131, but go ahead and read through the files Tetris.java,
    Grid.java, Board.java, Piece.java, and
    PieceFactory.java to understand the way the implementation
    is organized. Notice that the Tetris class provides some static
    methods for getting references to the board and the tetris game
    itself so that other objects can call methods on them, for example
    to check if a board position would be legal, or to add points to
    the score.
  2. The class Grid is the parent of both the Board and Piece classes.
    Study its implementation. Notice that a Grid object is created by
    passing it an array of rows, where each row is an array of integers
    representing the squares in the columns of that row. If an array
    entry is 0, the corresponding square is considered to be empty.
    Look at the paint method to see how a grid paints itself based on
    its array.

     

    • Add a method to the Grid class that takes in a row number
      as a parameter and returns true exactly when the given row is
      full (has no zero entries). This will be useful for determining
      when to remove a row from the board.
    • Similarly, add a method to the Grid class that returns true
      when a given row is entirely empty. This will be useful for
      determining when the game is over. (Because the game continues
      as long as the top row of the board is empty.)


     

  3. The Board class extends Grid. It will be helpful to add the
    following methods:

     

     

    • Write a method in the Board class that takes a row and
      column index and a two-dimensional array as parameters, and
      checks to see that the non-zero entries of the given array
      correspond to empty positions on the grid, assuming that the
      given array's upper left were positioned at the given row and
      column. You'll use this to determine if a piece can move into
      a given position.
    • To fill in the board square covered by a piece, it would be
      helpful to have a method similar to the one above that copies
      the non-zero entries from the given array into the corresponding
      board squares.
    • Finally, when it's necessary to remove a row, it would be
      nice to have a method on the board that would take that row
      out, move all the others down, and then replace the top row
      with an empty one. For effect, you may want to first clear
      the row being removed, sleep one second, and then bump down
      the other rows. Remember that since the grid is represented
      as an array of rows, it is not necessary to copy all the values
      in the arrays. Just move the rows themselves.


     

  4. The Piece class also extends Grid. Notice that its currentX
    (column) position is represented as an int, but its currentY (row)
    position is represented as a double. This is so you can drop the
    piece gradually, probably 1/5 of a square at a time. To determine
    the next whole row number, the method Math.ceil may help
    you.

     

    • In the Piece class, you'll want methods for moving the
      piece down, moving it left and right by one column, and for
      rotating the piece clockwise and counterclockwise 90 degrees.
      (You want these methods to be synchronized so that two
      modifications of the piece aren't attempted concurrently.)
      When a piece is rotated, the array changes shape (somewhat
      similar, but not exactly like, the transpose algorithm we did
      in class). Note: Each time you move a piece, call its
      updateLocation method so that it gets painted properly on the
      board. Similarly, each time you change the shape of a piece,
      call its updateSize method. You should only move or rotate a
      piece if it would be legal to do so. (The methods of the Board
      will be helpful for determining legality of a board position.)
    • You'll need to write a method that is responsible for making
      the piece fall from the top of the board until it's supposed to
      stop, at which time it should fill in the board as appropriate.
      Call the static sleep method in the Tetris class to
      control the animation speed. Remember, though, that when the
      space bar is pressed, the piece should fall without delay.

Maybe this will help you.

 

If you have questions, don't hesitate I will try to answer them.



#5 freeworld   Members   -  Reputation: 325

Like
3Likes
Like

Posted 17 February 2013 - 07:01 PM

obviously homework.... The questionsuggests you already have a function that pretty much does what it is you're supposed to do, you just have to make the changes you're told to make and write a new function to to just that.

 

 You don't see the the board array? it's the first chunk of code you posted.

 

if this really is homework, ask your instructor these same exact questions, that's what you're paying him for.


Edited by freeworld, 17 February 2013 - 07:14 PM.

[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.

#6 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 17 February 2013 - 08:37 PM

http://mathcs.slu.edu/~fritts/cse131/labs/lab9/index.html

 

not a homework

 

i just googled the tutorial

 

I have a question:

 

there are 2 classes that extends Grid, which has a int [] [] contents attribute. do both classes have their own copy and if so how can I access them individually?



#7 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 17 February 2013 - 08:51 PM

I have a question: how can i put the pieces inside the board?

 

Do I have to do it after it lands or as soon as it appears?

 

And what if statement would I use? I don't understand how I could implement this...



#8 ultramailman   Prime Members   -  Reputation: 1561

Like
3Likes
Like

Posted 18 February 2013 - 12:18 AM

Oh I see what you mean, after thinking about how I would make a tetris clone.

I suppose I would keep the position of the shape that is currently dropping down, and not write the shape array into the content array until the shape hits bottom and becomes part of the unmoving blocks.

#9 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 18 February 2013 - 12:51 AM

What would the condition be then? And how do you access the shape variable from the Board class? Earlier, for Piece, I simpy wrote shapes = a (a = int[][]array), but the method call was currentPiece.moveDown() (currentPiece is an instance of Piece). If the method call was simpy method(), how would I assign the shape variable of the Board class a value (both Piece and Board inherit shapes attribute from the parent class).



#10 ultramailman   Prime Members   -  Reputation: 1561

Like
2Likes
Like

Posted 18 February 2013 - 01:10 AM

I guess I am confused again. When you say "putting a piece inside the board", do you mean when a new pieces comes into the view at the top? Or do you mean when the piece finally settles down and becomes a part of the board landscape?

#11 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 18 February 2013 - 09:39 AM

synchronized void moveLeft() {



currentX--;

updateLocation();

board.method(); //method puts an array inside a bigger array



}

 

if I want to put shapes inside board, this is what must be done, right?



#12 ultramailman   Prime Members   -  Reputation: 1561

Like
2Likes
Like

Posted 18 February 2013 - 12:03 PM

If you mean writing the contents of a piece array into the board array, I think it should happen only when the pieces settles down, and not when it is still moving. So I don't think it belongs in the moveLeft method, unless I am misunderstanding you again.

#13 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 18 February 2013 - 04:25 PM

    public Board() {
        super(new int[ROWS][COLUMNS]);
        setSize(COLUMNS*Tetris.SQUARE_SIZE,
                ROWS*Tetris.SQUARE_SIZE);
    }

 

 

How do I access int[ROWS][COLUMNS] outside?

 

I tried the following, but it doesn't work...

 

 

        while(legalDown(currentX, currentY, board.contents, currentPiece.contents) && isNotOutOfBoundDown(currentX, currentY, board.contents, currentPiece.contents))
        {
        currentX--;
        updateLocation();
        updateSize();
        }
 


#14 ultramailman   Prime Members   -  Reputation: 1561

Like
4Likes
Like

Posted 18 February 2013 - 05:36 PM

Ok, now I see what you mean. The array you are looking for is in the Grid class. You don't see it in the Board class because Grid has it. Is the Grid class available to you? You will have to see which methods of the Grid class allows you to change the array.

#15 freeworld   Members   -  Reputation: 325

Like
2Likes
Like

Posted 18 February 2013 - 08:10 PM

The board class is a grid itself. What does the grid class look like. Does it have operator to allow access to the data like a normal array? Or functions to do so.

I would keep the falli g piece seperate from the board untill its done falling. Then copy the contents of your pieces to the correct spot on the board.
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.

#16 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 18 February 2013 - 10:15 PM

    synchronized void drop(Board board) {
        int [][] a = getContents();
        int [][] b = board.getContents();

        if(Board.legalDown(currentX, currentY, b, a) && Board.isNotOutOfBoundDown(currentX, currentY, b, a) && currentY < 28 )
        {
        currentY++;
        updateLocation();
        }
        else
        {
        Board.addArray(currentX, currentY, b, a);
        }

    }
 

 

	void fall(Board board) {

		int [][] a = getContents();
		int [][] b = board.getContents();


		while(currentY < 28)
		{
			if(Board.legalDown(currentX, currentY, b, a) && Board.isNotOutOfBoundDown(currentX, currentY, b, a))
			{currentY++;
			updateLocation();
	    	updateSize();
	    	Tetris.sleep(2000);
			}
			else
			{

			Board.addArray(currentX, currentY, b, a);

			}
		}

		//Tetris.sleep(2000);
	}
	public static void addArray(int currentX, int currentY, int[][] board, int[][] shape)
	{
	   int x = currentY;
	   int y = currentX;

	   for (int row = 0; row < 4; row++)
	   {
	   	for(int col = 0; col < 4; col++)
	   	{


	   		if (shape[row][col] == 1 )
	   		{

				board[x+row][y+col] = 1;
	   		}


	   	}
	   }
	}

	public static boolean legalDown(int currentX, int currentY, int[][] board, int[][] shape)
	{
	   int x = currentY+1;
	   int y = currentX;

	   for (int row = 0; row < 4; row++)
	   {
	   	for(int col = 0; col < 4; col++)
	   	{
	   		if(x + row == 32)
	   		{
	   			return false;
	   		}


	   		if (shape[row][col] == 1 && board[x+row][y+col] == 0)
	   		{


	   		}
	   		else
	   		{
	   			if (shape[row][col] == 0 && board[x+row][y+col] == 1)
	   			{

	   			}
	   			else
	   			{

	   			    if(shape[row][col] == 0 && board[x+row][y+row] == 0)
	   			    {

	   			    }

	   			    else
	   			    {

	   				return false;
	   			    }
	   			}
	   		}
	   	}
	   }


    return true;
	}


		public static boolean isNotOutOfBoundDown(int currentX, int currentY, int[][] board, int[][] shape)
	{
	   int x = currentX+1;
	   int y = currentY;
	   int lowestRow = 0;

	   for (int row = 0; row < 4; row++)
	   {
	   	for(int col = 0; col < 4; col++)
	   	{
	   		if (shape[row][col] == 1)
	   		{
	   			lowestRow = row+1;
	   			System.out.println(lowestRow);

	   		}





	    }
	   }

	   if (x + lowestRow > board.length)
	   {
	   	return false; //can't do it
	   }
	   else
	   {
	   	return true;
	   }
	}




Ok, I have some trouble. I get array out of bound exception if I go all the way down, because my method legalDown checks below the grid. So I could only fix it partially by making it stop at 31, then it froze so I fixed it by making it stop at 28 and then some pieces go below 28 after I rotate them. Now, I don't know what to do... Help! And how do I know that a piece landed? Like I fill the array at the end, but it doesn't seem to work that well at certain times...



#17 ultramailman   Prime Members   -  Reputation: 1561

Like
0Likes
Like

Posted 18 February 2013 - 11:27 PM

If, after a rotation, a piece goes underground, then don't allow the rotation to happen. You can either first check that the surrounding area is clear before rotating, or you can rotate and undo if it goes underground.

A shape is considered landed if it overlaps with the board after a drop or a movedown.

#18 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 19 February 2013 - 02:41 AM

It goes underground just because I rotated it earlier and not as I rotate it.

 

I know that, but it seems my code still doesn't work, so...



#19 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 19 February 2013 - 12:30 PM

damnit ... OK it kinda works now, but when I rotate an object there are 2 shapes that are created...
lol



public class Piece extends Grid {
    int currentX;     // current X location on the board
    int currentY;  // current Y location on the board


    public Piece(int shape[][]) {
        super(shape);
        currentX = 7;
        currentY = 5;
        updateLocation();
    }



    void updateSize() {
        setSize(Tetris.SQUARE_SIZE*getColumns(),
                Tetris.SQUARE_SIZE*getRows());
    }

    void updateLocation() {
        setLocation(Tetris.SQUARE_SIZE*currentX,
                    (int) (Tetris.SQUARE_SIZE*currentY));
    }

    synchronized void moveDown() {

    }

    synchronized void moveLeft() {

        currentX--;
        updateLocation();

    }

    synchronized void moveRight() {

        currentX++;
        updateLocation();

    }

    synchronized void rotateClockwise(Board board) {

        int [][] a = getContents();
        int [][] b = board.getContents();

        if(Board.legalDown(currentX, currentY, b, a) && Board.isNotOutOfBoundDown(currentX, currentY, b, a))
        {
        int [][] transpose = new int[4][4];
        transpose = transpose(contents);
        contents = multiplyMatrix(transpose);

        updateLocation();
        updateSize();
        }
    }




    synchronized void rotateCounterclockwise(Board board) {

        int [][] a = getContents();
        int [][] b = board.getContents();

        if(Board.legalDown(currentX, currentY, b, a) && Board.isNotOutOfBoundDown(currentX, currentY, b, a))
        {
        int [][] transpose2 = new int[4][4];
        transpose2 = multiplyMatrix(contents);
        transpose2 = transpose(transpose2);
        contents = transpose2;

        updateLocation();
        updateSize();
        }
    }

    void fall(Board board) {

        int [][] a = getContents();
        int [][] b = board.getContents();


        while(Board.legalDown(currentX, currentY, b, a) && Board.isNotOutOfBoundDown(currentX, currentY, b, a))
        {
            currentY++;
            updateLocation();
            updateSize();
            Tetris.sleep(2000);




        }
        Board.addArray(currentX, currentY, b, a);
        updateSize(); //necessary?

        //Tetris.sleep(2000);
    }

    synchronized void drop(Board board) {
        int [][] a = getContents();
        int [][] b = board.getContents();

        if(Board.legalDown(currentX, currentY, b, a) && Board.isNotOutOfBoundDown(currentX, currentY, b, a))
        {
        currentY++;
        updateLocation();
        }
        else
        {
        Board.addArray(currentX, currentY, b, a);
        updateLocation(); //necessary?
        }

    }

  public static int [][] transpose(int [][] m1)
  {
        int m = 4;
        int n = 4;
        int c = 0;
        int d = 0;

        int[][] transpose = new int [n][m];


        for ( c = 0 ; c < m ; c++ )
      {
          for ( d = 0 ; d < n ; d++ )
          {
             transpose[d][c] = m1[c][d];
          }
      }

      return transpose;

  }

  public static int [][] multiplyMatrix(int [][] m1)
  {
          int [][] m2 =
        {{0,0,0,1},
         {0,0,1,0},
         {0,1,0,0},
         {1,0,0,0},
        };


    int[][] result = new int[4][4];

    // multiply
    for (int i=0; i<4; i++)
      for (int j=0; j<4; j++)
        for (int k=0; k<4; k++)
        result[i][j] += m1[i][k] * m2[k][j];


    return result;
  }

    }


maybe it's because I called updateLocation 2 times sometimes.. I don't know or that rotate() and fall() both fills an array... I don't know..

#20 concepts   Members   -  Reputation: 122

Like
0Likes
Like

Posted 19 February 2013 - 01:59 PM

Uhmm, I had called addArray in two different places, now I only have it in fall();

and I remove updateLocation() in 2 places

Now, it kinda works, but there's an unusual behavior with the "I" block when I rotate it...

Do you have any idea what's causing this?






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS