본문 바로가기

JAVA/공부

13. 스레드와 멀티태스킹

7, 스네이크(뱀) 게임에 사용되는 움직이는 스네이크를 만들어보자. 그림과 같이 프레임의 배경에 이미지를 출력한다. 스네이크는 총 10개의 마디로 구성하고 상, 하, 좌, 우키에 의해 움직인다. 스네이크는 200ms마다 5픽셀씩 자동으로 움직인다.

 

5픽셀씩 움직이라지만 한 마디의 크기만큼 움직이는게 맞는듯하다. 아니면 마디 크기를 줄이자.

 

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

public class seven extends JFrame{
	private MyPanel panel=new MyPanel();

	public seven() {
		setTitle("스네이크 움직이기");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c=getContentPane();
		c.addKeyListener(new MyKeyListener());
			
		c.add(panel);
		
		c.setFocusable(true);
//		panel.requestFocus();
		setSize(1000,800);
		setVisible(true);
	}
	class MyPanel extends JPanel implements Runnable{
		private JLabel testLabel;
		private String direction="up";
		private ImageIcon icon=new ImageIcon("images/26.jpg");
		private Image img=icon.getImage();
		private ImageIcon icon1=new ImageIcon("images/head.jpg");
		private Image img1=icon1.getImage();
		private Image smallImg1=img1.getScaledInstance(35, 35, Image.SCALE_SMOOTH);
		private ImageIcon smallIcon1=new ImageIcon(smallImg1);
		private ImageIcon icon2=new ImageIcon("images/body.png");
		private Image img2=icon2.getImage();
		private Image smallImg2=img2.getScaledInstance(35, 35, Image.SCALE_SMOOTH);
		private ImageIcon smallIcon2=new ImageIcon(smallImg2);
		private JLabel []label=new JLabel[10];
		private Vector <Point> v=new Vector<Point>();
		public MyPanel() {
			setLayout(null);
			snake();
			Thread th=new Thread(this);
			th.start();
		}
		public void snake() {
			label[0]=new JLabel(smallIcon1);
			label[0].setSize(35,35);
			label[0].setPreferredSize(new Dimension(100,100));
			label[0].setLocation(100,100);
			add(label[0]);
			for(int i=1;i<label.length;i++) {
				label[i]=new JLabel();
				label[i].setIcon(smallIcon2);
				label[i].setSize(35,35);
				label[i].setLocation(100,100+35*i);
				add(label[i]);
			}
		}
		public void setDirection(int keyCode) {
			switch(keyCode) {
			case 38: direction="up";break;
			case 40: direction="down";break;
			case 37: direction="left";break;
			case 39: direction="right";
			}
		}
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(img, 0, 0, getWidth(), getHeight(), 0, 0, 1920, 1080, this);
		}
		public void run() {
			while(true) {
			try {
				v.removeAllElements();
				for(int i=0;i<label.length;i++) {
					v.add(label[i].getLocation());
				}
				int x=label[0].getX();
				int y=label[0].getY();
				switch(direction) {
				case"up":y-=35;label[0].setLocation(x,y);
				for(int i=1;i<label.length;i++) {
					int x1=v.get(i-1).x;
					int y1=v.get(i-1).y;
					label[i].setLocation(x1,y1);
				}
				break;
				case"down":y+=35;label[0].setLocation(x,y);
				for(int i=1;i<label.length;i++) {
					int x1=v.get(i-1).x;
					int y1=v.get(i-1).y;
					label[i].setLocation(x1,y1);
				}
				break;
				case"left":x-=35;label[0].setLocation(x,y);
				for(int i=1;i<label.length;i++) {
					int x1=v.get(i-1).x;
					int y1=v.get(i-1).y;
					label[i].setLocation(x1,y1);
				}
				break;
				case"right":x+=35;label[0].setLocation(x,y);
				for(int i=1;i<label.length;i++) {
					int x1=v.get(i-1).x;
					int y1=v.get(i-1).y;
					label[i].setLocation(x1,y1);
				}
				}
				Thread.sleep(200);
			}catch(InterruptedException e) {return;}
		}}
		}
	class MyKeyListener extends KeyAdapter{
		public void keyPressed(KeyEvent e) {
			panel.setDirection(e.getKeyCode());
		}
	}
	public static void main(String[]args) {
		new seven();
	}
}

 

 

 

