안드로이드 1to50 어플을 만들어보자 3편

진의님의 댓글을 참고하여 2차 수정된 내용입니다.


어느새 1to50 만들기 포스팅이 3편까지 진행이 되었네요.

[Android Study] - 안드로이드 1to50 어플을 만들어 보자 1편

[Android Study] - 안드로이드 1to50 어플을 만들어 보자 2편

이번 3편은 java코딩을 작성하는 포스팅으로 진행이 됩니다.


저는 코딩은 퍼즐조각을 맞추는것과 비슷하다고 생각을 합니다.

작동되는 하나하나가 퍼즐조각이고 그걸 하나로 맞춰주면 어플이 완성이 된다고 생각을 하거든요.


그러면 1to50의 퍼즐조각은 어떤것이 있는지 생각을 해봅시다.

1. 어플이 실행되면 바로 25개의 칸에 숫자가 보여져야 합니다.

2. 칸을 하나씩 클릭하면 위쪽에 클릭해야 하는 숫자를 출력해 줍니다.

3. 50까지 다 터치를 해야 합니다.

4. 50까지 다 터치를 하고나면 성공 화면이 보여져야 합니다.

5. 성공 화면에 확인을 누르면 1번이 다시 실행됩니다.

퍼즐조각은 5개네요. 


퍼즐조각을 하나씩 만들어봅시다.

1. 어플이 실행되면 바로 25개의 칸에 숫자가 보여져야 합니다.

int number_group1, number_group2;
private void game() {
now_number.setText(Integer.toString(match_number_int));
for(number_group1 = 1; number_group1 <= 2; number_group1++) {
for(number_group2 = 1; number_group2 <= 25; number_group2++) {
random();
}
}
for(int print_button_num = 0; print_button_num <= 24; print_button_num++) {
button_text[print_button_num].setText(Integer.toString(button_number_01[print_button_num]));
}
}

for문으로 25번씩 2번 출력을 하도록 작성해줍니다.

now_number.setText(Integer.toString(Match_number_int));는 현재 입력해야 하는 숫자를

어플을 실행하면 바로 출력을 해주기 위해서 작성해 두었습니다.

random();이 숫자를 뽑아줍니다. 

자세한 코드는 아래쪽에 작성하도록 하겠습니다.

number_group의 for문이 종료가 되면 25개의 버튼에 1~25의 숫자가 출력이 되도록 for문을 작성하였습니다.

int match_number_int = 1;
int random_button_number_int;
int[] button_number_01 = new int[25];
int[] button_number_02 = new int[25];
private void random() {
Random random = new Random();
random_button_number_int = random.nextInt(25);
if(number_group1 == 1 && button_number_01[(random_button_number_int)] == 0) {
button_number_01[(random_button_number_int)] = number_group2;
}else if(number_group1 == 1 && number_group2 <= 25){
random();
}
if(number_group1 == 2 && button_number_02[(random_button_number_int)] == 0) {
button_number_02[(random_button_number_int)] = (number_group2+25);
}else if(number_group1 == 2 && number_group2 <= 25){
random();
}
}

숫자를 뽑아주는 random()의 코드입니다.

int match_number_int = 1;이 현재 클릭해야 하는 숫자 int값입니다.

자세한 코드는 아래쪽에 설명이 되겠지만 1로 설정을 해주셔야 실행하면 출력이 1로 바로 나옵니다.

random_button_number_int에 랜덤으로 뽑힌 숫자를 저장합니다.

button_number_01이랑 button_number_02는 버튼 25개에 숫자가 2개가(1~15, 26~50)

저장이 되어야 하기에 01과 02로 나누어주었습니다.

예를들어 랜덤으로 4라는 숫자가 뽑히면 button_number_01[4]라는 int값에

현재 for문에서 진행중인 number_group2의 숫자가 저장이 됩니다.

만약에 button_number_01[4]의 int값에 이미 숫자가 저장이 되어있다면

random() 다시 호출해서 저장이 안되어 있는 button_number_01를 찾아서 저장이 될 때까지 실행이 됩니다.

아래쪽 if문에 +25가 되어있는 이유는 25 이후의 숫자인 26~50의 숫자로 만들기 위해서 +25를 해두고 있습니다.


여기까지의 코드를 작성하시면 1번 퍼즐조각이 만들어집니다.

스마트폰에 실행을 시켜보면 아래 이미지와 같이 보여집니다.

아직 버튼을 클릭했을때의 동작은 만들지 않았기 때문에 1부터 25까지 숫자가 출력되는게 전부입니다.


2. 칸을 하나씩 클릭하면 위쪽에 현재 클릭해야 하는 숫자를 출력해 줍니다.

match_number_int += 1;
now_number.setText(Integer.toString(match_number_int));

위에 코드는 0부터 24까지의 버튼에 모두 작성이 되어야 합니다.

match_number_int에 숫자를 1씩 올라가게 저장하고

저장된 값을 출력해주고 있습니다.


3. 50까지 다 터치를 해야 합니다.

