kotlin

앱 만들어보기 - 1

beejaem 2022. 2. 19. 15:50

음악을 듣고 어떤 영화의 음악인지 맞추는 퀴즈 어플을 만들어 보았습니다.

 

먼저 layout을 구성해주었습니다.

메인화면

메인화면에서 필요한 기능들은 버튼 동작과 최고점수 표시정도가 끝이라 어렵진 않습니다.

최고 점수는 SharedPreferences기능을 이용했습니다.

var pref : SharedPreferences = getSharedPreferences("wordPref", MODE_PRIVATE)
var point = pref.getInt("record",0)!!
record.text = point.toString()

버튼들은 기본적인 화면전환 기능 입니다.

btn.setOnClickListener {
    var intent = Intent(this, GameActivity::class.java)
    startActivity(intent)
}

btn2.setOnClickListener {
    var intent = Intent(this, ListActivity::class.java)
    startActivity(intent)
}

이제 퀴즈 화면입니다.

퀴즈 화면

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_game)

    //키보드설정
    imm = getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as InputMethodManager?

    music = arrayListOf()
    movie = arrayListOf()
    list  = arrayListOf()
    hint  = arrayListOf()
    ox_list = arrayListOf()
    num_list = arrayListOf()

    var quiz_num = 1
    add(list,movie,music,hint)
    btn_next = findViewById(R.id.btn_next)
    tv_chance = findViewById(R.id.tv_chance)
    progress = findViewById(R.id.progressBar)
    btn_chk = findViewById(R.id.btn_chk)
    ib = findViewById(R.id.ib)
    ev = findViewById(R.id.ev)
    tv = findViewById(R.id.tv2)
    tv4 = findViewById(R.id.tv4)
    ib_hint = findViewById(R.id.ib_hint)
    tv_hint = findViewById(R.id.tv_hint)
    tv_hint_title = findViewById(R.id.tv_hint_title)


    //랜덤 생성
    var random = Random.nextInt(list.size)
    var r_num = random

    //넘버리스트에 중복방지를 위해 입력
    num_list.add(r_num)

    //프로그레스바 설정
    progress.max = count

    //타이머 동작
    timer()
    //미디어 생성
    play = MediaPlayer()
    set_music(r_num)

    //노래재생 버튼
    ib.setOnClickListener {
        flag = !flag
        if(flag){
            play!!.start()
            ib.setImageResource(R.drawable.stop)
        }else{
            play!!.pause()
            ib.setImageResource(R.drawable.play)
        }
    }

    //넘어가기 버튼
    btn_next.setOnClickListener {
        hideKeyboard(it)
        ox_list.add(false)
        if(num_list.size < music.size) {
            flag = false
            ib.setImageResource(R.drawable.play)

            play!!.reset()
            //힌트 초기화
            tv_hint.visibility = View.INVISIBLE
            tv_hint.text = ""

            //다음 곡 랜덤으로 재생
                if (num_list.size != movie.size) {
                    while (num_list.size < movie.size) {
                        var random = Random.nextInt(movie.size)
                        if (num_list.contains(random)) {
                            continue
                        } else {
                            r_num = random
                            num_list.add(r_num)
                            break
                        }
                    }
                    ev.setText("")
                }
            set_music(r_num)
            quiz_num++
        }else{
            //모든 곡을 맞추면 현재 점수와 최고 점수 비교 후 메인으로 전달
            var pref : SharedPreferences = getSharedPreferences("wordPref", MODE_PRIVATE)
            var edit : SharedPreferences.Editor = pref.edit()

            tv.text = point.toString()
            record = pref.getInt("record",0)
            if(record < point){
                edit.putInt("record",point)
                edit.commit()
            }

            //게임 종료 팝업
            var pop : AlertDialog.Builder = AlertDialog.Builder(this)
            pop.setTitle("Qst Quiz")
            pop.setMessage("내 점수 : ${point} \n모든 퀴즈를 맞추셨습니다. 게임을 종료합니다")
            var intent = Intent(this, MainActivity::class.java)
            pop.setPositiveButton("종료",object : DialogInterface.OnClickListener{
                override fun onClick(p0: DialogInterface?, p1: Int) {
                    startActivity(intent)
                    finish()
                }
            })
            pop.show()
        }
    }
    //Hint버튼
    ib_hint.setOnClickListener {
        if(chance>0){
            if(tv_hint.text == ""){
                var pop : AlertDialog.Builder = AlertDialog.Builder(this)
                pop.setTitle("Qst Quiz")
                pop.setMessage("힌트를 사용하시겠습니까?")
                pop.setPositiveButton("사용",object : DialogInterface.OnClickListener{
                    override fun onClick(p0: DialogInterface?, p1: Int) {
                        tv_hint.visibility = View.VISIBLE
                        tv_hint_title.visibility = View.VISIBLE
                        tv_hint.text = hint.get(r_num)
                        chance--
                        tv_chance.text = "$chance/3"
                    }
                })
                pop.setNegativeButton("취소",object : DialogInterface.OnClickListener{
                    override fun onClick(p0: DialogInterface?, p1: Int) {
                    }
                })
                pop.show()

            }else{
                //이미 힌트를 사용한 경우
                var pop : AlertDialog.Builder = AlertDialog.Builder(this)
                pop.setTitle("Qst Quiz")
                pop.setMessage("이미 초성 힌트를 사용하셨습니다.")
                pop.show()
            }
        }else{
            //힌트 없을 때 pop
            var pop : AlertDialog.Builder = AlertDialog.Builder(this)
            pop.setTitle("Qst Quiz")
            pop.setMessage("힌트 기회를 모두 사용하셨습니다.")
            pop.show()
        }
    }

    //확인 버튼
    btn_chk.setOnClickListener {
        hideKeyboard(it)
        var insert = ev.text.toString().replace(" ","")
        var movie_name = movie.get(r_num).replace(" ","")
        Log.d("abcd",movie_name)
        //입력값과 제목 비교
        if(insert == movie_name){
            ox_list.add(true)
            //힌트 초기화
            tv_hint.visibility = View.INVISIBLE
            tv_hint_title.visibility = View.INVISIBLE
            tv_hint.text = ""

            play!!.pause()
            play!!.reset()
            //다음 곡 랜덤으로 재생
            if(num_list.size != movie.size) {
                while (num_list.size < movie.size) {
                    var random = Random.nextInt(movie.size)
                    if (num_list.contains(random)) {
                        continue
                    } else {
                        r_num = random
                        num_list.add(r_num)
                        break
                    }
                }
                flag = false
                point += 10
                tv.text = point.toString()
                ev.setText("")
                //다음곡 준비
                set_music(r_num)
                //재생 이미지 초기화
                ib.setImageResource(R.drawable.play)

            }else{
                //모든 곡을 맞추면 현재 점수와 최고 점수 비교 후 메인으로 전달
                var pref : SharedPreferences = getSharedPreferences("wordPref", MODE_PRIVATE)
                var edit : SharedPreferences.Editor = pref.edit()
                point += 10
                tv.text = point.toString()
                record = pref.getInt("record",0)
                if(record < point){
                    edit.putInt("record",point)
                    edit.commit()
                }

                //게임 종료 팝업
                var pop : AlertDialog.Builder = AlertDialog.Builder(this)
                pop.setTitle("Qst Quiz")
                pop.setMessage("내 점수 : ${point} \n모든 퀴즈를 맞추셨습니다. 게임을 종료합니다")
                var intent = Intent(this, MainActivity::class.java)
                pop.setPositiveButton("종료",object : DialogInterface.OnClickListener{
                    override fun onClick(p0: DialogInterface?, p1: Int) {
                        startActivity(intent)
                        finish()
                    }
                })
                pop.show()
            }
        }else{
            ev.setText("")
        }
    }
}



