코딩캠프 1,2일차 정리

건희·2023년 1월 10일
0

생성일: 2023년 1월 11일 오전 12:18

2023.01.09 ~ 2023.01.12 코딩캠프

  • 그림판
  • 테트리스

그림판

  • GraphicEditor.java
  • EditorFrame.java
  • EditorPanel.java

총 3개의 java파일로 구성된 미니 프로젝트

  • GraphicEditor.java : JFrame객체를 만들어 실행하는 역할을 하는 파일
  • EditorFrame.java : JFrame 클래스를 구현해놓은 파일
  • EditorPanel.java : JFrameContentPane으로 설정해줄 JPanel 클래스를 구현해놓은 파일

EditorPanel 객체를 EditorFrame 객체의 ContentPane으로 설정해주면서 그림판 역할을 하게했다.

public class GraphicEditor {
	public static void main(String[] args) {
		EditorFrame editorframe=new EditorFrame();
	}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class EditorFrame extends JFrame{
	JMenuBar t=new JMenuBar();
	EditorPanel editorPanel=null;
	private String mode="";
	public EditorFrame() {
		super("도형편집기");
		setSize(800,800);  // 사이즈 지정
		setLocation(500,200);  // 위치 지정
		
		editorPanel=new EditorPanel(this);
		setContentPane(editorPanel);  //에디터 패널 컨텐트팬 지정
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //창을 닫았을 시 메인 스레드 종료
		makeToolbar(); //툴바를 생성해주는 메소드
		
		setVisible(true);
	}

	private void makeToolbar() { //도형 선택 , 도형 저장 기능 구현
		setJMenuBar(t);
		JMenu shapeMenu=new JMenu("도형 선택");
		JMenuItem circle=new JMenuItem("원");
		JMenuItem square=new JMenuItem("사각형");
		JMenuItem line=new JMenuItem("직선");
		
		JMenu saveMenu=new JMenu("도형 저장");
		JMenuItem save=new JMenuItem("저장");
		JMenuItem read=new JMenuItem("불러오기");
		saveMenu.add(save);
		shapeMenu.add(circle);
		shapeMenu.add(square);
		shapeMenu.add(line);
		t.add(shapeMenu);
		t.add(saveMenu);
		
		// JMenuItem EventListener 구현. 도형 그리기 시 EditorPanel 클래스의 도형그리기 메소드 가져와서 수행하도록 함.
		circle.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//editorPanel.drawCircle();  // Circle 그리는 메소드    ?? EditorPanel 클래스에서 사용할지 여기서 사용할지 정해야함
				mode="Circle";
			}
		});
		square.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//editorPanel.drawSquare(); // Square 그리는 메소드    ?? EditorPanel 클래스에서 사용할지 여기서 사용할지 정해야함
				mode="Square";
			}
		});
		line.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				editorPanel.drawLine(); // Line 그리는 메소드    ?? EditorPanel 클래스에서 사용할지 여기서 사용할지 정해야함
				mode="Line";
			}
		});
		save.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				editorPanel.saveVector();
			} //기능 구현 아직 하지 못함
		});
		/*read.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				editorPanel.readVector();
			}
		});*/
	}
	public String getMode() {
		return mode;
	}
}
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.Vector;
import javax.swing.JPanel;

public class EditorPanel extends JPanel{
	
	private Point p1; //사각형이나 원을 그리기 위한 마우스 위치
	private Point p2; //사각형이나 원을 그리기 위한 마우스 위치
	
	private Vector<Point> vector=new Vector<Point>(); //포인트 형식으로 . 선을 그릴때 사용한다.   //선 객체가 생성되는 것과 마찬가지고 , 이 벡터 객체를 따로 저장할 공간 필요.
	private Vector<Vector> lists=new Vector<Vector>(); // 선 저장
	private Vector<Square> squareLists=new Vector<Square>(); //사각형 좌표 객체 저장 , 벡터 컬렉션 내의 데이터는 Square class
	private Vector<Circle> circleLists=new Vector<Circle>(); //사각형 좌표 객체 저장 , 벡터 컬렉션 내의 데이터는 Circle class
	//벡터 바이너리파일로 저장.
	
	private String mode=""; //EditorFrame 에서 mode 가져오기
	private boolean count=false; //선 연결되는것 삭제 위함.
	