8. 스레드를 이용하여 아래와 같이 화면에 눈이 내리도록 연출하라. 화면의 바탕 이미지는 독자가 좋은 것으로 선택하면 된다.

 

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

public class eight extends JFrame{
	private MyPanel panel=new MyPanel();
	public eight() {
		setTitle("눈 내리는 이미지");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		setContentPane(panel);
		
		setLocation(880,420);
		setSize(800,600);
		setVisible(true);
	}
	Vector <Point> v=new Vector<Point>();
	public void setPosition() {
		for(int i=0;i<50;i++) {
		int x=(int)(Math.random()*800);
		int y=(int)(Math.random()*600);
		v.add(new Point(x,y));
		}
	}
	class MyPanel extends JPanel implements Runnable{
		private ImageIcon icon=new ImageIcon("images/12.jpg");
		private Image img=icon.getImage();
		private Vector <Point> v=new Vector<Point>();
		public MyPanel() {
			Thread th=new Thread(this);
			th.start();
		}
		public void snow() {
			for(int i=0;i<80;i++) {
			int x=(int)(Math.random()*800);
			int y=(int)(Math.random()*600);
			v.add(new Point(x,y));
			}
		}
		public void snowFall() {
			for(int i=0;i<80;i++) {
				int tmpx=v.get(i).x;
				int tmpy=v.get(i).y;
				if(tmpy>600) {
					tmpx=(int)(Math.random()*800);
					tmpy=0;
				}
				else
					tmpy+=5;
				v.remove(i);
				v.add(i,new Point(tmpx,tmpy));
			}
		}
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(img, 0, 0, getWidth(), getHeight(), 0, 0, 1920, 1080, this);
			g.setColor(Color.white);
			snow();
			for(int i=0;i<80;i++) {
				Point p=v.get(i);
				g.fillOval(p.x, p.y, 10, 10);
			}
			}
		public void run() {
			while(true) {
				try {
					Thread.sleep(150);
					snowFall();
					repaint();
				}catch(InterruptedException e) {return;}
			}
		}
		}
	public static void main(String[]args) {
		new eight();
}
}

 

 

 

9. 10장의 Open Challenge 겜블링 게임에 스레드를 달아보자. 아래 그림과 같이 3개의 레이블 컴포넌트가 있다. 이 컴포넌트에는 0~4까지의 한 자릿수가 출력된다. 패널에 마우스를 누를 때마다 3개의 수를 랜덤하게 발생시키고 각 수를 레이블에 출력한다. 이때 스레드를 이용하여 3개의 수를 왼쪽에서부터 200ms 간격으로 하나씩 출력한다. 그러고 나서 모두 동일한 수인지 판단하고 동일하면 "축하합니다!!"를, 아니면 "아쉽군요"를 출력한다.

 

경우의수가 너무 많아서 3개(0,1,2)로 줄임

 

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

