자바로 만든 테트리스 질문
간단하게 만들어서
.블럭 생성
.블럭 이동
.블럭 회전
.꽉찬 라인 제거
.라인 제거 마다 점수증가
이정도...?
간단한 설명을 하면
블럭을 [4][4] array로, 게임 패널을 [30][20] array로 나타 냈습니다.
그리고 블럭 부분을 1로 하고 나머지는 0으로 초기화 해서 블럭을 표현했고,
이 것을 토대로 [30][20]개의 Label을 만든 후 1인 부분(블럭)을 BackgroundColor로 블럭 색을 만들었습니다.
움직이는 것은 백그라운드 제거, 배열 값 변경, 변경 값으로 백그라운드 설정 으로 나타냈습니다.
Thread로 3초마다 1칸씩 내리고, KeyListener로 좌, 우, 회전을 할 수 있게 했습니다.
게임패널 pre_array를 하나 더만들어서 블럭이 맨 아래로 가거나 1을 만나면 정지 후 pre_array에 array를 대입.
다음 블럭을 만들 때 array에 pre_array 대입해서 내려간 이전 블럭을 유지.
겹치는 블럭 확인은 내리다가 array[y][x] 값이 1이면 정지.
꽉찬 라인 없애는 건 array에서 x축 값이 모두 1이면 그 라인부터 처음 라인까지 덮었습니다.
질문
자바로 처음 만들어 보는거라 많이 조잡 합니다만..
근데 속도가 너무 느립니다. 너무 심하게 느려요.. 블럭이 부셔져서 보입니다.
속도가 느린 이유를 알 수 있을까요?
그리고 다른 방법으로 다시 만들어 보는 중인데
KeyListener를 mainclass에 만 설정 가능한가요? MouseListener하고 KeyListener를 같이 넣어봤는데
MouseListener만 반응하고 KeyListener는 반응하지 않아서 mainclass에 다시 달고 있네요.. requestFocus는 했습니다.
MainFrame
package Tetris;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MainFrame extends JFrame
{
Block block = new Block();
Score ScorePanel = new Score();
int gameX = 20;//Game X-length
int gameY = 30;//Game Y-length
JPanel GamePanel = new JPanel();
JLabel[][] GL = new JLabel[gameY][gameX];
int[][] GameArray = new int[gameY][gameX];
int[][] StandardArray = new int[gameY][gameX];
Down down = new Down();
ArrayList<Integer> line = new ArrayList<Integer>();
ArrayList<Integer> LineCheck()//full line check
{
ArrayList<Integer> Item = new ArrayList<Integer>();
int count;
for(int i = 0; i < gameY; i++)
{
count = 0;
for(int j = 0; j < gameX; j++)
if(GameArray[i][j] == 1)
count++;
if(count == gameX) Item.add(i);
}
return Item;
}
void LineRemove()//full line remove
{
line = LineCheck();
Iterator<Integer> iter = line.iterator();
int index = 0;
int size = line.size();
ScorePanel.Scoring(size);
while(iter.hasNext())
{
index = iter.next();
for(int i = index; i > 1; i--)
for(int j = 0; j < gameX; j++)
GameArray[i][j] = GameArray[i-1][j];
}
index = 0;
}
boolean Overlap()//overlap
{
try
{
for(int i = 0; i < block.array_size; i++)
for(int j = 0; j < block.array_size; j++)
if(block.array[i][j] == 1 &&
StandardArray[i+block.y][j+block.x] == 1)//block overlap
throw new Exception();
return false;
}
catch(Exception e)
{
return true;
}
}
void Next()//next block
{
for(int i = 0; i < gameY; i++)//Game repaint
for(int j = 0; j < gameX; j++)
StandardArray[i][j] = GameArray[i][j];
block = ScorePanel.Pre_block;//next block
ScorePanel.Pre_block = new Block();
}
void View()//view
{
for(int i = 0; i < gameY; i++)
for(int j = 0; j < gameX; j++)//Game repaint
{
GameArray[i][j] = StandardArray[i][j];
if(GameArray[i][j] == 0)
GL[i][j].setBackground(null);
}
for(int i = 0; i < block.array_size; i++)
for(int j = 0; j < block.array_size; j++)//Block repaint
if(block.array[i][j] == 1)
{
GameArray[i+block.y][j+block.x] = 1;
GL[i+block.y][j+block.x].setBackground(block.color);
GL[i+block.y][j+block.x].setOpaque(true);
}
}
class Down extends Thread//down
{
@Override
public void run()
{
// TODO Auto-generated method stub
super.run();
try
{
while(true)
{
block.y++;
if(block.y > 26 || Overlap())//bottom
throw new Exception();
View();
sleep(3000);
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
System.out.println("End");
e.printStackTrace();
}
catch (Exception e)//bottom
{
LineRemove();
Next();
run();
return;
}
}
}
class Keyboard implements KeyListener//keyboard
{
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e)
{
// TODO Auto-generated method stub
try
{
switch(e.getKeyCode())
{
case 37://←
if(Overlap()) break;
block.x--;
View();
break;
case 38://↑
block.Rotate();
View();
break;
case 39://→
if(Overlap()) break;
block.x++;
View();
break;
case 40://↓
if(Overlap()) break;
block.y++;
View();
}
}
catch(ArrayIndexOutOfBoundsException a)
{
switch(e.getKeyCode())
{
case 37://←
block.x++;
View();
break;
case 39://→
block.x--;
View();
break;
case 40://↓
block.y--;
View();
}
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
MainFrame() //main
{
// TODO Auto-generated constructor stub
setTitle("TETRIS");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
ScorePanel.setBounds(240, 20, 90, 300);
GamePanel.setBounds(20, 20, 200, 300);
GamePanel.setLayout(new GridLayout(30, 20, 1, 1));
GamePanel.setBackground(Color.lightGray);
GamePanel.setOpaque(true);
for(int i = 0; i < gameY; i++)
for(int j = 0; j < gameX; j++)//Game initialize
{
GL[i][j] = new JLabel();
GamePanel.add(GL[i][j]);
}
//////test(Bottom OBlock)//////
// for(int i = gameY-2; i < gameY; i++)
// for(int j = 2; j < gameX; j++)
// {
// StandardArray[i][j] = 1;
// GL[i][j].setBackground(block.color);
// GL[i][j].setOpaque(true);
// }
// View();
///////////////////////////////
down.start();
add(GamePanel);
add(ScorePanel);
setSize(350, 400);
setVisible(true);
addKeyListener(new Keyboard());
requestFocus();
}
public static void main(String[] args)
{
// TODO Auto-generated method stub
new MainFrame();
}
}Block
package Tetris;
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Random;
import java.util.Iterator;
import javax.swing.JLabel;
public class Block extends JLabel
{
int[][][] block_array =
{
{//OBlock[0]
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0}
},
{//LBlock[1]
{0, 0, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 1, 0}
},
{//JBlock[2]
{0, 0, 0, 0},
{0, 0, 0, 1},
{0, 0, 0, 1},
{0, 0, 1, 1}
},
{//TBlock[3]
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 1, 1, 1},
{0, 0, 1, 0}
},
{//IBlock[4]
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0}
},
{//ZBlock[5]
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 0, 1, 1}
},
{//SBlock[6]
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 1, 1},
{0, 1, 1, 0}
}
};
int array_size = 4;//array size
int array_index = 0;// select index
int[][] array = new int[array_size][array_size];//selected array
Random ran = new Random();
int x = 9;//block X-coordinate
int y = 0;//block Y-coordinate
Color color = null;//block color
boolean flag = true;//rotate flag
void Rotate()//rotate
{
int[][] temp = new int[array_size][array_size];
switch(array_index)
{
case 0://OBlock No rotate
break;
case 1://L, J, TBlock 90ºrotate 4times
case 2:
case 3:
for(int i = 0; i < array_size; i++)
for(int j = 0; j < array_size; j++)
{
temp[j][i] = array[i][j];
array[i][j] = 0;
}
for(int i = 0; i < array_size; i++)
for(int j = 0; j < array_size; j++)
if(temp[i][j] == 1 && i < 2)
array[2+Math.abs(i-2)][j] = temp[i][j];
else if(temp[i][j] == 1)
array[2-Math.abs(i-2)][j] = temp[i][j];
break;
case 4://I, Z, SBlock 90ºrotate 2times
case 5:
case 6:
if(flag)//rotate check
{
for(int i = 0; i < array_size; i++)
for(int j = 0; j < array_size; j++)
{
temp[j][i] = array[i][j];
array[i][j] = 0;
}
for(int i = 0; i < array_size; i++)
for(int j = 0; j < array_size; j++)
if(temp[i][j] == 1 && i < 2)
array[2+Math.abs(i-2)][j] = temp[i][j];
else if(temp[i][j] == 1)
array[2-Math.abs(i-2)][j] = temp[i][j];
flag = false;
}
else
{
for(int i = 0; i < array_size; i++)
for(int j = 0; j < array_size; j++)
array[i][j] = block_array[array_index][i][j];
flag = true;
}
}
}
public Block()
{
// TODO Auto-generated constructor stub
array_index = ran.nextInt(7);
// array_index = *;//test(All *Block)
for(int i = 0; i < array_size; i++)
for(int j = 0; j < array_size; j++)//choice block
array[i][j] = block_array[array_index][i][j];
switch(array_index)
{
case 0://OBlock[0]
color = Color.blue;
break;
case 1://LBlock[1]
color = Color.magenta;
break;
case 2://JBlock[2]
color = Color.yellow;
break;
case 3://TBlock[3]
color = Color.green;
break;
case 4://IBlock[4]
color = Color.red;
break;
case 5://ZBlock[5]
color = Color.orange;
break;
case 6://SBlock[6]
color = Color.cyan;
break;
}
}
}Score
package Tetris;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Score extends JPanel
{
Block Pre_block = new Block();
int number = 0;
JPanel PrePanel = new JPanel();//block view
JLabel PreLabel = new JLabel("Pre Block");//block name
JLabel ScoreTitle = new JLabel("Score");
JLabel ScoreNumber = new JLabel(Integer.toString(number));//score view
JLabel[][] PL = new JLabel[Pre_block.array_size][Pre_block.array_size];//block
void Scoring(int size)
{
for(int i = 0; i < size; i++)//10 + bonus(line * 5);
number += 10;
number += size * 5;
ScoreNumber.setText(Integer.toString(number));
}
public Score()
{
// TODO Auto-generated constructor stub
setBackground(Color.lightGray);
setOpaque(true);
setLayout(null);
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
PreLabel.setBounds(15, 20, 80, 10);
ScoreTitle.setBounds(30, 150, 60, 10);
ScoreNumber.setBounds(40, 180, 60, 10);
PrePanel.setBounds(35, 40, 40, 40);
PrePanel.setBackground(Color.lightGray);
PrePanel.setOpaque(true);
PrePanel.setLayout(new GridLayout(4, 4, 1, 1));
for(int i = 0; i < Pre_block.array_size; i++)
for(int j = 0; j < Pre_block.array_size; j++)//block initialize
{
PL[i][j] = new JLabel();
if(Pre_block.array[i][j] == 1)
{
PL[i][j].setBackground(Pre_block.color);
PL[i][j].setOpaque(true);
}
PrePanel.add(PL[i][j]);
}
add(PreLabel);
add(PrePanel);
add(ScoreTitle);
add(ScoreNumber);
}
}| 첨부 | 파일 크기 |
|---|---|
| 16.13 KB |