버튼을 터치했을때 number_group2의 숫자가 출력이 되어야 게임이 진행이 가능하겠죠.

int number = 0;
if(match_number_int == button_number_01[number]) {
button_text[number].setText(Integer.toString(button_number_02[number]));
}
if(match_number_int == button_number_02[number]) {
button_text[number].setVisibility(View.GONE);
}

위에 코드를 0부터 24까지의 버튼에 모두 작성이 되어야 합니다.

그런데 int number = 0;은 버튼에 맞는 숫자로 변경을 해주세요. 6번 버튼에는 6으로 입력을 해주셔야 합니다.

현재 클릭해야 하는 숫자와 버튼에 저장되어 있는 1그룹의 숫자가 맞으면 2그룹의 숫자가 출력이 되도록 작성하였습니다.

그리고 현재 클릭해야 하는 숫자와 2그룹의 숫자가 맞으면 버튼에 텍스트뷰가 숨겨지게 작성하였습니다.


4. 50까지 다 터치를 하고나면 성공 화면이 보여져야 합니다.

if(match_number_int == 50) {
include[1].setVisibility(View.VISIBLE);
include[0].setVisibility(View.GONE);
}

위에 코드도 0부터 24까지의 버튼에 모두 작성이 되어야 합니다.

버튼을 클릭했을때 50의 숫자라면 성공화면이 보여지고 게임화면이 숨겨지도록 하고 있습니다.

5. 성공 화면에 확인을 누르면 1번이 다시 실행됩니다.

match_number_int = 1;
for(int reset_button_number = 0; reset_button_number <= 24; reset_button_number++) {
button_number_01[reset_button_number] = 0;
button_number_02[reset_button_number] = 0;
button_text[reset_button_number].setVisibility(View.VISIBLE);
}
include[0].setVisibility(View.VISIBLE);
include[1].setVisibility(View.GONE);
game();

확인 버튼에 작성되어야 하는 코드입니다.

확인을 누르면 int값을 초기화 해줘야 게임을 처음부터 시작이 가능하겠죠.

그룹01이랑 02에 저장된 숫자를 0으로 초기화를 해주고 각 버튼에 숨김처리된 텍스트뷰를 다시 보여지게 만들어 줘야 합니다.

확인을 눌렀으니 성공화면을 숨겨지게 하고 게임화면을 보여지게 해줘야겠죠.

또 각 버튼에 숫자를 다시 출력해 주도록 game();도 작성되어 있습니다.


이렇게 5개의 퍼즐조각이 모두 작성이 되었습니다.

for (int i = 0; i < 25; i++) {
final int j = i;
button[j].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(match_number_int == 50) {
include[1].setVisibility(View.VISIBLE);
include[0].setVisibility(View.GONE);
}
int number = j;
if(match_number_int == button_number_01[number]) {
match_number_int += 1;
button_text[number].setText(Integer.toString(button_number_02[number]));
}
if(match_number_int == button_number_02[number]) {
match_number_int += 1;
button_text[number].setVisibility(View.GONE);
}
now_number.setText(Integer.toString(match_number_int));
}
});
}


이로써 모든 코드 작성이 완료가 되었습니다.

퍼즐조각 5개가 하나로 합쳐지면 어플이 완성이 됩니다.

완성된 코드는 아래 java파일을 다운 받으셔서 확인해주세요.

MainActivity.java



처음 xml파일에 코딩을 할때에 색상적용도 같이 했기 때문에 따로 디자인 포스팅은 작성하지 않습니다.

모든 코딩이 완료되었을때 사용자 입맛에 맞게 색상이나 글씨크기 등등 변경해주세요.

이해하기 쉽게 설명을 하겠다고 생각하고 작성을 했는데 생각처럼 쉽게 설명이 되지 않은것 같네요.

지금까지 안드로이드 1to50 어플을 만들어 모자 포스팅을 읽어주셔서 감사합니다.


이 글을 공유하기