public class nine extends JFrame{				//프레임
	private MyPanel panel=new MyPanel();
	public nine() {
		setTitle("스레드를 가진 겜블링");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocation(880,420);//Frame 화면중앙에 설정
		
		setContentPane(panel);
		
		setSize(600,400);
		setVisible(true);
	}
	class MyPanel extends JPanel implements Runnable{
		private JLabel []label=new JLabel[3];
		private int []random=new int[3];
		private boolean flag=false;
		private JLabel text;
		public MyPanel() {							//패널
			setLayout(null);
			setLabel();
			addMouseListener(new MyMouseListener());
			
			
			Thread th=new Thread(this);
			th.start();
		}
		synchronized public void start() {			//시작
			flag=true;
			this.notify();
		}
		synchronized public void waitForStart() {	//대기
			if(!flag)
				try {this.wait();}catch(InterruptedException e) {return;}
		}
		public void run() {							//쓰레드
			while(true) {
				waitForStart();
			try {for(int i=0;i<3;i++) {
				int tmp=(int)(Math.random()*3);		//경우의수가 너무 많아서 3개(0,1,2)로 줄임
				label[i].setText(Integer.toString(tmp));
				Thread.sleep(200);}
				if(label[0].getText().equals(label[1].getText())&&label[1].getText().equals(label[2].getText()))
					text.setText("축하합니다!!");
				else
					text.setText("아쉽군요");
				flag=false;}
			catch(InterruptedException e) {return;}
		}}
		public void setLabel() {					//라벨 생성
			for(int i=0;i<label.length;i++) {
				label[i]=new JLabel("0");
				label[i].setSize(120,100);
				label[i].setHorizontalAlignment(JLabel.CENTER);
				label[i].setFont(new Font("Serif",Font.BOLD,100));
				label[i].setLocation(60+180*i,50);
				label[i].setForeground(Color.yellow);
				label[i].setBackground(Color.magenta);
				label[i].setOpaque(true);
				add(label[i]);
			}
			text=new JLabel("마우스를 클릭할 때 마다 게임합니다.");
			text.setSize(400,100);
			text.setHorizontalAlignment(JLabel.CENTER);
			text.setForeground(Color.black);
			text.setFont(new Font("Serif",Font.BOLD,20));
			text.setLocation(100,200);
			add(text);
		}
	}
	class MyMouseListener extends MouseAdapter{		//리스너 구현
		public void mouseClicked(MouseEvent e) {
			panel.start();
		}
	}
	public static void main(String[]args) {
		new nine();
	}
}

 

 

 

10. 다음 설명과 같이 작동하는 스윙 프로그램을 작성하라. 패널에 사용자가 마우스를 올리면 랜덤한 크기와 위치에 타원 그리기가 시작된다. 타원은 300ms 간격으로 다른 위치로 옮기면서 그려진다. 사용자가 마우스를 패널에서 내리면 타원 그리기는 일시 멈추고, 다시 마우스를 올리면 그리기가 계속된다. 이문제를 풀기 위해서 wait-notify를 사용하는 것이 좋다.

 

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

public class ten extends JFrame{
	private MyPanel panel=new MyPanel();
	public ten() {
		setTitle("Make Drawing to start");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		setContentPane(panel);
		setLocation(880,420);
		
		setSize(500,500);
		setVisible(true);
	}
	class MyPanel extends JPanel implements Runnable{
		private boolean flag=false;
		private Graphics g;
		private int []size=new int[4];
		MyPanel(){
			addMouseListener(new MouseAdapter() {
				public void mouseEntered(MouseEvent e) {
					panel.On();
				}
				public void mouseExited(MouseEvent e) {
					flag=false;
				}
			});
			
			Thread th=new Thread(this);
			th.start();
		}
		public void draw(Graphics g,int x,int y,int width,int height) {
			g.fillOval(x,y,width,height);
		}
		synchronized public void On() {
			flag=true;
			this.notify();
		}
		synchronized public void Wait() {
			if(!flag)
				try {this.wait();}catch(InterruptedException e) {return;}
		}
		public void run() {
			while(true) {
				Wait();
				try {
					for(int i=0;i<size.length;i++) {
						size[i]=(int)(Math.random()*400+1);
					}
					repaint();
					Thread.sleep(300);
				}catch(InterruptedException e) {return;}
			}
		}
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.setColor(Color.magenta);
			draw(g,size[0],size[1],size[2],size[3]);
		}
	}
	public static void main(String[]args) {
		new ten();
	}
}

 

 

 

