package com.gogame.minesweeper.swipe import android.app.Dialog import android.content.Context import android.media.MediaPlayer import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import com.gogame.minesweeper.DifficultyLevel import com.gogame.minesweeper.R import com.gogame.minesweeper.databinding.ActivitySwipeBinding import com.gogame.minesweeper.BaseActivity import com.gogame.minesweeper.ad.AdShowFailed import com.gogame.minesweeper.ad.AdsInsUtil import com.gogame.minesweeper.ad.LoadListener import com.gogame.minesweeper.ad.ShowListener import com.gogame.minesweeper.bean.GameState import com.google.gson.Gson import com.ironsource.fa import com.thinkup.core.api.TUAdInfo import kotlin.random.Random class SwipeActivity : BaseActivity() { private lateinit var binding: ActivitySwipeBinding private var minutes = 0 private var seconds = 0 private var isRunning = false private var pausedTime = 0L // 暂停时保存的时间戳 private var isGameStarted = false //游戏是否开始了 private var isGameOver = false //游戏是否结束了(不管成功还是失败) private val handler = Handler(Looper.getMainLooper()) private lateinit var runnable: Runnable private lateinit var winSoundPlayer: MediaPlayer private lateinit var loseSoundPlayer: MediaPlayer private var isNewGame = true override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySwipeBinding.inflate(layoutInflater) setContentView(binding.root) loadAd() immersionBar() winSoundPlayer = MediaPlayer.create(this, R.raw.win) loseSoundPlayer = MediaPlayer.create(this, R.raw.explosion) var difficulty = intent.getSerializableExtra("difficulty") as? DifficultyLevel if (difficulty == null) { difficulty = DifficultyLevel.BEGINNER } isNewGame = intent.getBooleanExtra("isNewGame", true) initTimeRun() resetTimer() val sharedPreferences = getSharedPreferences("minesweeper_prefs", Context.MODE_PRIVATE) val gameStateJson = sharedPreferences.getString("game_state", null) binding.gridSwipe.postDelayed({ binding.gridSwipe.setDifficulty(difficulty) setNumberImage(binding.gridSwipe.mineNum, binding.hundreds, binding.tens, binding.ones) binding.gridSwipe.fillAll() if (!isNewGame) { if (!gameStateJson.isNullOrEmpty()) { val gameState: GameState = Gson().fromJson(gameStateJson, GameState::class.java) minutes = gameState.minutes seconds = gameState.seconds startTimeRun() } binding.gridSwipe.loadGameState() } }, 120) binding.btnStart.setOnClickListener { handleButtonClick() } binding.gridSwipe.listener = object : SwipeGridLayout.GameStateChange { override fun onStart(rest: Int) { isGameStarted = true binding.stateImg.setImageResource(R.mipmap.smile) startTimeRun() } override fun onFlagsChange(flags: Int, rest: Int) { setNumberImage(rest, binding.hundreds, binding.tens, binding.ones) } override fun victory() { isGameOver = true playWinSound() showResultDialog(true) stopTimer() binding.gridSwipe.clearGameStateSP() } override fun defeat() { isGameOver = true playLoseSound() binding.stateImg.setImageResource(R.mipmap.sorrow) showResultDialog(false) stopTimer() binding.gridSwipe.clearGameStateSP() } } } private fun immersionBar() { //自适应沉浸式 ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) windowInsetsController.isAppearanceLightStatusBars = true//状态栏文字颜色 } private val successImages = arrayOf( R.drawable.win_emoji_partying_face, // 替换为你的成功图片资源 R.drawable.win_emoji_cowboy_hat_face, R.drawable.win_emoji_smiling_face_with_sunglasses, R.drawable.win_emoji_beaming_face_with_smiling_eyes ) private val failureImages = arrayOf( R.drawable.lose_emoji_bomb, // 替换为你的失败图片资源 R.drawable.lose_emoji_confounded_face, R.drawable.lose_emoji_anguished_face, R.drawable.lose_emoji_exploding_head, // 替换为你的失败图片资源 R.drawable.lose_emoji_grimacing_face, R.drawable.lose_emoji_downcast_face_with_sweat, R.drawable.lose_emoji_face_with_head_bandage, R.drawable.lose_emoji_sad_but_relieved_face ) private fun showResultDialog(isVictory: Boolean) { val dialog = Dialog(this) dialog.setContentView(R.layout.dialog_result) val imageView = dialog.findViewById(R.id.imageView) val titleTextView = dialog.findViewById(R.id.textViewTitle) val messageTextView = dialog.findViewById(R.id.textViewMessage) if (isVictory) { val randomSuccessImage = successImages[Random.nextInt(successImages.size)] imageView.setImageResource(randomSuccessImage) titleTextView.text = getString(R.string.you_win) messageTextView.text = getString(R.string.win_desc) } else { val randomFailureImage = failureImages[Random.nextInt(failureImages.size)] imageView.setImageResource(randomFailureImage) titleTextView.text = getString(R.string.you_lose) messageTextView.text = getString(R.string.lose_desc) } val btn = dialog.findViewById(R.id.newGameBtn) btn.setOnClickListener { handleButtonClick() dialog.dismiss() showAd(randomAdPlace) } dialog.setCancelable(false) dialog.show() } private fun playWinSound() { if (!winSoundPlayer.isPlaying) { winSoundPlayer.start() } } private fun playLoseSound() { if (!loseSoundPlayer.isPlaying) { loseSoundPlayer.start() } } private fun handleButtonClick() { binding.stateImg.setImageResource(R.mipmap.smile) binding.gridSwipe.reset() // 复位逻辑 setNumberImage( binding.gridSwipe.mineNum, binding.hundreds, binding.tens, binding.ones ) // 设置数字图片 stopTimer() // 停止计时器 resetTimer() // 重置计时器 } private fun startTimeRun() { if (!isRunning) { isRunning = true handler.post(runnable) } } // 停止计时并移除 runnable private fun stopTimer() { isRunning = false handler.removeCallbacks(runnable) // 移除 runnable,防止继续执行 } private fun initTimeRun() { // 初始化计时器 runnable = object : Runnable { override fun run() { if (isRunning) { incrementTime() updateTimeImage() handler.postDelayed(this, 1000) // 每秒更新一次 } } } } private fun setNumberImage( number: Int, hundredsImageView: ImageView, tensImageView: ImageView, onesImageView: ImageView ) { // 数字限制在1-999 if (number < 1 || number > 999) return // 获取百位、十位、个位 val hundreds = number / 100 val tens = (number % 100) / 10 val ones = number % 10 // 根据数字设置图片资源ID,假设图片资源名为c0到c9 val resIdHundreds = getResourceIdForNumber(hundreds) val resIdTens = getResourceIdForNumber(tens) val resIdOnes = getResourceIdForNumber(ones) // 设置ImageView的图片资源 hundredsImageView.setImageResource(resIdHundreds) tensImageView.setImageResource(resIdTens) onesImageView.setImageResource(resIdOnes) } // 获取数字对应的资源ID private fun getResourceIdForNumber(num: Int): Int { return when (num) { 0 -> R.mipmap.c0 1 -> R.mipmap.c1 2 -> R.mipmap.c2 3 -> R.mipmap.c3 4 -> R.mipmap.c4 5 -> R.mipmap.c5 6 -> R.mipmap.c6 7 -> R.mipmap.c7 8 -> R.mipmap.c8 9 -> R.mipmap.c9 else -> R.mipmap.c0 // 默认值,数字应为0-9 } } // 增加时间 private fun incrementTime() { seconds++ if (seconds == 60) { seconds = 0 minutes++ } binding.gridSwipe.setTime(minutes, seconds) } // 更新时间的图片显示 private fun updateTimeImage() { val minuteTens = minutes / 10 val minuteOnes = minutes % 10 val secondTens = seconds / 10 val secondOnes = seconds % 10 binding.minuteTens.setImageResource(getResourceIdForNumber(minuteTens)) binding.minuteOnes.setImageResource(getResourceIdForNumber(minuteOnes)) binding.secondTens.setImageResource(getResourceIdForNumber(secondTens)) binding.secondOnes.setImageResource(getResourceIdForNumber(secondOnes)) } override fun onResume() { super.onResume() //如果游戏开始了并且游戏没有结束 if (isGameStarted && !isGameOver) { if (pausedTime > 0L) { // 继续计时 handler.post(runnable) isRunning = true } } } override fun onPause() { super.onPause() // 保存当前的计时状态 pausedTime = System.currentTimeMillis() isRunning = false handler.removeCallbacks(runnable) // 停止计时 } override fun onDestroy() { super.onDestroy() // 重置计时器 resetTimer() //释放资源 binding.gridSwipe.onPlayerRelease() winSoundPlayer.release() loseSoundPlayer.release() } // 重置计时器为00:00 private fun resetTimer() { minutes = 0 seconds = 0 updateTimeImage() } private var randomAdPlace = "" private fun loadAd() { // 生成一个随机索引 val randomIndex = Random.nextInt(AdsInsUtil.Placement.adPlaceAllList.size) // 获取随机的广告位 randomAdPlace = AdsInsUtil.Placement.adPlaceAllList[randomIndex] AdsInsUtil.loadAd( act = this, adID = randomAdPlace, loadListener = object : LoadListener { override fun loaded(ad: TUAdInfo) { } override fun loadFailed(error: String) { } }) } private fun showAd(randomAdPlace: String) { AdsInsUtil.showAd( act = this, adID = randomAdPlace, listener = object : ShowListener { override fun onAdShown(ad: TUAdInfo?) { } override fun onAdShowFailed(error: AdShowFailed?) { loadAd() } override fun onAdClosed() { loadAd() } }) } }