TIL #13 - 생성자 응용 프로그램
# 야구게임
야구게임 예제이다.
두 배열을 비교해 값과 위치 둘 다 같다면 스트라이크, 값은 같으나 위치가 다르면 볼을 출력한다.
삼진이 되면 프로그램은 종료한다.
사용자의 상대는 컴퓨터로 컴퓨터는 난수 3개가 들어있는 배열을 가지고 있다.
사용자는 직접 입력한다.
class BaseBall{
public static void main(String[] args) throws IOException{
Scanner scan = new Scanner(System.in);
int com[] = new int[3];
int user[] = new int[3];
내가 입력할 변수 choice와 스크라이크와 볼의 변수도 선언한다.
int choice;
int strike, ball;
삼진 (스트라이크 3)이 나올 때까지 입력이 계속 되어야하기 때문에 do-while문을 사용한다.
do{
}while(조건);
do에서 질문을 던지고 while문이 true가 되기 전까지 계속 돌아간다.
false인 경우 do-while을 나간다.
먼저 게임 실행 여부를 묻는다.
받을 입력은 y/n 인데 y/n 외에 다른 것이 입력되면 다시 질문을 한다.
do {
System.out.print("게임을 실행하겠습니까? (y/n)");
choice = System.in.read();
System.in.read();
System.in.read(); // 플러시 처리
딱 한글자를 입력받을 수 있는 System.in.read() 이다.
단, System.in.read()를 하면 콘솔창에 입력되는 값은 모두 아스키코드 값으로 입력받는다.
아스키코드는 전부 int이기 때문에 char 형태로 입력해도 결국 입력받는 것은 int 형이다.
또 System.in.read()는 예외처리를 해주어야한다. main메소드에 throw IOException 입출력 예외처리를 해준다.
밑의 두 read()는 \t,\n 에 따른 플러시 처리이다. (버퍼를 비워주는 과정)
do는 아래의 while문이 true가 될 때까지 계속해서 실행된다 (y/n 이외의 것이 입력되는 동안)
그렇다면 while이 true가 되는 조건은 사용자가 게임을 하겠다고 y를 입력하거나 게임을 하지 않겠다고 n을 입력한 것이다.
}while(choice!='Y' && choice!='y' && choice!='N'&& choice!='n');
만약 사용자가 게임을 하겠다고 한다면,
게임을 하기 앞서 컴퓨터의 배열에 난수 3개를 발생시켜야한다.
난수를 만들기 위해서는 중복도 체크해주어야한다.
if(choice=='Y' || choice=='y'){
//난수 발생
for (int i=0; i<com.length; i++) {
com[i] = (int)(Math.random() * 9) + 1;
//중복 체크
for (int k=0; k<i; k++) {
if (com[i] == com[k]) {
i--;
break;
}
}//for k
}//for i
그럼 본격적으로 게임으로 들어간다.
게임에서도 사용자가 삼진을 맞기 전까지 계속해서 숫자입력을 해야하기 때문에 while문을 사용한다.
그런 후 사용자에게 숫자 3개를 입력받는다.
for(int i=0; i<user.length; i++){
user[i] = System.in.read()-'0';
}//for i
여기서 사용자로부터 받은 배열의 요소들을 - '0' 해주는 것은
System.in.read()로 입력을 받을 시 문자로 입력을 받기 때문에 이것을 숫자로 바꿔주기 위해서이다.
숫자 0은 아스키코드가 0, 숫자 1은 아스키코드가 1
문자 '0'은 아스키코드가 48, 문자 '2'는 아스키코드가 49이다.
만약 문자 '0'에서 숫자 0으로 바꿔주고 싶다면 -48을 해주면 된다.
그렇기 때문에 위에서 입력받은 user 배열의 값들은 모두 System.in.read()로 입력받았으므로 문자열로 받은 꼴이 되는데
우리는 그것을 숫자로서 컴퓨터 배열과 비교해야하기 때문에 숫자로 바꾸어주어야한다.
그렇기 때문에 아스키코드가 48인 문자 '0'을 빼서 숫자로 바꾸어주는 것이다.
System.in.read();
System.in.read(); // 플러시 처리
strike = ball = 0;
for (int i = 0; i < com.length; i++) {
for (int k = 0; k < user.length; k++) {
if(com[i] == user[k]){
if(i == k) strike++;
else ball++;
}
}
}
사용자로부터 받은 문자를 숫자로 바꿔준후 플러시 처리로 엔터와 줄바꿈 버퍼를 없애준다.
그런 다음 strike와 ball을 0으로 초기화 시켜준다.
이 다음 for문 부터 배열을 비교해 strike와 ball을 더해줄 것이다.
먼저 제일 바깥 for문을 컴퓨터 배열의 길이만큼 돌림과 동시에
안쪽 for문에서는 사용자 배열의 길이만큼 돌린다.
그러면서 컴퓨터 배열의 요소와 사용자 배열의 요소가 같을 경우
배열의 위치까지 같으면 strike ++
컴퓨터 배열의 요소와 사용자 배열의 요소는 같지만 배열의 위치는 다른 경우엔 ball++
을 해준다.
System.out.println(strike + "스트라이크 " + ball + "볼");
if(strike == 3) {
System.out.println("삼진! 게임 끝 ");
break; // while문 나감
}
}//while
}
System.out.println("프로그램을 종료합니다");
}
}
배열이 한 번 돌았다면 게임 근황을 알려준다.
그러다 만약 strike가 3개가 되면 삼진임을 알려주고 while문에서 나간다.
# 전화번호 프로그램
전화번호 관리 프로그램이다.
사용자로부터 가입, 출력, 수정, 탈퇴, 끝의 메뉴를 보여주고 수행한다.
위의 메뉴들은 모두 메소드로 따로 분리시켰다.
(메소드로 따로 분리시키는 것이 나에겐 쉽지않았다.)
먼저 객체배열과 메소드들이 들어있는 MemberMain 클래스와 필드와 생성자들이 들어있는 MemberDTO 클래스 두개로 나누었다.
먼저 MemberDTO 클래스이다.
class MemberDTO {
private String name;
private int age;
private String phone, address;
우리가 다룰 데이터들은 위와 같이 이름, 나이, 핸드폰번호, 주소이다.
그런 후 생성자를 만든다.
public MemberDTO() {}
public MemberDTO(String name, int age, String phone, String address) {
this.name = name;
this.age = age;
this.phone = phone;
this.address = address;
}
생성자는 아무것도 없는 디폴트생성자 하나,
값들을 초기화시켜주는 생성자 하나이다.
값들을 받아주는 생성자가 하나 있음에도 만약을 대비해 setter 메소드도 만들어 둔다.
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void setPhone(String phone){
this.phone = phone;
}
public void setAddress(String address){
this.address = address;
}
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}
setter가 있으면 getter도 만들어준다.
이로써 MemberDTO는 끝이다.
다음은 메소드들이 있는 MemberMain 클래스이다.
먼저 5명의 정보만 넣을 것이기 때문에 크기 5의 객체 배열을 만든다
import java.util.Scanner;
class MemberMain {
Scanner scan = new Scanner(System.in);
MemberDTO[] ar = new MemberDTO[5];
그런 후 사용자에게 보여줄 메뉴 메소드이다.
public void menu(){
int choice;
while(true){
System.out.println();
System.out.println("************");
System.out.println(" 1. 가입");
System.out.println(" 2. 출력");
System.out.println(" 3. 수정");
System.out.println(" 4. 탈퇴");
System.out.println(" 5. 끝");
System.out.println("************");
System.out.print(" 번호 : ");
choice = scan.nextInt();
if(choice == 5) break;
if(choice == 1) this.insert();
else if(choice == 2) list();
else if(choice == 3) update();
else if(choice == 4) delete();
else System.out.println("1 ~ 5번 숫자만 입력하세요");
}//while
}
먼저 5를 입력받은 경우 while문을 나가게 설정한 뒤에
1부터 4까지 입력시 수행할 메소드들을 넣는다.
그런 후 1~5 외에 다른 숫자가 입력될 시 경고 메세지를 띄운다.
아래의 메소드들은 1~5 각 숫자에 따라 수행될 메소드들이다.
정보를 넣는 insert()
public void insert(){
System.out.println();
int i;
for(i=0; i<ar.length; i++){
if(ar[i] == null){
ar[i] = new MemberDTO();
System.out.print("이름 : ");
ar[i].setName(scan.next());
System.out.print("나이 : ");
ar[i].setAge(scan.nextInt());
System.out.print("전화번호 : ");
ar[i].setPhone(scan.next());
System.out.print("주소 : ");
ar[i].setAddress(scan.next());
break;
}
}//for
insert에서는 먼저 배열의 길이 만큼 배열에 null이 있는지 검사 한 후
null이 있으면 데이터가 들어갈 자리가 있다는 의미이므로 사용자로부터 데이터를 입력받는다.
if(i==ar.length){
System.out.println("5명의 정원이 꽉 찼습니다");
return; //메소드를 벗어나라
}
그런데 만약, index가 배열의 끝까지 도달하면 null이 없어서 멈추지 못했다는 뜻이므로
정원초과 메세지를 띄우며 return을 통해 insert 메서드에서 빠져나온다
(메서드에서 빠져나오기 위해서는 return을 쓴다)
int count=0;
for(i=0; i<ar.length; i++){
if(ar[i] == null) count++;
}
System.out.println("1 row created");
System.out.println(count+"자리 남았습니다");
}
그런 후 자리가 몇개 남았는지 보여주기 위해 다시 null을 검사해 null 값만큼 count를 더해주어
출력해준다.
데이터 리스트를 보여주는 list()
public void list(){
System.out.println();
System.out.println("이름\t나이\t핸드폰\t\t주소");
for(MemberDTO data : ar){
if(data != null){
System.out.println(data.getName()+"\t"
+ data.getAge()+"\t"
+ data.getPhone()+"\t"
+ data.getAddress());
}
}
}
list 메서드는 확장형 for문을 이용해서 한번에 출력한다.
단, name, age, phone, address 모두 private 필드이기 때문에 getter 메소드를 이용해서 불러올 수 있다.
또한 data가 null이 아닌 경우에 출력을 한다.
데이터를 수정하는 update()
현재 데이터에는 id값을 두지 않았기 때문에 유일하게 중복이 없는 값은 휴대폰 번호이다.
따라서 수정할 데이터를 휴대폰 번호로 찾는다.
public void update(){
System.out.println();
System.out.print("핸드폰 번호 입력 : ");
String phone = scan.next();
int i;
for(i=0; i<ar.length; i++){
if(ar[i] != null){
if(ar[i].getPhone().equals(phone)){
System.out.println(ar[i].getName()+"\t"
+ ar[i].getAge()+"\t"
+ ar[i].getPhone()+"\t"
+ ar[i].getAddress());
사용자에게 핸드폰 번호를 입력받고
null이 아니고 입력받은 핸드폰 번호와 가지고 있는 핸드폰 번호를 비교해 똑같으면 해당 행의 데이터를 getter 메소드로 가져와 출력한다.
//수정
System.out.println();
System.out.print("수정할 이름 입력 : ");
ar[i].setName(scan.next());
System.out.print("전화번호 : ");
ar[i].setPhone(scan.next());
System.out.print("주소 : ");
ar[i].setAddress(scan.next());
System.out.println("1 row(s) updated");
break;
}
}
}//for
그리고 다른 것 없이 그 위에다 setter 메소드를 통해 새로운 데이터를 입력받아 수정한다.
if(i==ar.length)
System.out.println("찾는 회원이 없습니다");
}
그런데 만약 i가 위의 코드들을 수행치 않고 배열의 끝까지 도달한다면 해당되는 번호가 없다는 의미이므로 그에 따른 메세지를 띄운다.
마지막으로 데이터를 삭제하는 delete()
delete도 역시 핸드폰 번호를 기준으로 찾는다.
그리고 찾은 번호에 해당되는 행을 전부 null로 바꾼다.
public void delete(){
System.out.println();
System.out.print("핸드폰 번호 입력 : ");
String phone = scan.next();
int i;
for(i=0; i<ar.length; i++){
if(ar[i] != null){
if(ar[i].getPhone().equals(phone)){
ar[i] = null;
System.out.println("1 row(s) deleted");
break;
}
}
}//for
if(i==ar.length)
System.out.println("찾는 회원이 없습니다");
}
메인 메소드에는 static이 없는 메소드를 불러오기 위해 MemberMain 객체를 생성해
메소드에게 위치를 알려주어 불러온다.
public static void main(String[] args) {
MemberMain main = new MemberMain();
main.menu();
System.out.println("프로그램을 종료합니다");
}