11. 산성비 게임을 만들어보자. 스레드를 만들고 단어를 가진 레이블을 200ms마다 5픽셀씩 아래로 떨어지게 하라. 텍스트필드 창을 하나 만들고 이곳에서 떨어지는 단어를 입력하고 <Enter> 키를 입력하면 떨어지는 단어와 일치하는지 확인하라. 일치하면 성공 메세지를 출력하고 다시 새로운 단어를 선택하고 처음 위치에서 떨어지게 하라. 입력창에 "그만"을 입력하면 프로그램을 종료하라. 점수 관리는 없다. 단어 파일은 words.txt 파일을 이용하라. 프로그램이 시작하는 처음에 words.txt 를 읽어 벡터에 넣어두면 된다. words.txt 파일에는 한 라인에 한개의 영어 단어가 들어있다. words.txt파일을 읽고 벡터를 삽입하는 코드는 OpenChallenge 8장을 참고하라.

 

너무 느려서 10픽셀로 바꿈

 

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

public class eleven extends JFrame{
	private MyPanel panel=new MyPanel();
	private JPanel jp;
	private JTextField jt;
	private JLabel jl1,jl2;
	private Vector <String> v=new Vector<String>();
	public eleven() {
		setTitle("떨어지는 단어 맞추기");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		panel.getWord();
		
		setLocation(880,420);
		Container c=getContentPane();
		c.setLayout(new BorderLayout());
		
		jt=new JTextField(10);
		jt.addActionListener(new MyActionListener());
		jp=new JPanel();
		jp.setBackground(Color.LIGHT_GRAY);
		jp.add(jt);
		c.add(jp,BorderLayout.SOUTH);
		c.add(panel,BorderLayout.CENTER);
		jl2.setText(v.get((int)(Math.random()*25142)));

		setSize(300,400);
		setVisible(true);
	}
class MyPanel extends JPanel implements Runnable{
	public MyPanel() {
		setLayout(null);
		jl1=new JLabel();
		jl1.setFont(new Font("Serif",Font.BOLD,18));
		jl1.setSize(120,20);
		jl1.setLocation(10,10);
		add(jl1);
		jl2=new JLabel("test");
		
		jl2=new JLabel();
		jl2.setFont(new Font("Serif",Font.BOLD,35));
		jl2.setSize(400,50);
		jl2.setForeground(Color.magenta);
		jl2.setLocation((int)(Math.random()*400/2),0);
		add(jl2);
		
		Thread th=new Thread(this);
		th.start();
	}
	public void run() {
		while(true) {
			try {
				Point p=jl2.getLocation();
				jl2.setLocation(p.x,p.y+10);//너무 느려서 10픽셀로 바꿈
				Thread.sleep(200);
				if(p.y>panel.getHeight()-15)
					{jl1.setText("시간초과실패");jl2.setText(v.get((int)(Math.random()*25142)));
					jl2.setLocation((int)(Math.random()*panel.getWidth()/2),0);}
			}catch(InterruptedException e) {return;}
		}
	}
	public void getWord() {
		try {FileReader fin=new FileReader("words.txt");//단어 25143개
		BufferedReader bf=new BufferedReader(fin);
		String line="";
		while((line=bf.readLine())!=null) {
			v.add(line);
		}}catch(IOException e) {System.out.println("파일이 없습니다.");};
	}
}
class MyActionListener implements ActionListener{
	public void actionPerformed(ActionEvent e) {
		if(jt.getText().equals(jl2.getText()))
			{jl1.setText("성공");
			jl2.setText(v.get((int)(Math.random()*25142)));
			jl2.setLocation((int)(Math.random()*panel.getWidth()/2),0);
			}
		if(jt.getText().equals("그만"))
			System.exit(0);//종료
		jt.setText("");
	}
}
	public static void main(String[]args) {
		new eleven();
	}
}

 

"그만"을 입력하여 종료

'JAVA > 공부' 카테고리의 다른 글

15. 네트워크  (0) 2021.02.24
14. 고급 스윙 컴포넌트  (0) 2021.02.15
12. 그래픽  (0) 2021.01.28
11. 기본적인 스윙 컴포넌트와 활용  (0) 2021.01.23
10. 자바의 이벤트 처리  (0) 2021.01.19