Making of Tetris Game in Java

Here in this post, i will share a Java program to make a Tetris game. I have already wrote a post on how to make a tetris game in C language. I have discussed the data structures used in the program in that post. The Java program is almost similar to it. The description is available in this post: Making of Tetris Game in C.

The following video shows the java code in action:


The tetris game Java source code is as follows:


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JOptionPane;



public class Tetris extends JFrame{

boolean stopthread=false;
int SIZE_HORIZ=13;
int SIZE_VERTI=35;
Graphics g;
boolean waitnow=false;
int[][] board=new int[SIZE_VERTI][SIZE_HORIZ];
int t_[]={1,0,1,1,1,2,2,1};
int t_90[]={0,1,1,0,1,1,2,1};
int t_180[]={0,1,1,0,1,1,1,2};
int t_270[]={0,1,1,1,1,2,2,1};
int l_[]={0,2,1,0,1,1,1,2};
int l_90[]={0,1,1,1,2,1,2,2};
int l_180[]={1,0,1,1,1,2,2,0};
int l_270[]={0,0,0,1,1,1,2,1};
int s_[]={0,0,0,1,1,0,1,1};
int z_[]={1,1,1,2,2,0,2,1};
int z_90[]={0,1,1,1,1,2,2,2};
int i_ver[]={0,1,1,1,2,1,3,1};
int i_hor[]={1,0,1,1,1,2,1,3};
String scorestr;
Random rand=new Random(System.currentTimeMillis());
Color colors[]={Color.BLUE,Color.GREEN,Color.MAGENTA,Color.RED,Color.YELLOW};
File HighScore;
Color bgcolor=Color.WHITE;
/*
Numbering for blocks:
(values of fallingBlockNumber)
0=T
1=L
2=S
3=Z
4=I
*/
int [] blockarray;
int fallingblockNum;
int fallingBlockVersion=0;
int fallingBlockRow=0;
int fallingBlockCol=0;
int startdelay=200;
int motiondelay;
int scoreInc=5;
int myscore=0;
int tversion;
boolean spawn=true;
int scorespeedctrl=0;
int timehalving=0;
String highscoreholder;
int highscore;
KeyListener kl;

public Tetris()
{
int i,j;
startdelay=250;
scoreInc=5;
myscore=0;
motiondelay=startdelay;
NextBlock();
for(i=0;i<35;i++)
    for(j=0;j<13;j++)
 board[i][j]=0;
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(480,500);
setResizable(false);
setLocationRelativeTo(null);
HighScore=new File(System.getProperty("java.io.tmpdir")+File.separator+"TetrisHighScore");
try{
if(HighScore.exists())
    {
    BufferedReader br=new BufferedReader(new FileReader(HighScore));
    highscoreholder=br.readLine();
    highscore=Integer.parseInt(br.readLine());
    br.close();
    }
else
    {
    highscoreholder=null;
    highscore=0;
    }
}catch(Exception ex){}
kl=new KeyListener() {
    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
    
        if(!spawn&&!waitnow)
 {
            waitnow=true;
            int key=e.getKeyCode();
     if(key==KeyEvent.VK_UP)//up
  {
  if(fallingblockNum==0||fallingblockNum==1)
      tversion=(fallingBlockVersion+1)%4;
  else if(fallingblockNum==4||fallingblockNum==3)
      tversion=(fallingBlockVersion+1)%2;

  if(fallingblockNum!=2&&isDrawable(fallingBlockRow,fallingBlockCol,tversion))
      {
      clearOldBlockVersion(g);
      fallingBlockVersion=tversion;
      blockarray=getFallingBlockArray();
      drawNewBlockVersion(g);
      }
  }
     else if(key==KeyEvent.VK_LEFT)//left
  {
  if(isDrawable(fallingBlockRow,fallingBlockCol-1,fallingBlockVersion))
      {
      clearOldBlockVersion(g);
      fallingBlockCol--;
      drawNewBlockVersion(g);
      }
  }
     else if(key==KeyEvent.VK_RIGHT)//right
  {
  if(isDrawable(fallingBlockRow,fallingBlockCol+1,fallingBlockVersion))
      {
      clearOldBlockVersion(g);
      fallingBlockCol++;
      drawNewBlockVersion(g);
      }
  }
     else if(key==KeyEvent.VK_DOWN)//down
  {
  if(isDrawable(fallingBlockRow+1,fallingBlockCol,fallingBlockVersion))
      {
      clearOldBlockVersion(g);
      fallingBlockRow++;
      drawNewBlockVersion(g);
      }
  }
            waitnow=false;
 }
    }
    @Override
    public void keyReleased(KeyEvent e) {}
};
th.start();
addKeyListener(kl);
}

