그림짝맞추기 앱개발

그림짝맞추기 앱만들기 14 - 30초 카운트다운 타이머 추가하기, 30초 카운트다운 소수점 3자리까지 표시하기, 30초안에 못맞출 경우, 재도전 창 띄우기

두결앱개발 2026. 1. 6. 04:13
반응형
SMALL

안녕하세요~ 두결입니다.

 

지난시간에는 4단계까지 해보았는데요~

 

이번시간에는

5단계로 가기전에 30초 시간제한 기능을 구현해보겠습니다.

 


▣  30초 카운트다운 타이머 추가하기

먼저, 30초 카운트다운 타이머를 추가해보겠습니다.

CountDownTimer cdTimer;
// 30초 카운트다운 타이머
private void StartCountDownTimer()
{
    // 타이머가 이미 있으면 종료하기
    if(cdTimer !=null)
    {
        cdTimer.cancel();
        cdTimer = null;
    }

    cdTimer = new CountDownTimer(30000,1000) {
        @Override
        public void onFinish() {

        }
        @Override
        public void onTick(long l) {
            
        }
    };
    cdTimer.start();
}

 

cdTimer라는 CountDown Timer를 하나 만들구요~

StartCountDownTimer()함수를 만들어서 여기에서 CountDownTimer를 생성하였습니다.

카운트다운 시간은 30초로 설정하였습니다.

 

ActivityResultLauncher<Intent> mPopupCountDownForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == RESULT_OK) {
                 // blank 이미지 표시하기
                 for(int i=0;i<nCurImageCount;i++) {
                     ImageView imgvCur = arrayListImage.get(i);
                     FlipCardAnimation(imgvCur);
                 }

                bGameStart =true;

                StartCountDownTimer();
            }
        }
);

 

새게임 시작하고 5초 카운트다운이 끝난후에 그림카드를 뒤집고 나서

StartCountDownTimer()함수를 호출하였습니다.

 

카운트 다운이 잘 표시되는지 확인하기 위해서 TextView를 하나추가해보겠습니다.

 

 

Main Layout에서 TextView를 하나 추가하구요~

 

<TextView
    android:id="@+id/txtvCountDown"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text=""
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.1" />

 

ID는 txtvCountDown이라고 하였습니다.

 

txtv_CountDown = findViewById(R.id.txtvCountDown);
txtv_CountDown.setTextSize(20);
txtv_CountDown.setTypeface(null, Typeface.BOLD);
txtv_CountDown.setGravity(Gravity.CENTER|Gravity.TOP);
txtv_CountDown.setTextColor(Color.parseColor("#FFFFFF"));

 

txtv_CountDown 객체 생성하고 기본 설정까지 해주었습니다.

 

cdTimer = new CountDownTimer(30000,1000) {
    @Override
    public void onFinish() {

    }
    @Override
    public void onTick(long l) {
        txtv_CountDown.setText((l / 1000) + "");
    }
};
cdTimer.start();

 

마지막으로 CountDownTimer의 onTick()함수에서 30초 카운트다운하는 숫자를 표시해주었습니다.

 

여기까지 잘 되는지 실행을 해보면

 

 

네 위쪽에 카운트다운하는 숫자가 잘 표시되네요..^^

 

 


▣  30초 카운트다운 소수점 3자리까지 표시하기

먼저, 30초 카운트다운 타이머를 추가해보겠습니다.

 

소수점 3자리까지 표시하는것은 String.format()을 이용하면 쉽게 할수 있습니다.

 

// 30초 카운트다운 타이머
private void StartCountDownTimer()
{
    // 타이머가 이미 있으면 종료하기
    if(cdTimer !=null)
    {
        cdTimer.cancel();
        cdTimer = null;
    }

    cdTimer = new CountDownTimer(30000,1000) {
        @Override
        public void onFinish() {

        }
        @Override
        public void onTick(long l) {
            String sLeftTime;
            sLeftTime = String.format("%.03f",l / 1000.0f);
            txtv_CountDown.setText(sLeftTime);
        }
    };
    cdTimer.start();
}

 

위와같이 String.format("%.03f", l / 1000.0f);를 이용해서 

30초중에 남은 시간을 소숫점 3자리로 표시하였습니다.

 