	public EditorPanel(EditorFrame editorFrame) {
		this.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				mode=editorFrame.getMode();           //마우스가 올려지는 순간 모드 가져오기
				if(mode=="Square" || mode=="Circle") { //원이나 사각형 모드일 경우에
					getMousePosition();
					p1=getMousePosition();
				}
			}
			@Override
			public void mouseReleased(MouseEvent e) {
				if(mode=="Line") {
					lists.add(vector);
					vector=new Vector<Point>();
					setCount();
				}
				else if(mode=="Square") {
					getMousePosition();
					p2=getMousePosition();
					squareLists.add(new Square(p1,p2)); //사각형 리스트에 저장
					repaint();
					revalidate();
				}
				else {
					getMousePosition();
					p2=getMousePosition();
					circleLists.add(new Circle(p1,p2)); //사각형 리스트에 저장
					repaint();
					revalidate();
				}
				
				
			}
		});
		this.addMouseMotionListener(new MouseMotionAdapter() {
			@Override
			public void mouseDragged(MouseEvent e) { //마우스 꾹 누를때 실행
				if(mode=="Line") drawLine(); // 선 그리는 함수 실행. 사실상 벡터에 포인트 추가하는 것.
			}
		});
	}
	//도형 그리는 메소드 구현
	//벡터 생성 후
    public void drawLine() { //if mode==Line
    	if(this.count==false) {
    		getMousePosition();
    		this.count=true;
    	}
    	else vector.add(getMousePosition()); //마우스의 위치를 벡터에 추가 
    	
    	repaint();
    	revalidate();   //컴포넌트 재배치 및 다시 그리기
	}
    public void setCount() {
    	this.count=false;
    }
    public void paintComponent(Graphics g) {  //그림판 초기화 시에 vector들 모두 초기화 해주어야 한다.
    	super.paintComponent(g);
    	
    	// 선 그려주기
		for(int i=1;i<vector.size();i++) {
			g.drawLine(vector.get(i-1).x, vector.get(i-1).y, vector.get(i).x,vector.get(i).y); //선 그리기
		}
		for(int j=0;j<lists.size();j++) { // Vector 저장하는 Vector lists , 즉 선들을 그린다.
			Vector<Point> v=lists.get(j);
			for(int i=1;i<v.size();i++) {
    			g.drawLine(v.get(i-1).x, v.get(i-1).y, v.get(i).x,v.get(i).y); //선 그리기
    		}
		}
		
		// 사각형 그려주기
		for(int i=0;i<squareLists.size();i++) {
			Point p1=squareLists.get(i).p1;
			Point p2=squareLists.get(i).p2;
			int width=p2.x-p1.x;
			int height=p2.y-p1.y;
			g.drawRect(p1.x, p1.y, width, height);
		}
    	//원 그려주기
		for(int i=0;i<circleLists.size();i++) {
			Point p1=circleLists.get(i).p1;
			Point p2=circleLists.get(i).p2;
			int width=p2.x-p1.x;
			int height=p2.y-p1.y;
			g.drawOval(p1.x, p1.y, width, height);
		}
    }
	/*public void saveVector() {
    	// 1. 스트림 생성
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(new File("C:/Users/keonh/OneDrive/Desktop/객체지향언어2/eclipse프로젝트/CodingCamp/test.bin")));
			// 2. 객체 스트림에 기록
			oos.writeObject(vector);
			oos.writeObject(lists);
			oos.writeObject(squareLists);
			oos.writeObject(circleLists);
			// 3. 스트림의 내용 분출
			oos.flush();
		} catch(Exception e){
			System.out.println("오류 발생");
    }
	}*/
}

class Square{
	Point p1;
	Point p2;
	public Square(Point p1,Point p2) {
		this.p1=p1;
		this.p2=p2;
	}
}
class Circle{
	Point p1;
	Point p2;
	public Circle(Point p1,Point p2) {
		this.p1=p1;
		this.p2=p2;
	}
}

EditorPanel.java파일 , 구현 시 컬렉션 객체에 저장되어있는 데이터들을 입출력을 구현하고 싶었는데 벡터 형식으로 저장되어있는 (선,원,사각형)을 나타내기 위한 Point 데이터를 저장하는 방식이 서로 다르기에 선 벡터 객체, 원 벡터 객체, 사각형 벡터 객체 각각 따로 저장을 하였는데 그 여러 벡터들을 저장은 할 수 있겠지만 나중에 데이터를 불러와야할 때, 즉 입력시에 어떻게 구분하여 각각의 벡터에 넣어주어야 할 지 생각을 하지 못했다.
이부분에 대해서는 파일입출력 공부를 따로 해야겠다고 느꼈다.
그리고 마우스의 위치를 Point 객체에 받는 것을 볼 수 있는데
그 부분을 잘 보면 getMousePosition() 메소드만 호출하여 마우스 위치를 나타내는 Point 객체를 버려주는 것을 확인할 수 있다.
이유는 getMousePosition() 메소드가 마우스리스너에서 사용된 마지막 마우스의 위치를 가지고 있기 때문에 , 한 번 버려준 뒤 다시 부르면 현재의 마우스 위치 Point 객체가 저장된다.
설명을 잘 하지 못해 아쉽다.