void NextBlock()
{
fallingblockNum=rand.nextInt(5);
if(fallingblockNum==0||fallingblockNum==1)
 fallingBlockVersion=rand.nextInt(4);
else if(fallingblockNum==4||fallingblockNum==3)
 fallingBlockVersion=rand.nextInt(2);
else
 fallingBlockVersion=0;
fallingBlockRow=0;
fallingBlockCol=5;
blockarray=getFallingBlockArray();
}

int[] getFallingBlockArray()
{
int a=fallingblockNum*10+fallingBlockVersion;
switch(a)
    {
    case 0:return (t_);
    case 1:return (t_90);
    case 2:return (t_180);
    case 3:return (t_270);
    case 10:return (l_);
    case 11:return (l_90);
    case 12:return (l_180);
    case 13:return (l_270);
    case 20:return (s_);
    case 30:return (z_);
    case 31:return (z_90);
    case 40:return (i_hor);
    case 41:return (i_ver);
    }
return (i_ver);
}

boolean isDrawable(int newrow,int newcol,int blockversion)
{
int i,tempversion;
boolean flag=true;
tempversion=fallingBlockVersion;
fallingBlockVersion=blockversion;
blockarray=getFallingBlockArray();
for(i=0;i<8;i+=2)
    {
    if(newrow+blockarray[i]>34||newrow+blockarray[i]<0)
 {
 flag=false;
 break;
 }
    if(newcol+blockarray[i+1]>12||newcol+blockarray[i+1]<0)
 {
 flag=false;
 break;
 }
    if(board[(newrow+blockarray[i])][(newcol+blockarray[i+1])]==2)
 {
 flag=false;
 break;
 }
    }
fallingBlockVersion=tempversion;
blockarray=getFallingBlockArray();
return flag;
}

void clearOldBlockVersion(Graphics g)
{
int i,r,c;
for(i=0;i<8;i+=2)
 {
 r=fallingBlockRow+blockarray[i];
 c=fallingBlockCol+blockarray[i+1];
 board[r][c]=0;
 g.setColor(bgcolor);
        g.fillRect(8+c*13,32+r*13,14,14);
 }
}

void drawNewBlockVersion(Graphics g)
{
int i,r,c;
for(i=0;i<8;i+=2)
 {
 r=fallingBlockRow+blockarray[i];
 c=fallingBlockCol+blockarray[i+1];
 board[r][c]=1;
        g.setColor(colors[fallingblockNum]);
 g.fillRect(8+c*13,32+r*13,13,13);
        g.setColor(Color.BLACK);//cyan,orange
 g.drawRect(8+c*13,32+r*13,13,13);
 }
}
boolean isGameOver(Graphics g)
{
if(isDrawable(0,5,fallingBlockVersion)==false)
    return true;
drawNewBlockVersion(g);
if(isAtBottom())
    return true;
return false;
}

boolean isAtBottom()
{
int i,max=0,ti,tj;
for(i=0;i<8;i+=2)
    if(blockarray[i]>max)
 max=blockarray[i];
if(fallingBlockRow+max>=34)
 return true;
for(i=0;i<8;i+=2)
    {
    ti=blockarray[i]+fallingBlockRow;
    tj=blockarray[i+1]+fallingBlockCol;
    if(board[ti+1][tj]==2)
       return true;
    }
return false;
}

void showScore(Graphics g)
{
int left,top;
left=getWidth()-100;
top=getHeight()/2;
g.setColor(bgcolor);
g.fillRect(left,top,80,70);
g.setColor(Color.RED);
g.setFont(new Font("Arial",Font.BOLD,14));
g.drawString("Score: "+Integer.toString(myscore),left,top+20);
}

