目录
前言
本项目是一个基于Android Studio的拼图游戏应用程序。通过重新排列碎片的方式,将乱序的图片拼接成完整的图片。该应用程序具有计时功能,记录玩家完成拼图所需的时间,并提供重新开始按钮,方便玩家重新挑战。
一、项目概述
1、构成以及功能设计
①.启动页
②游戏页面
- 实现拼图游戏
-计时器
二、开发环境
我的开发环境如下,大家的AS版本不需要和我相同,只要是近两年从官网下载的版本,都是比4.0.0(2020版)高的,是可以满足运行和开发要求的。
三、准备内容
需要准备一张照片,并且将照片分割成9份
四、详细设计
1、新建工程
-
首先打开Android Studio,并新建一个工程,File——>New——>New Project——>Empty Project,工程名称叫做SawPuzzle,可以根据自己喜好设置名称。
-
包名自己随意设定,这里博主用的是com.example,一般是com.example;工程文件的保存路径要修改一下,不要放在C盘,我这里选择的是放在H盘,养成项目统一放在英文路径下的好习惯。
-
最后选择API 24:Android 7.0,因为这样它就拥有了96.3%的跨平台性(兼容性非常好),因为它版本很低,基本上模拟器API版本都是高于20的,所以这个软件可以运行其他各种设备上。点击Finish完成创建。
-
2、搭建启动页
设计一个app的时候,一定要先设计layout文件,再设计java文件,因为布局有了,才能在上面进行代码的编写。我们来看一下activity_start.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"
android:background="@drawable/start"
tools:context=".Start.StartActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
然后回到我们的Activity文件,启动页逻辑代码如下:
package com.example.sawpuzzle.Start;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import androidx.appcompat.app.AppCompatActivity;
import com.example.sawpuzzle.MainActivity;
import com.example.sawpuzzle.R;
public class StartActivity extends AppCompatActivity {
TimeCount timeCount;
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
tomainActive();
}
};
// 进入主页面
private void tomainActive() {
startActivity(new Intent(this, MainActivity.class));
// 跳转完成后注销
finish();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
}
// 计时器
class TimeCount extends CountDownTimer {
public TimeCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onTick(long l) {
}
@Override
public void onFinish() {
}
}
}
3、搭建游戏界面
图片碎片的随机排列:通过定义一个图片数组的下标数组,随机打乱数组元素的顺序,从而实现图片碎片的随机排列。
图片碎片的移动:通过按钮的点击事件,判断选中的图片碎片是否可以移动,并且将移动后的图片位置更新到存储图片位置数组中,同时更新空白区域的位置。
判断拼图是否成功:在每次移动完成后,判断是否完成了拼图游戏。通过遍历存储图片位置数组,判断每个位置上的图片是否与预期位置一致,从而确定游戏是否成功。
计时功能和重新开始:通过Handler实现计时功能,每隔一秒更新计时器的显示。同时,提供重新开始按钮,点击按钮后将游戏状态和计时器还原,并重新打乱图片碎片的顺序。
activity_main.xml页面布局代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity"
android:padding="20dp">
<TextView
android:id="@+id/pt_tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="时间 : 0"
android:textColor="#FF0000"
android:textSize="20sp" />
<LinearLayout
android:id="@+id/pt_line1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
<ImageButton
android:id="@+id/pt_ib_00x00"
android:layout_width="100dp"
android:layout_height="140dp"
android:onClick="onClick"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="@drawable/xx_01" />
<ImageButton
android:id="@+id/pt_ib_00x02"
android:layout_width="100dp"
android:layout_height="140dp"
android:onClick="onClick"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="@drawable/xx_03" />
</LinearLayout>
<LinearLayout
android:id="@+id/pt_line2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
<ImageButton
android:id="@+id/pt_ib_01x02"
android:layout_width="100dp"
android:layout_height="140dp"
android:onClick="onClick"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="@drawable/xx_06" />
</LinearLayout>
<LinearLayout
android:id="@+id/pt_line3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
<ImageButton
android:id="@+id/pt_ib_02x00"
android:layout_width="100dp"
android:layout_height="140dp"
android:onClick="onClick"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="@drawable/xx_07" />
<ImageButton
android:id="@+id/pt_ib_02x02"
android:layout_width="100dp"
android:layout_height="140dp"
android:onClick="onClick"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="@drawable/xx_09"
android:visibility="invisible" />
</LinearLayout>
<Button
android:id="@+id/pt_btn_restart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:onClick="restart"
android:text="重新开始" />
<ImageView
android:id="@+id/pt_iv"
android:layout_width="99dp"
android:layout_height="131dp"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:src="@drawable/xx" />
</LinearLayout>
对应的逻辑代码:
package com.example.sawpuzzle;
public class MainActivity extends AppCompatActivity {
ImageButton ib00,ib01,ib02,ib10,ib11,ib12,ib20,ib21,ib22;
Button restartBtn;
TextView timeTv;
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what==1) {
time++;
timeTv.setText("时间 : "+time+" 秒");
handler.sendEmptyMessageDelayed(1,1000);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
// 打乱碎片的函数
disruptRandom();
handler.sendEmptyMessageDelayed(1,1000);
}
// 随机排列到指定的控件上
ib00.setImageResource(image[imageIndex[0]]);
ib01.setImageResource(image[imageIndex[1]]);
ib02.setImageResource(image[imageIndex[2]]);
ib10.setImageResource(image[imageIndex[3]]);
ib11.setImageResource(image[imageIndex[4]]);
ib12.setImageResource(image[imageIndex[5]]);
ib20.setImageResource(image[imageIndex[6]]);
ib21.setImageResource(image[imageIndex[7]]);
ib22.setImageResource(image[imageIndex[8]]);
}
/* 初始化控件*/
private void initView() {
ib00 = findViewById(R.id.pt_ib_00x00);
ib01 = findViewById(R.id.pt_ib_00x01);
ib02 = findViewById(R.id.pt_ib_00x02);
ib10 = findViewById(R.id.pt_ib_01x00);
ib11 = findViewById(R.id.pt_ib_01x01);
ib12 = findViewById(R.id.pt_ib_01x02);
ib20 = findViewById(R.id.pt_ib_02x00);
ib21 = findViewById(R.id.pt_ib_02x01);
ib22 = findViewById(R.id.pt_ib_02x02);
timeTv = findViewById(R.id.pt_tv_time);
restartBtn = findViewById(R.id.pt_btn_restart);
}
public void onClick(View view) {
int id = view.getId();
// 九个按钮执行的点击事件的逻辑应该是相同的,如果有空格在周围,可以改变图片显示的位置,否则点击事件不响应
switch (id) {
case R.id.pt_ib_00x00:
move(R.id.pt_ib_00x00,0);
break;
case R.id.pt_ib_00x01:
move(R.id.pt_ib_00x01,1);
break;
case R.id.pt_ib_00x02:
move(R.id.pt_ib_00x02,2);
break;
case R.id.pt_ib_01x00:
move(R.id.pt_ib_01x00,3);
break;
case R.id.pt_ib_01x01:
move(R.id.pt_ib_01x01,4);
break;
case R.id.pt_ib_01x02:
move(R.id.pt_ib_01x02,5);
break;
case R.id.pt_ib_02x00:
move(R.id.pt_ib_02x00,6);
break;
case R.id.pt_ib_02x01:
move(R.id.pt_ib_02x01,7);
break;
case R.id.pt_ib_02x02:
move(R.id.pt_ib_02x02,8);
break;
}
}
/* 判断拼图是否成功*/
private void judgeGameOver() {
boolean loop = true; //定义标志位
for (int i = 0; i < imageIndex.length; i++) {
if (imageIndex[i]!=i) {
loop = false;
break;
}
}
if (loop) {
// 拼图成功了
// 停止计时
handler.removeMessages(1);
// 拼图成功后,禁止玩家继续移动按钮
ib00.setClickable(false);
ib01.setClickable(false);
ib02.setClickable(false);
ib10.setClickable(false);
ib11.setClickable(false);
ib12.setClickable(false);
ib20.setClickable(false);
ib21.setClickable(false);
ib22.setClickable(false);
ib22.setImageResource(image[8]);
ib22.setVisibility(View.VISIBLE);
// 弹出提示用户成功的对话框
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("恭喜,拼图成功!您用的时间为"+time+"秒")
.setPositiveButton("确认",null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
/* 重新开始按钮的点击事件*/
public void restart(View view) {
// 将状态还原
restore();
// 将拼图重新打乱
disruptRandom();
handler.removeMessages(1);
// 将时间重新归0,并且重新开始计时
time = 0;
timeTv.setText("时间 : "+time+" 秒");
handler.sendEmptyMessageDelayed(1,1000);
}
private void restore() {
// 拼图游戏重新开始,允许完成移动碎片按钮
ib00.setClickable(true);
ib01.setClickable(true);
ib02.setClickable(true);
ib10.setClickable(true);
ib11.setClickable(true);
ib12.setClickable(true);
ib20.setClickable(true);
ib21.setClickable(true);
ib22.setClickable(true);
// 还原被点击的图片按钮变成初始化的模样
ImageButton clickBtn = findViewById(blankImgid);
clickBtn.setVisibility(View.VISIBLE);
}
}
五、运行演示
Android studio期末设计大作业~拼图游戏App
Get 项目模板源码
👇👇👇快捷获取方式👇👇👇