Android滑动拼图游戏启动闪退,报NullPointerException求助
滑动拼图游戏启动闪退问题解决
问题根源
闪退的直接原因是空指针异常:GameActivity的onCreate方法中,先调用了loadNumbers(),但这个方法里需要访问group.getChildCount(),而group此时还未被初始化——group是在loadViews()中通过findViewById获取的,调用顺序颠倒导致group为null,触发异常。
另外代码里还有几处逻辑和布局不匹配的问题,也会导致后续运行异常:
- 布局中
groupPuzzle内只有12个按钮,但tiles数组定义为长度16,循环逻辑也按16个元素处理,和实际控件数量不符; - 按钮的
tag设置错误,比如第四行的buttonJ标签是"10",但实际它属于第4行(索引3)第1列(索引0),标签应该设为"30",否则点击时获取的行列坐标错误,无法正常判断移动逻辑; buttons数组定义为new Button[3][4],但实际布局是4行3列,数组维度搞反了,会导致数组越界。
修复步骤
1. 调整onCreate方法的调用顺序
把loadViews()放在最前面,确保group初始化后再调用其他依赖它的方法:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_game); loadViews(); // 先初始化控件引用 loadNumbers(); generateNumbers(); loadDataToViews(); }
2. 修正数组和循环逻辑
根据布局中12个按钮(11个带数字,1个空白)的实际情况,修改相关代码:
loadNumbers()中调整数组长度和循环范围:
private void loadNumbers(){ tiles = new int[11]; // 实际只有11个带数字的按钮 for(int i =0; i< group.getChildCount() -1;i++){ tiles[i]=i+1; } }
generateNumbers()中调整随机交换的范围:
private void generateNumbers(){ int n = 10; // 11个元素,索引0-10 Random random = new Random(); while (n>0){ int randomNum = random.nextInt(n+1); int temp = tiles[randomNum]; tiles[randomNum]=tiles[n]; tiles[n] =temp; n--; } if(!isSolvable()) generateNumbers(); }
isSolvable()中调整循环范围:
private boolean isSolvable(){ int countInversion = 0; for (int i = 0; i<11;i++){ // 遍历11个数字 for (int j =0; j<i; j++){ if(tiles[j]>tiles[i]) countInversion++; } } return countInversion%2 == 0; }
3. 修正按钮数组维度和标签
loadViews()中把buttons数组改为4行3列:
private void loadViews(){ group = findViewById(R.id.groupPuzzle); buttons = new Button[4][3]; // 4行3列对应布局 for (int i =0; i<group.getChildCount();i++){ buttons[i/3][i%3] = (Button) group.getChildAt(i); // 行索引i/3,列索引i%3 } }
- 修改
activity_game.xml中所有按钮的tag,格式为"行号列号"(行和列都从0开始):
<!-- 示例修正部分按钮tag,其余按钮按对应行列修改 --> <Button android:id="@+id/buttonA" android:onClick="buttonClick" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:tag="00" <!-- 第0行第0列 --> android:text="A" style="@style/ButtonStyle" /> <Button android:id="@+id/buttonJ" android:onClick="buttonClick" android:layout_alignParentStart="true" android:layout_below="@+id/buttonG" android:tag="30" <!-- 第3行第0列 --> android:text="J" style="@style/ButtonStyle" /> <Button android:id="@+id/freeButton" android:onClick="buttonClick" android:layout_below="@+id/buttonI" android:layout_toEndOf="@+id/buttonK" android:tag="32" <!-- 第3行第2列 --> android:text="-" android:background="@color/colorFreeButton" style="@style/ButtonStyle" />
4. 修正loadDataToViews和checkWin中的循环逻辑
确保循环范围和实际控件数量匹配:
private void loadDataToViews(){ emptyX=3; emptyY=2; // 空白按钮在第3行第2列 for(int i = 0; i <group.getChildCount()-1; i++){ buttons[i/3][i%3].setText(String.valueOf(tiles[i])); buttons[i/3][i%3].setBackgroundResource(android.R.drawable.btn_default); } buttons[emptyX][emptyY].setText(""); buttons[emptyX][emptyY].setBackgroundColor(ContextCompat.getColor(this,R.color.colorFreeButton)); } private void checkWin(){ boolean isWin = false; if(emptyX==3 && emptyY==2){ isWin = true; for (int i = 0; i < group.getChildCount()-1; i++){ if(!buttons[i/3][i%3].getText().toString().equals(String.valueOf(i+1))){ isWin = false; break; } } } if (isWin){ Toast.makeText(this, "MENANG", Toast.LENGTH_SHORT).show(); for (int i = 0; i <group.getChildCount();i++){ buttons[i/3][i%3].setClickable(false); } } }
验证修复
完成上述修改后,重新编译运行,点击启动按钮即可正常进入GameActivity,滑动拼图功能也能正常工作。
内容的提问来源于stack exchange,提问作者lanaksa
相关产品推荐
相关产品推荐