//음악 준비
fun set_music(r_num : Int){
    //랜덤숫자로 노래 입력
    var name = GameActivity.music.get(r_num)
    Log.d("r_num : ",r_num.toString())
    //입력받은 노래로 raw폴더에 있는 파일의 id 받기
    var resid = resources.getIdentifier(name,"raw", packageName)
    Log.d("abab","resid : $resid")
    Log.d("name : ",name)
    Log.d("packagename : ",packageName)
    //Uri로 해당 id를 이용해 리소스파일 호출
    play!!.setDataSource(this, Uri.parse("android.resource://$packageName/$resid"))
    Log.d("abab","context = $this")
    play!!.prepare()
    //문제 넘버 변경
    tv_quiz = findViewById(R.id.tv_quiz)
    tv_quiz.text = "${num_list.size.toString()}번"
}

//핸들러 작동
fun timer(){
    handler.sendEmptyMessageDelayed(0,1000)
}
//핸들러 중지
fun timer_q(){
    ox_list.add(false)
    handler.removeMessages(0)

    //게임 종료 팝업
    var pop : AlertDialog.Builder = AlertDialog.Builder(this)
    pop.setTitle("Qst Quiz")
    pop.setMessage("내 점수 : ${point} \n시간이 초과 되었습니다. 게임을 종료합니다")
    var intent = Intent(this, MainActivity::class.java)
    pop.setPositiveButton("종료",object : DialogInterface.OnClickListener{
        override fun onClick(p0: DialogInterface?, p1: Int) {
            startActivity(intent)
            finish()
        }
    })
    pop.show()
    var pref : SharedPreferences = getSharedPreferences("wordPref", MODE_PRIVATE)
    var edit : SharedPreferences.Editor = pref.edit()
    record = pref.getInt("record",0)
    if(record < point){
        edit.putInt("record",point)
        edit.commit()
    }
}


