当我玩游戏时,一段时间后会出现错误,窗口关闭,应用程序不断停止。
游戏的 Logcat 是
Process: com.example.tictactoe, PID: 12663
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:414)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28309)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28309)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=9; index=9
at com.example.tictactoe.MainActivity.playertap(MainActivity.java:32)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28309)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
游戏的 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="10dp"
android:fontFamily="cursive"
android:padding="10dp"
android:text="@string/heading"
android:textSize="34sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@string/main_grid"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintVertical_bias="1.0"
app:srcCompat="@drawable/grid" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="420dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
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/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:contentDescription="@string/o_value"
android:onClick="playertap"
android:tag="1"
android:padding="20sp"
/>
<ImageView
android:id="@+id/imageView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="playertap"
android:tag="2"
android:padding="20sp" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="playertap"
android:tag="3"
android:contentDescription="TODO"
android:padding="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="playertap"
android:tag="4"
android:padding="20sp" />
<ImageView
android:id="@+id/imageView5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="playertap"
android:tag="5"
android:padding="20sp" />
<ImageView
android:id="@+id/imageView6"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="playertap"
android:tag="6"
android:padding="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView7"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="playertap"
android:tag="7"
android:padding="20sp" />
<ImageView
android:id="@+id/imageView8"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="playertap"
android:tag="8"
android:padding="20sp" />
<ImageView
android:id="@+id/imageView9"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick ="playertap"
android:tag="9"
android:padding="20sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="15sp"
android:text="@string/status"
android:textSize="18sp"
android:textStyle="italic"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
like so
mainactivity java代码:
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
boolean gameActive = true;
// Player representation
// 0 - X
// 1 - O
int activePlayer = 0;
int[] gameState = {2, 2 , 2, 2, 2, 2, 2, 2, 2};
// State meanings:
// 0 - X
// 1 - O
// 2 - Null
int[][] winPositions = {{0,1,2}, {3,4,5}, {6,7,8},
{0,3,6}, {1,4,7}, {2,5,8},
{0,4,8}, {2,4,6}};
public void playertap(View view){
ImageView img = (ImageView) view;
int tappedImage = Integer.parseInt(img.getTag().toString());
if(!gameActive){
gameReset(view);
}
if(gameState[tappedImage] == 2) {
gameState[tappedImage] = activePlayer;
img.setTranslationY(-1000f);
if (activePlayer == 0) {
img.setImageResource(R.drawable.x);
activePlayer = 1;
TextView status = findViewById(R.id.status);
status.setText("O's Turn - Tap to play");
} else {
img.setImageResource(R.drawable.o);
activePlayer = 0;
TextView status = findViewById(R.id.status);
status.setText("X's Turn - Tap to play");
}
img.animate().translationYBy(1000f).setDuration(300);
}
// Check if any player has won
for(int[] winPosition: winPositions){
if(gameState[winPosition[0]] == gameState[winPosition[1]] &&
gameState[winPosition[1]] == gameState[winPosition[2]] &&
gameState[winPosition[0]]!=2){
// Somebody has won! - Find out who!
String winnerStr;
gameActive = false;
if(gameState[winPosition[0]] == 0){
winnerStr = "X has won";
}
else{
winnerStr = "O has won";
}
// Update the status bar for winner announcement
TextView status = findViewById(R.id.status);
status.setText(winnerStr);
}
}
}
public void gameReset(View view) {
gameActive = true;
activePlayer = 0;
for(int i=0; i<gameState.length; i++){
gameState[i] = 2;
}
((ImageView)findViewById(R.id.imageView9)).setImageResource(0);
((ImageView)findViewById(R.id.imageView1)).setImageResource(0);
((ImageView)findViewById(R.id.imageView2)).setImageResource(0);
((ImageView)findViewById(R.id.imageView3)).setImageResource(0);
((ImageView)findViewById(R.id.imageView4)).setImageResource(0);
((ImageView)findViewById(R.id.imageView5)).setImageResource(0);
((ImageView)findViewById(R.id.imageView6)).setImageResource(0);
((ImageView)findViewById(R.id.imageView7)).setImageResource(0);
((ImageView)findViewById(R.id.imageView8)).setImageResource(0);
TextView status = findViewById(R.id.status);
status.setText("X's Turn - Tap to play");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
应用程序通常会在一次输入后崩溃,但有时会在完成一整场游戏后崩溃 无法理解,因为点击功能工作正常。
这里的问题出在您的索引中,就像您的例外中所说的那样:
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=9; index=9
at com.example.tictactoe.MainActivity.playertap(MainActivity.java:32)
这里有两种可能的解决方案。第一个是更好的,就是简单地将图像上的标签从 0 更改为 8,而不是 1 到 9。另一种方法是仅在
- 1
上使用 tappedImage
,这样您始终可以获得正确的索引,但这会使将来的事情变得复杂,所以我建议使用第一个,因为您没有太多代码需要编辑。
发生这种情况是因为当您使用
ImageView
单击 tag = "9"
时,tappedImage
会获取 9
的值,并且您将其用作具有 size == 9
的数组的索引。但数组索引始终以 0
开始,到 size - 1
。在这种情况下,对于 size == 9
,索引将为 0, 1, 2, 3, 4, 5, 6, 7, 8
- 其中 8 是最后一个。
据我所知,您的
winPositions
有这种逻辑,您只是忘记从零开始标签。
它准确地告诉您堆栈跟踪中发生了什么:
引起:java.lang.ArrayIndexOutOfBoundsException: length=9;索引=9 在 com.example.tictactoe.MainActivity.playertap(MainActivity.java:32)
MainActivity
的第 32 行超出了数组范围,并抛出异常 (ArrayIndexOutOfBoundsException
)。与以索引 1 开头的 ImageView
不同,该数组是基于 0 的索引。
您需要调整数组索引,使它们位于
0-8
而不是 1-9
的范围内,方法是使用 tappedImage - 1
我制作了新的Tic-Tac-Toe,也称为圈和十字或X和O,其根源可以追溯到古埃及,那里也有类似的游戏。它穿过罗马帝国,演变成我们今天所熟知的游戏。 玩得开心。你也玩谷歌