실행 결과는 아래와 같다.

원 선택 시

사각형 선택 시

직선(곡선) 선택 시


테트리스

  • TetrisMain.java
  • TetrisFrame.java
  • GamePanel.java
  • Block.java
  • BlockThread.java
  • KeyPanel.java
  • ScorePanel.java

총 7개의 java 파일로 구성된 미니프로젝트

  • TetrisMain.java : TetrisFrame 객체를 생성하여 프로젝트를 실행해준다.
  • TetrisFrame.java : TetrisFrame 클래스을 구현하였다.
  • GamePanel.java : 테트리스 게임이 진행되는 JPanel을 상속받은 패널로 , 각 객체(Block 객체)를 컬렉션에 add하고 객체의 좌표를 사용하여 GamePanel의 paintComponent 메소드에서 for(int i=0;i<blockVector.size();i++) 반복문을 돌며 그리게끔 구현해주었다.
  • Block.java : Block 객체의 필드 , 메소드를 정의해둔 클래스 파일. Block 객체를 GamePanel에 그릴 수 있게 하기위해 위치(x , y) 필드를 주어 좌표를 나타낼 수 있도록 했고 , color 필드로 Block 의 색을 표현할 수 있게 했다.
  • BlockThread.java : 필드에는 스레드의 run메소드를 돌며 Block 객체를 생성 후 바로 객체를 저장하기 위한 (GamePanel에서 받아올)Vector 객체의 인스턴스를 제외하고도 여러 필드를 선언해주었고 , 메소드로는 Block객체가 실제로 Y축으로 움직이게 해주는 blockMoveY() 메소드와 스레드를 돌아가게 해주는run() 메소드로 스레드를 구현하였다. 그 외의 메소드로는 속도 조절 메소드 , wait - notify 메소드등이 있다.
  • KeyPanel.java : 아직 구현은 안했지만 , 이 Panel 에는 방향키를 사용하지 못할 경우를 위해 방향키를 버튼으로 구현할까 생각중이다.
  • ScorePanel.java : 게임 진행 중 점수를 보여주며 , 일시정지 , 게임 재개 기능을 구현한 Panel

01/10 (화요일) 오전부터 시작하여 현재 진행중에 있는 미니 프로젝트다. 일반적인 테트리스와는 다르게 사각형 블럭 하나가 떨어지며 세개의 같은색 블록이 일자 , 대각선으로 있을 때 해당 3개 블록들을 삭제시키며 점수를 추가시키는 방식이다. 여기에 추가로 코딩을 더 진행한다면 , 중간중간 아이템을 가지고있는 블록들을 내려오게 하여 게임 중 여러 방식으로 점수를 획득할 수도 있겠다.

총 9시간정도 해당 미니프로젝트를 진행하였는데 , 알고리즘 구현 시 가장 힘들었던 부분은 블록이 세개가 모이며 사라지게 해주는 조건문을 작성할 때였다. 물론 현재 구현은 했지만 , 맘에 들지는 않는다.. 결국 좋지 못한 코드인 셈이다.

현재 어느정도 구현한 상태이다. 테트리스 코드는 미니 프로젝트를 완성시키고 난 뒤 올려보도록 하겠다.

코딩 잘하는 친구에게 조금의 조언을 받았는데 , Vector 컬렉션 객체에 저장되어있는 Block 객체에 마킹을 하는 식으로 진행하면 수월하게 구현될 것이라고 말을 해줬다. 이해한 바로는 DFS (깊이 우선 탐색) 알고리즘과 비슷하게 진행하면 될 것 같은데 , 빠르게 마무리하고 남은 코딩캠프 기간동안 다른 미니프로젝트도 진행해보기 위해 첫번째 방법을 택하게 됐다.

이상으로 포스팅을 마치도록 하겠다.

profile
💻 🍎

0개의 댓글