자바로 구현된 다양한 게임들이 많지만 아래의 소스 코드는 직접 구현된 코드들이라서 온라인 상에 다듬어진 코드와는 정리가 부족하다는 말씀 미리 드립니다. 7가지의 블럭(모양)을 구성하고 그 블럭들의 상태에따라 동작하는 이벤트 처리가 되는 방식입니다.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MultiClient extends JFrame implements KeyListener {
static int[][] state = new int[21][11];
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MultiClient extends JFrame implements KeyListener {
static int[][] state = new int[21][11];
/*
* state = 0 : 빈 공간
* state %2 == 1 : 멈춰져 있는 블럭
* state %2 == 0 && state != 20 : 움직이고 있는 (떨어지고 있는) 블럭
* state = 999 : 맨 밑의 줄 (떨어지는 블럭이 멈추게 하기 위함.)
*/
* state = 0 : 빈 공간
* state %2 == 1 : 멈춰져 있는 블럭
* state %2 == 0 && state != 20 : 움직이고 있는 (떨어지고 있는) 블럭
* state = 999 : 맨 밑의 줄 (떨어지는 블럭이 멈추게 하기 위함.)
*/
boolean isThreadEnd = false;// 쓰레드 작동이 끝났는지 (블럭이 떨어질수 있는 곳까지 떨어졌는지)
Blocks currentBlock; // 떨어지는 블럭의 정보
static boolean isGameOver; // 게임이 끝났는지 안 끝났는지
Image tetris_defaultblock_1 = new ImageIcon("TetrisDefaultBlock1.jpg").getImage(); // 블럭 이미지 1
Image tetris_defaultblock_2 = new ImageIcon("TetrisDefaultBlock2.jpg").getImage(); // 블럭 이미지 2
Image tetris_defaultblock_3 = new ImageIcon("TetrisDefaultBlock3.jpg").getImage(); // 블럭 이미지 3
Image tetris_defaultblock_4 = new ImageIcon("TetrisDefaultBlock4.jpg").getImage(); // 블럭 이미지 4
Image tetris_defaultblock_5 = new ImageIcon("TetrisDefaultBlock5.jpg").getImage(); // 블럭 이미지 5
Image tetris_defaultblock_6 = new ImageIcon("TetrisDefaultBlock6.jpg").getImage(); // 블럭 이미지 6
Image tetris_defaultblock_7 = new ImageIcon("TetrisDefaultBlock7.jpg").getImage(); // 블럭 이미지 7
Image tetris_BackGround = new ImageIcon("TetrisBackGround.jpg").getImage(); // 테트리스 배경
private Image offScreenImageDrawed = null;
private Graphics offScreenGraphicsDrawed = null;
public static void main(String[] args) {
new MultiClient();
}
Image tetris_defaultblock_2 = new ImageIcon("TetrisDefaultBlock2.jpg").getImage(); // 블럭 이미지 2
Image tetris_defaultblock_3 = new ImageIcon("TetrisDefaultBlock3.jpg").getImage(); // 블럭 이미지 3
Image tetris_defaultblock_4 = new ImageIcon("TetrisDefaultBlock4.jpg").getImage(); // 블럭 이미지 4
Image tetris_defaultblock_5 = new ImageIcon("TetrisDefaultBlock5.jpg").getImage(); // 블럭 이미지 5
Image tetris_defaultblock_6 = new ImageIcon("TetrisDefaultBlock6.jpg").getImage(); // 블럭 이미지 6
Image tetris_defaultblock_7 = new ImageIcon("TetrisDefaultBlock7.jpg").getImage(); // 블럭 이미지 7
Image tetris_BackGround = new ImageIcon("TetrisBackGround.jpg").getImage(); // 테트리스 배경
private Image offScreenImageDrawed = null;
private Graphics offScreenGraphicsDrawed = null;
public static void main(String[] args) {
new MultiClient();
}
public MultiClient() {
super("Tetris");
setSize(233, 485);
addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});
addKeyListener(this);
setResizable(false);
setBackground(Color.WHITE);
// 메뉴
MenuBar mb = new MenuBar();
Menu mOption = new Menu("기능");
MenuItem mQuit = new MenuItem("종료");
mQuit.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {System.exit(0);}});
mOption.add(mQuit);
mb.add(mOption);
setMenuBar(mb);
for(int i=0; i<21; i++)
for(int j=0; j<10; j++) {
if(i==20)
state[20][j]=999;
else
state[i][j]=0;
}
setVisible(true);
isThreadEnd = true;
while(true) {
if(isThreadEnd) {
isThreadEnd = false;
new Thread(new FallingBlockThread()).start();
}
}
}
public void paint(Graphics g) {
final Dimension d = getSize();
if(offScreenImageDrawed == null)
offScreenImageDrawed = createImage(d.width, d.height);
offScreenGraphicsDrawed = offScreenImageDrawed.getGraphics();
offScreenGraphicsDrawed.setColor(Color.WHITE);
offScreenGraphicsDrawed.fillRect(0, 0, d.width, d.height);
renderOffScreen(offScreenImageDrawed.getGraphics());
g.drawImage(offScreenImageDrawed, 0, 0, null);
}
public void renderOffScreen(final Graphics g) {
g.setColor(Color.black);
g.drawImage(tetris_BackGround, 0, 50, 230, 434, this);
for(int i=0; i<20; i++)
for(int j=0; j<10; j++) {
if(state[i][j]==1 || state[i][j]==2)
g.drawImage(tetris_defaultblock_1, 14+j*20, 67+i*20, 20, 20, this);
if(state[i][j]==3 || state[i][j]==4)
g.drawImage(tetris_defaultblock_2, 14+j*20, 67+i*20, 20, 20, this);
if(state[i][j]==5 || state[i][j]==6)
g.drawImage(tetris_defaultblock_3, 14+j*20, 67+i*20, 20, 20, this);
if(state[i][j]==7 || state[i][j]==8)
g.drawImage(tetris_defaultblock_4, 14+j*20, 67+i*20, 20, 20, this);
if(state[i][j]==9 || state[i][j]==10)
g.drawImage(tetris_defaultblock_5, 14+j*20, 67+i*20, 20, 20, this);
if(state[i][j]==11 || state[i][j]==12)
g.drawImage(tetris_defaultblock_6, 14+j*20, 67+i*20, 20, 20, this);
if(state[i][j]==13 || state[i][j]==14)
g.drawImage(tetris_defaultblock_7, 14+j*20, 67+i*20, 20, 20, this);
}
}
public void removeLine() {
ArrayList<Integer> v = new ArrayList<Integer>();
for(int i=19; i>=0; i--) {
int tmp = 0;
for(int j=0; j<10; j++)
if(state[i][j]%2==1) {
tmp++;
}
if(tmp==10) {
for(int j=0; j<10; j++)
state[i][j]=0;
v.add(i);
}
}
for(int k=0; k<v.size(); k++) {
for(int i=v.get(k); i>=0; i--)
for(int j=0; j<10; j++)
if(state[i+1][j]==0) {
state[i+1][j] = state[i][j];
state[i][j]=0;
}
}
}
public boolean isGameOver() {
boolean result = false;
for(int i=0; i<10; i++)
if(state[0][i]%2==1)
result = true;
return result;
}
public static void setGameOver() {
isGameOver = true;
JFrame game_over = new JFrame();
game_over.setSize(150, 100);
game_over.setLayout(null);
game_over.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});
JLabel l = new JLabel("Game Over!");
l.setBounds(25, 40, 100, 10);
game_over.add(l);
game_over.setResizable(false);
game_over.setVisible(true);
}
public Point getBlockPosition() {
int temp_Xpos=100, temp_Ypos=100;
for(int i=0; i<20; i++)
for(int j=0; j<10; j++)
if(state[i][j]!=0 && state[i][j]%2==0 && state[i][j]!=20 && state[i][j]!=20) {
if(temp_Xpos>i)
temp_Xpos=i;
if(temp_Ypos>j)
temp_Ypos=j;
}
return new Point(temp_Xpos, temp_Ypos);
}
public void set(boolean isRot) {
Point tmp = getBlockPosition();
int temp_Xpos = (int)tmp.getX();
int temp_Ypos = (int)tmp.getY();
int[][] block_Info = currentBlock.getBlockCodeInfo();
if(isRot) {
boolean isRotPoss = true;
try {
for(int i=0; i<4; i++)
for(int j=0; j<4; j++) {
if(block_Info[i][j]!=0 && state[temp_Xpos+i][temp_Ypos+j]%2==1)
isRotPoss = false;
}
} catch (ArrayIndexOutOfBoundsException e) {return;}
if(!isRotPoss)
return;
boolean tmp_Boolean = true;
try {
for(int i=0; i<4; i++)
for(int j=0; j<4; j++) {
if(!(state[temp_Xpos+i][temp_Ypos+j]==1 && block_Info[i][j]==0)) {}
}
} catch (ArrayIndexOutOfBoundsException e) {tmp_Boolean = false;} // 예외 발생 확인
if(tmp_Boolean) {
for(int i=0; i<4; i++)
for(int j=0; j<4; j++) {
if(!(state[temp_Xpos+i][temp_Ypos+j]%2==1 && block_Info[i][j]==0)) {
state[temp_Xpos+i][temp_Ypos+j]=block_Info[i][j];
}
}
}
} else {
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
if(block_Info[i][j]!=0)
state[i][j+3]=block_Info[i][j];
}
}
public void keyPressed(KeyEvent e) {
if(isGameOver)
return;
if(e.getKeyCode()==KeyEvent.VK_LEFT || e.getKeyCode()==KeyEvent.VK_A) { // <- 키를 눌렀을때
Vector<Point> v = new Vector<Point>();
for(int i=0; i<20; i++)
for(int j=0; j<10; j++) {
if(state[i][j]!=0 && state[i][j]%2==0 && state[i][j]!=20) {
if(j-1<0)
return;
Point tmp = getBlockPosition();
int tmpX = (int)tmp.getX();
int tmpY = (int)tmp.getY();
int[][] block_Info = currentBlock.getBlockCodeInfo();
for(int a=0; a<4; a++)
for(int b=0; b<4; b++) {
if(block_Info[a][b]!=0)
if(state[tmpX+a][tmpY+b-1]%2==1 && state[tmpX+a][tmpY+b-1]!=999)
return;
}
v.add(new Point(i, j));
}
}
for(int i=0; i<v.size(); i++) {
Point tmp = v.get(i);
state[(int)tmp.getX()][((int)tmp.getY())-1]=state[(int)tmp.getX()][(int)tmp.getY()];
state[(int)tmp.getX()][(int)tmp.getY()]=0;
}
repaint();
}
if(e.getKeyCode()==KeyEvent.VK_RIGHT || e.getKeyCode()==KeyEvent.VK_D) {
Vector<Point> v = new Vector<Point>();
for(int i=0; i<20; i++)
for(int j=9; j>=0; j--) {
if(state[i][j]!=0 && state[i][j]%2==0 && state[i][j]!=20) {
if(j+1>9)
return;
Point tmp = getBlockPosition();
int tmpX = (int)tmp.getX();
int tmpY = (int)tmp.getY();
int[][] block_Info = currentBlock.getBlockCodeInfo();
for(int a=0; a<4; a++)
for(int b=0; b<4; b++) {
if(block_Info[a][b]!=0 && state[tmpX+a][tmpY+b+1]%2==1 && state[tmpX+a][tmpY+b+1]!=999)
return;
}
v.add(new Point(i, j));
}
}
for(int i=0; i<v.size(); i++) {
Point tmp = v.get(i);
state[(int)tmp.getX()][((int)tmp.getY())+1]=state[(int)tmp.getX()][(int)tmp.getY()];
state[(int)tmp.getX()][(int)tmp.getY()]=0;
}
repaint();
}
if(e.getKeyCode()==KeyEvent.VK_DOWN || e.getKeyCode()==KeyEvent.VK_S) {
while(true) {
boolean temp_Bool = false;
for(int i=19; i>=0; i--) // 밑에서 부터 확인
for(int j=0; j<10; j++)
if((state[i+1][j]%2==1 || state[i+1][j]==20) && state[i][j]%2==0 && state[i][j]!=20 && state[i][j]!=0) // 떨어질 수 있는 끝까지 떨어졌을때
temp_Bool = true; // while(true) 문 종료
repaint();
if(temp_Bool)
break;
for(int i=19; i>=0; i--)
for(int j=0; j<10; j++)
if(state[i][j]!=0 && state[i][j]%2==0 && state[i][j]!=20) {
state[i+1][j]=state[i][j];
state[i][j]=0;
}
}
}
if(e.getKeyCode()==KeyEvent.VK_UP || e.getKeyCode()==KeyEvent.VK_W) {
currentBlock.rotateBlock();
set(true);
repaint();
}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
class FallingBlockThread extends Thread {
@Override
public void run() {
// 랜덤으로 블럭 소환
currentBlock = new Blocks();
set(false);
repaint();
// 떨구기
while(true) {
try {Thread.sleep(500);} catch (InterruptedException e) {}
boolean temp_Bool = false;
for(int i=19; i>=0; i--) // 밑에서 부터 확인
for(int j=0; j<10; j++)
if((state[i+1][j]%2==1 || state[i+1][j]==20) && state[i][j]%2==0 && state[i][j]!=20 && state[i][j]!=0 && state[i][j]!=20) { // 떨어질 수 있는 끝까지 떨어졌을때
temp_Bool = true; // while(true) 문 종료
}
repaint();
if(temp_Bool)
break;
for(int i=19; i>=0; i--)
for(int j=0; j<10; j++)
if(state[i][j]!=0 && state[i][j]%2==0 && state[i][j]!=20 && state[i][j]!=20) {
state[i+1][j]=state[i][j];
state[i][j]=0;
}
}
for(int i=0; i<20; i++)
for(int j=0; j<10; j++)
if(state[i][j]%2==0 && state[i][j]!=20 && state[i][j]!=0 && state[i][j]!=20)
state[i][j]-=1;
removeLine();
if(isGameOver())
setGameOver();
if(!isGameOver() && !isGameOver)
isThreadEnd = true;
}
}
}
'→ My Meta+IT > JAVA Source' 카테고리의 다른 글
자바 암호화 Security Provider 클래스 사용 방법 (0) | 2022.12.06 |
---|---|
Multi-threaded chatting Application in Java (0) | 2022.12.06 |
이클립스(eclipse IDE) 오라클 클라우드(Oracle cloud) ojdbc11.jar database 연결 접속 성공 (0) | 2022.07.08 |
알파 베타 가지치기/alpha-beta pruning (0) | 2022.02.09 |
MiniMax 미니맥스 알고리즘+JAVA 예제 코드 (0) | 2022.02.09 |
댓글