var handler =  object : Handler(){
    override fun handleMessage(msg: Message) {
        super.handleMessage(msg)
        var min = count/60
        var sec = count%60
        var time = "${min.toString()}분 ${sec.toString()}"
        tv4.text = time
        if(count >0){
            count--
            progress.incrementProgressBy(1)
            sendEmptyMessageDelayed(0,1000)
        }else{
            timer_q()
        }
    }
}

//생명주기
override fun onStop() {
    super.onStop()
    if(play!=null){
        play!!.pause()
    }
}

override fun onDestroy () {
    super.onDestroy ()
    if(play!=null){
        play!!.stop()
        play!!.release()
        play = null
    }
}
//키보드 숨기기
fun hideKeyboard(v : View) {
    if(v != null){
        imm!!.hideSoftInputFromWindow(v.windowToken,0)
    }
}
class MyData{
    var num : Int = 0
    var title : String = ""
    var flag : Boolean = true
    var music : String = ""

    constructor(num:Int, title:String,flag:Boolean,music:String){
        this.num = num
        this.title = title
        this.flag = flag
        this.music = music
    }
}

fun add(list:ArrayList<String>,movie:ArrayList<String>,music:ArrayList<String>,hint:ArrayList<String>){
    //영화 및 노래 추가
    list.add("하울의 움직이는 성,castle/ㅎㅇㅇ ㅇㅈㅇㄴ ㅅ")
    list.add("겨울 왕국,winter/ㄱㅇ ㅇㄱ")
    list.add("비긴 어게인,star/ㅂㄱ ㅇㄱㅇ")
    list.add("분노의 질주,again/ㅂㄴㅇ ㅈㅈ")
    list.add("알라딘,speech/ㅇㄹㄷ")
    list.add("타이타닉,titanic/ㅌㅇㅌㄴ")
    list.add("맘마미아,dancing/ㅁㅁㅁㅇ")
    list.add("보헤미안랩소디,queen/ㅂㅎㅁㅇ ㄹㅅㄷ")
    list.add("그 여자 작사 그 남자 작곡,wayback/ㄱ ㅇㅈ ㅈㅅ ㄱ ㄴㅈ ㅈㄱ")

    //영화 및 노래 제목 분할 저장
    list.forEach {
        var com = it.indexOf(',')
        var num = it.indexOf('/')
        var movie_title = it.substring(0,com)
        var music_title = it.substring(com+1,num)
        var hint_title = it.substring(num+1,it.lastIndex+1)

        movie.add(movie_title)
        music.add(music_title)
        hint.add(hint_title)
    }
}