스레드와 화면출력은 이런 방식으로 사용 할 수 있는거 같습니다.
synchronized(this) { int i; int size = snow.size(); for(i=0; i < size; i++) { Point p = snow.get(i); snow.remove(p); } }synchronized(this) 와 for() 문 2가지를 적용해야 오류가 나지 않았습니다.
스레드 오류를 수정하였습니다.
http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=1040201&docId=221054316&qb=ZXh0ZW5kcyBKRnJhbWUsIGV4dGVuZHMgVGhyZWFk&enc=utf8§ion=kin&rank=1&search_sort=0&spq=0
AWT-EventQueue-0
http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=1040201&docId=241836507&qb=SmF2YSByYW5k&enc=utf8§ion=kin&rank=1&search_sort=0&spq=0&pid=So2DcwoRR18ssvgjdQ0sssssss8-086974&sid=3ZSiXSWGS0A%2BSu/da7hOuA%3D%3D
http://blog.naver.com/robinnw/80211544638
http://blog.naver.com/kdw9242/70139152463
https://opentutorials.org/module/1335/8711
javac SnowThread.java java SnowThread -------------------------- import java.awt.*; import javax.swing.*; import java.util.*; import java.util.Random; import java.util.ArrayList; import java.util.Iterator; class SnowBallThread extends Thread { ArrayList<Point> snow;//눈을 저장할 변수 public SnowBallThread(ArrayList<Point> snow) { this.snow = snow; } public void run() { Random rand = new Random(); while (true) { try { synchronized(this) { Point point = new Point(rand.nextInt(500), 0);//눈생성 snow.add(point);//생성한 눈을 저장 } Thread.sleep(300); } catch (InterruptedException e) { System.out.println("SnowBallThread run"); return; } } } } class SnowThread extends JFrame { SnowBallThread th; BackPanel backGround; Random rand = new Random(); ArrayList<Point> snow = new ArrayList<Point>(); public SnowThread() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setTitle("SnowThread 예제"); backGround = new BackPanel(); setContentPane(backGround); setSize(500, 440); setLocation(200, 200); setVisible(true); backGround.requestFocus(); th = new SnowBallThread(snow);//눈을 생성하기 위해 snow를 스레드에 넣어줌 th.start(); Thread t = new Thread(backGround);//눈을 움직이기 위한 스레드 t.start(); } public class BackPanel extends JPanel implements Runnable { Image imgSample; public BackPanel() { setLayout(null); ImageIcon icon = new ImageIcon("image.png"); imgSample = icon.getImage(); } public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(imgSample, 0, 0, getWidth(), getHeight(), null); synchronized(this) { int i; int size = snow.size(); for(i=0; i<size; i++) { Point p = snow.get(i); g.setColor(Color.white);//하얀색으로 g.fillOval(p.x, p.y, 5, 5);//눈위치에 5크기로 그리기 } } } public void run() { while (true) { try { synchronized(this) { int i; int size = snow.size(); for(i=0; i<size; i++) { Point p = snow.get(i); p.x = rand.nextInt(500); p.y += 3; if (p.y > 440)//화면 밖으로 나가면 삭제 { snow.remove(i); break; } } } repaint();//화면 갱신 Thread.sleep(50); } catch (InterruptedException e) { System.out.println("SnowThread run"); return; } } } } public static void main(String[] args) { new SnowThread(); } }----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기