그런데, 지금 이 카운트다운 타이머가 1초간격으로 바뀌다보니까 약간 역동적이지가 않네요~

타이머간격을 조금 바꾸어보겠습니다.

 

cdTimer = new CountDownTimer(30000,50) {

 

네, 위와같이 50ms간격으로 바꾸었습니다.

 

 

네, 위와같이 소숫점 3자리까지 표시가 잘 되고.. 50ms간격이라 빠르게 잘 바뀌네요..^^

 

 


▣  30초안에 못맞출 경우, 재도전 창 띄우기

마지막으로 한가지만 더 해보겠습니다.

 

30초 안에 맞추지 못할 경우에는 재도전 할지 게임을 종료할지를 물어보는 창을 띄워보도록 하겠습니다.

이건 팝업창을 새로 만들지 않고 그냥 간단한 Dialog박스로 해보겠습니다.

 

// 다시 도전할지 여부 물어보는 Dialog 박스 띄워주는 함수
private void ShowRetryDialog() {
    AlertDialog.Builder builderRetryDialog = new AlertDialog.Builder(this);
    builderRetryDialog.setTitle("재 도전?");
    builderRetryDialog.setMessage("두결 - 그림짝 맞추기 게임을 다시 도전하시겠습니까?");

    builderRetryDialog.setPositiveButton("확인", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // 확인 버튼 클릭시 동작
            NewGame();
        }
    });

    builderRetryDialog.setNegativeButton("취소", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // 취소 버튼 클릭시 동작
            finishAndRemoveTask();
        }
    });

    builderRetryDialog.setCancelable(false); // 외부 터치로 다이얼로그 닫기 방지
    builderRetryDialog.show();
}

 

ShowRetryDialog()함수를 만들어서 

AlertDialog.Builder를 이용해서 간단한 메세지 박스를 띄워보았습니다.

여기에서 확인버튼을 누르면 NewGame()을 호출해서 새로운 게임을 하고

취소버튼을 누르면 앱을 종료하도록 하였습니다.

 

cdTimer = new CountDownTimer(30000,50) {
    @Override
    public void onFinish() {
        ShowRetryDialog(); // 재도전?
    }
    @Override
    public void onTick(long l) {
        String sLeftTime;
        sLeftTime = String.format("%.03f",l / 1000.0f);
        txtv_CountDown.setText(sLeftTime);
    }
};
cdTimer.start();

 

카운트다운타이머의 onFinish()에서 ShowRetryDialog()함수를 호출하였습니다.

즉, 30초안에 맞추지 못하고 카운트다운이 종료되면 그때 재도전할지를 물어보는 다이얼로그 창을 띄운것이죠..

 

아, 그리고

30초 안에 맞춘경우에는

 

// 다음단계 설정 팝업창 띄우는 함수.
private void ShowPopupNextStage()
{
    StopCountDownTimer();

    Intent intent = new Intent(getApplicationContext(), PopupNextStage.class);
    intent.putExtra("curgamestage", nGameStage);
    mStartForResult.launch(intent);
}

 

다음단계 설정 팝업창을 띄우기전에

StopCountDownTimer()함수를 호출해서 30초 카운트 다운 타이머를 멈추도록 하였습니다.

 

private void StopCountDownTimer()
{
    // 타이머가 이미 있으면 종료하기
    if(cdTimer !=null)
    {
        cdTimer.cancel();
        cdTimer = null;
    }
    txtv_CountDown.setText("30.000");
}

 

네 위와같이 StopCountDownTimer()에서 cdTimer를 종료해주고 30초 숫자 표시해주는 TextView도 초기화 해주었습니다.

 

 

네, 위와같이 30초 안에 다 못맞추면 "재도전" Dialog 상자가 표시가 됩니다. ^^

 

 

여기까지 전체 동영상으로 한번 보겠습니다.

 

 

 

 

네  1~4단계까지 잘 되고 30초 안에 못맞추면 재도전 대화상자도 잘 표시가 되네요.. ^^

 

이번시간은 여기까지만 하도록 하구요~

 

다음시간에는 저 30초 숫자를 숫자로만 표시하지말고 프로그레스바도 같이 표시해보도록 하겠습니다. 

 

그럼, 이만 ~

 

감사합니다. ^^

반응형
LIST