이제 오답노트 페이지로 가면 내가 맞춘 문제들과 틀린 문제들을 확인하고 다시 음악을 들어볼 수 있다.

오답노트 화면

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_list)
    
    //문제와 OX리스트를 새로운 리스트에 추가
    if(GameActivity.num_list.size == GameActivity.ox_list.size) {
        for (i in 0..GameActivity.movie.size - 1) {
            var a = GameActivity.num_list.get(i)
            var b: String = GameActivity.movie.get(a)
            var c: Boolean = GameActivity.ox_list.get(i)
            var d: String = GameActivity.music.get(a)
            arr.add(MyData(i, b, c, d))
        }
    }
    //리스트가 정상적으로 추가되면 리사이클러뷰가 실행
    if(arr.size > 0) {
        rv = findViewById(R.id.rv)
        adapter = MainRvAdapter(this, arr,packageName)
        rv.adapter = adapter
        rv.layoutManager = LinearLayoutManager(this)
    }else{
        tv = findViewById(R.id.tv)
        tv.text = "게임 기록이 존재하지 않습니다"
    }
}


//오답노트 리사이클러 뷰
class MainRvAdapter(val context: Context, val arr: ArrayList<MyData>, val packageName:String) :
    RecyclerView.Adapter<MainRvAdapter.Holder>() {
    var play : MediaPlayer? = null
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val view = LayoutInflater.from(context).inflate(R.layout.view_item, parent, false)
        return Holder(view)
    }

    override fun getItemCount(): Int {
        return arr.size
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        var i = arr.get(position).num +1
        holder.tv_1.setText("${i}번")
        if(arr.get(position).flag){
            holder.tv_2.setText("O")
            holder.view.setBackgroundColor(Color.parseColor("#8BC34A"))
        }else{
            holder.tv_2.setText("X")
            holder.view.setBackgroundColor(Color.parseColor("#F60F60"))
        }
        holder.tv_4.setText(arr.get(position).title)


        holder.btn.setOnClickListener {
            var music = arr.get(position).music
            Log.d("abab","title : $music")
            var resid = context.resources.getIdentifier(music,"raw", packageName)
            Log.d("abab","context = $context")
            Log.d("abab","package = $packageName")
            Log.d("abab","resid = $resid")

            //들어보기 미디어플레이어
            try{
                play = MediaPlayer()
                play!!.setDataSource(context, Uri.parse("android.resource://$packageName/$resid"))
                play!!.prepare()
                play!!.start()
            }catch(e : Exception){
                Log.d("abab","$e")
            }

        }

    }

    inner class Holder(itemView: View?) : RecyclerView.ViewHolder(itemView!!) {
        val tv_1 : TextView = itemView!!.findViewById(R.id.tv_1)
        val tv_2 : TextView = itemView!!.findViewById(R.id.tv_2)
        val tv_4 : TextView = itemView!!.findViewById(R.id.tv_4)
        var view : View = itemView!!
        var btn : Button = itemView!!.findViewById(R.id.btn)
    }

}

 

'kotlin' 카테고리의 다른 글

image파일 저장하기  (0) 2022.08.26
qr코드 생성하기  (0) 2022.08.22
canvas  (0) 2022.02.24
SharedPreferences  (0) 2022.02.16
handler  (0) 2022.02.10