You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio井字棋游戏获胜者显示异常技术求助

修复井字棋游戏的获胜者显示错误与状态栏问题

嘿,我仔细看了你的井字棋代码,找到了导致获胜者显示错误、甚至状态栏异常消失的核心问题,咱们来一步步修复它:

问题根源分析

  • 获胜者判断逻辑完全错误:你当前通过winningPosition[0]的索引值(比如0或1)来判定X/O获胜,这和实际的玩家标记(gameState里的0=X、1=O)完全不相关,自然会大部分场景判断错误。
  • 游戏状态被错误重置:在检查获胜条件前,你写了gameActive = true;,这会把已经结束的游戏状态强行恢复成可玩,导致游戏无法正确终止,还会干扰状态栏的显示。
  • 缺少平局处理:当所有格子填满却无人获胜时,状态栏没有对应的提示,看起来就像“消失”了一样。
  • 重复查找控件:每次点击都重新查找status TextView,虽然功能没问题,但可以优化成成员变量提升效率。

修复后的完整代码

MainActivity.java

package com.jashanubhi.tictactoeme; 
import androidx.appcompat.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.ImageView; 
import android.widget.TextView; 

public class MainActivity extends AppCompatActivity { 
    int activePlayer = 0; 
    boolean gameActive = true; 
    int[] gameState = {2,2,2,2,2,2,2,2,2}; 
    int[][] winningPositions = {{0,1,2}, {3,4,5}, {6,7,8}, {0,4,8}, {2,4,6}, {0,3,6}, {1,4,7}, {2,5,8}};
    // 把status声明为成员变量,避免重复findViewById
    private TextView statusTextView;

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main);
        // 初始化statusTextView
        statusTextView = findViewById(R.id.status);
    } 

    public void playerTap(View view) { 
        ImageView img = (ImageView) view; 
        int tappedImage = Integer.parseInt(img.getTag().toString()); 

        // 如果游戏已结束,点击就重置
        if(!gameActive){ 
            gameReset(view); 
            return; // 重置后直接返回,避免后续逻辑执行
        } 

        // 只有空位才能被点击
        if(gameState[tappedImage] == 2 && gameActive) { 
            gameState[tappedImage] = activePlayer; 
            img.setTranslationY(-1000f); 

            if (activePlayer == 0) { 
                img.setImageResource(R.drawable.x); 
                activePlayer = 1; 
                statusTextView.setText("O's Turn - Tap to Play"); 
            } else { 
                img.setImageResource(R.drawable.o); 
                activePlayer = 0; 
                statusTextView.setText("X's Turn - Tap to Play"); 
            } 

            img.animate().translationYBy(1000f).setDuration(300); 
        } 

        // 检查是否有获胜者
        checkWinner();
        // 检查是否平局
        checkDraw();
    } 

    // 单独提取获胜检查逻辑
    private void checkWinner() {
        for (int[] winningPosition : winningPositions) { 
            int pos0 = gameState[winningPosition[0]];
            int pos1 = gameState[winningPosition[1]];
            int pos2 = gameState[winningPosition[2]];
            // 三个位置都不为空,且值相同则获胜
            if (pos0 == pos1 && pos1 == pos2 && pos0 != 2) { 
                String winner = pos0 == 0 ? "X has won" : "O has won";
                statusTextView.setText(winner); 
                gameActive = false; 
                return; // 找到获胜者后直接退出循环
            } 
        }
    }

    // 检查平局逻辑:所有格子都被填满且无人获胜
    private void checkDraw() {
        if(gameActive){
            boolean isDraw = true;
            for(int state : gameState){
                if(state == 2){
                    isDraw = false;
                    break;
                }
            }
            if(isDraw){
                statusTextView.setText("It's a Draw!");
                gameActive = false;
            }
        }
    }

    public void gameReset(View view){ 
        activePlayer = 0; 
        gameActive = true;
        for(int i = 0; i < gameState.length; i++){ 
            gameState[i] = 2; 
        } 

        // 清空所有图片
        int[] imageIds = {R.id.imageView0, R.id.imageView1, R.id.imageView2,
                          R.id.imageView3, R.id.imageView4, R.id.imageView5,
                          R.id.imageView6, R.id.imageView7, R.id.imageView8};
        for(int id : imageIds){
            ((ImageView)findViewById(id)).setImageResource(0);
        }

        statusTextView.setText("X's Turn - Tap to Play"); 
    } 
}

布局XML(无需修改,保持原代码即可)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@string/title" android:textSize="38dp" android:textStyle="bold" app:fontFamily="sans-serif-light" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" />
<ImageView android:id="@+id/imageView" android:layout_width="398dp" android:layout_height="398dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" app:srcCompat="@drawable/grid" />
<TextView android:id="@+id/status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="X's Turn - Tap to Play" android:textSize="30sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView" />
<LinearLayout android:layout_width="398dp" android:layout_height="398dp" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="@+id/imageView" app:layout_constraintTop_toBottomOf="@+id/textView">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal">
<ImageView android:id="@+id/imageView0" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="0" />
<ImageView android:id="@+id/imageView1" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="1" />
<ImageView android:id="@+id/imageView2" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="2" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal">
<ImageView android:id="@+id/imageView3" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="3" />
<ImageView android:id="@+id/imageView4" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="4" />
<ImageView android:id="@+id/imageView5" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="5" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal">
<ImageView android:id="@+id/imageView6" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="6" />
<ImageView android:id="@+id/imageView7" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="7" />
<ImageView android:id="@+id/imageView8" android:layout_width="50dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="playerTap" android:padding="23sp" android:tag="8" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

关键修改点说明

  1. 修正获胜者判断逻辑:现在通过gameState[winningPosition[0]]的值来判断,0对应X,1对应O,完全符合你的玩家标记规则。
  2. 移除错误的gameActive重置:删掉了之前在检查获胜前的gameActive = true;,确保游戏结束后状态保持为false,不再响应无效点击。
  3. 添加平局检测:当所有格子都被填满且没有获胜者时,状态栏会显示"It's a Draw!",解决了状态栏“消失”的问题。
  4. 优化控件查找:把status TextView声明为成员变量,在onCreate中初始化,避免每次点击都重复查找,提升性能。
  5. 重构代码结构:把获胜检查和平局检查单独提取成方法,让代码更清晰易读。

这样修改后,你的井字棋游戏就能正确显示获胜者,处理平局,状态栏也不会再异常消失啦!

内容的提问来源于stack exchange,提问作者Jashan Ubhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 08:17:28