댓글(9)

  • 진의
    2017.06.12 16:52 신고

    강의 잘봤습니다!!
    그런데 private void print_button_text() {...} 함수에서는 for문으로 돌려주는게 더 효율적이지 않을까요?

    private void print_button_text() {

    for(int i = 0; i < 25; i ++) {
    button_text[i].setText(Integer.toString(button_number_01[i]))
    }

    }

    • 2017.06.12 16:54 신고

      그렇네요 ㅎ for문으로 해주는게 더 효율적입니다. 포스팅 수정해줘야겠네요.
      감사합니다.

  • 진의
    2017.06.12 17:07 신고

    그거 말고도
    버튼에 setOnClickListener부분있잖아여

    버튼을 배열로 구현하셨으니까, 일일이 온클릭리스너를 지정해주지마시고, 배열의 장점을 이용해서

    for (int i = 0; i < 25; i++) {

    button[i].setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View view) {

    if(match_number_int == 50) {

    include[1].setVisibility(View.VISIBLE);

    include[0].setVisibility(View.GONE);

    }

    int number = i;

    if(match_number_int == button_number_01[number]) {

    match_number_int += 1;

    button_text[number].setText(Integer.toString(button_number_02[number]));

    }

    if(match_number_int == button_number_02[number]) {

    match_number_int += 1;

    button_text[number].setVisibility(View.GONE);

    }

    now_number.setText(Integer.toString(match_number_int));

    }

    });

    }

    코드로 바꾸는게 더 효율적일꺼같애요!

    • 2017.06.12 17:15 신고

      제가 실력이 부족한건지 모르겠지만
      이 코드로 버튼이 작동이 되지 않을것 같네요. 코드상으로는 버튼 25개 모두에 세팅은 되겠지만 버튼 작동은 안되지 않을까요?

  • 진의
    2017.06.12 17:59 신고

    오버라이드 함수 onClickListener는 해당 함수가 쓰인 SetOnClickListener 함수 와 같은 지역에 존재하는 변수는 참조를 못합니다. 같은 지역의 값을 쓰려면 final을 붙여 상수화를 해야하죠. 제가 for(int i...)라고 답변을 드렸는데 이 당시의 i변수는 같은 지역의 변수이기 때문에 참조륾 못할겁니다. 상수화를 해야하는데 상수화를 하면 증감을 못하니 기능을 못구현하겠죠. 하지만 클래스의 전역변수는 오버라이드 함수에서 쓸 수 있기때문에, for문에서 0부터 24까지 증감할 변수 i를 전역변수로 쓴다면 될것같아요. 아니면 변수를 하나더 선언해서 증감되는 i변수를 상수변수에 저장한다음, 상수변수를 통해 i변수에 접근하는 방식으로도될 것 같네요.

  • 진의
    2017.06.12 18:23 신고

    혹시나 해서 for문으로 버튼배열을 돌려 SetOnClickListener를 적용해 오버라이드된 무명함수에서 for문으로 증감되는 변수 i를 호출해봤습니다. 실제로 써본적은 없었는데, 전역으로 해보니까 onCLlck을 받는 시점의 값을 불러들이기때문에, i<25 조건으로 onClick할수를 셋팅하면 25값을 불러들였습니다. 즉, 전역으로 선언된 변수를 OnClickListener 무명함수에서 호출하면 호출된 시점의 값을 부르기 때문에 i변수의 마지막 값을 불러들이더군요. 두번째 방법으로 final 키워드를 이용해 for문안에 상수를 만들고 i값을 상수에 저장했다가 부르니 setOnClickListener가 실행된 시점의 제대로된 변수값이 불러지더군요. 따라서 한글님이 의도하신 코드 대로 짜려면

    for (int i = 0; i < 25; i++) {
    final int j = i;
    button[j].setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View view) {

    if(match_number_int == 50) {

    include[1].setVisibility(View.VISIBLE);

    include[0].setVisibility(View.GONE);

    }

    int number = j;

    if(match_number_int == button_number_01[number]) {

    match_number_int += 1;

    button_text[number].setText(Integer.toString(button_number_02[number]));

    }

    if(match_number_int == button_number_02[number]) {

    match_number_int += 1;

    button_text[number].setVisibility(View.GONE);

    }

    now_number.setText(Integer.toString(match_number_int));

    }

    });

    }

    제 생각에는 이렇게 사용하면 될것같습니다.

    • 2017.06.12 18:32 신고

      좋은 의견과 자세한 설명글 감사드립니다.
      적용해보도록 하겠습니다.
      정말 오랫만에 공부한 내용은 머릿속에 남겨야 한다는 자극이 된것 같아서 기분이 좋습니다.

    • 2017.06.12 18:36 신고

      이상없이 잘 작동이 되네요.
      포스팅을 다시 수정해야겠네요.
      계속 도움 많이 주세요.

  • 진의
    2017.06.12 18:51 신고

    저도 몇달간 안드로이드를 안했었는데, 오랜만에 해보기도하고, 이론적으로 이해했던부분을 직접실험해서 정확한 결과를 보니 공부가 된것같아 기분이 좋습니다! 또한 기능이 잘 작동한다니 다행이네요!

    보충을 하자면, onClick이라는 오버라이드된 무명함수에서, for문내부의 i를 못쓰는 이유는 , onClick함수가 View.OnClickListener의 인스턴스 내부의 무명함수이기 때문입니다. 따라서 코드를 살펴보면 for문에서 쓰인 변수 i는 MainActivity의 멤버이고 onClick 무명함수는 OnClickListener의 멤버인것을 확인할 수 있습니다. new 키워드로 인스턴스화하여 사용한 View.OnClickListener는 MainActivity의 inner class(내부 클래스)로써 자바의 특성상 지역 변수는 inner class에서 참조가 불가능하기 때문에 위와 같은 방법을 쓴것입니다. 하지만 final을 통해 상수를 만들어놓고 지역변수 i를 담아 inner class에서 참조가 되도록 우회하는식으로 접근해본것입니다. 결과적으로도 가능한 부분이구요.

    앞으로도 자주 들르도록 하겠습니다!!!~~

Designed by JB FACTORY