void CollapseFilledRow(Graphics g)
{
int i,j,k,sum,copyskipover=0,r;
for(i=34;i>=0;)
    {
    sum=0;//full flag
    for(j=0;j<13;j++)
 sum+=board[i][j];
    if(sum==2*13)//row full
 {
 myscore+=scoreInc;
 copyskipover++;
 }
    if(sum==0)
 break;
    i--;
    if(copyskipover>0)
 {
 for(j=0;j<13;j++)
     {
     r=i+copyskipover;
     board[r][j]=board[i][j];
     if(board[i][j]==0)
  {
                g.setColor(bgcolor);
                g.fillRect(8+j*13,32+r*13,14,14);
  }
     else
  {
                g.setColor(Color.GREEN);
                g.fillRect(8+j*13,32+r*13,13,13);
                g.setColor(Color.BLACK);
                g.drawRect(8+j*13,32+r*13,13,13);
  }
     }
 }
    }
for(k=0;k<copyskipover;k++)
    {
    r=i+k;
    for(j=0;j<13;j++)
 {
 board[r][j]=0;
        g.setColor(bgcolor);
 g.fillRect(8+j*13,32+r*13,14,14);
 }
    }
showScore(g);
}


public static void main(String[] args)
{
Tetris tt=new Tetris();
tt.setVisible(true);
}

void GameOver(Graphics g)
{
stopthread=true;
g.setColor(Color.RED);
g.setFont(new Font("Arial",Font.BOLD,28));
String str="Game Over.";
g.drawString(str,getWidth()/2-10, getHeight()/2);
if(highscore>0)
    str="Highscore : "+highscoreholder+" - "+Integer.toString(highscore);
g.setFont(new Font("Arial",Font.BOLD,16));
g.drawString(str,getWidth()/2-30, getHeight()/2+80);
if(myscore>highscore)
    {
        highscoreholder=JOptionPane.showInputDialog("New high score. Enter your name:");
        highscore=myscore;
        try{
        if(!HighScore.exists())
            HighScore.createNewFile();
        BufferedWriter bw=new BufferedWriter(new FileWriter(HighScore));
        bw.write(highscoreholder);
        bw.newLine();
        bw.write(Integer.toString(highscore));
        bw.close();
        }catch(Exception ee){}
    }
}


Thread th=new Thread()
{
int i;
public void run()

{
try {
    while(!isShowing())
        Thread.sleep(1000);
    } catch (InterruptedException ex) {}
setOpacity(1f);
setBackground(bgcolor);
getContentPane().setBackground(bgcolor);
g=getGraphics();
g.setColor(Color.RED);
g.drawRect(6,30,13*13+6,35*13+6);
showScore(g);
while(!stopthread)
{
g.setColor(Color.RED);
g.drawRect(6,30,13*13+6,35*13+6);
while (waitnow)
    {
    try {
        Thread.sleep(20);
    } catch (InterruptedException ex) {}
    }
waitnow=true;
if(isAtBottom()&&!spawn)
 {
 for(i=0;i<8;i+=2)
     {
     board[fallingBlockRow+blockarray[i]][fallingBlockCol+blockarray[i+1]]=2;
     }
 spawn=true;
 CollapseFilledRow(g);
 }
    if(spawn)
 {
 NextBlock();
 blockarray=getFallingBlockArray();
 spawn=false;
 if(isGameOver(g))
     {
     GameOver(g);
     return;
     }
 }
    else
 {
 timehalving=(timehalving+1)%3;
 if(timehalving==2)
  {
  clearOldBlockVersion(g);
  fallingBlockRow++;
  drawNewBlockVersion(g);
  }
 }
    scorespeedctrl=(scorespeedctrl+1)%140;
    if(scorespeedctrl==0&&motiondelay>0)
 {
 motiondelay-=12;
 scoreInc+=2;
        if(motiondelay<0)
            motiondelay=0;
 }
    waitnow=false;
    try {
        Thread.sleep(motiondelay);
            } catch (InterruptedException ex) {}
}
}
};
}

No comments:

Post a Comment