拼图游戏
- 项目简介
- 权限
- adapter
- PictureListAdapter
- PuzzleAdapter
- bean
- ItemBean
- Presenter
- IPuzzlePresenter
- PuzzlePresenterImpl
- ui
- IGameCallback
- utils
- Constant
- ImagesUtils
- ScreenUtils
- View
- MainActivity
- PuzzleActivity
- 布局
- activity_main.xml
- activity_puzzle.xml
项目简介
选择图片,生成拼图,通过移动拼图还原图片通关游戏,选择界面如下
游戏界面如下
采用MVP架构,项目结构如下
权限
需要读取相册中的图片
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
adapter
PictureListAdapter
public class PictureListAdapter extends BaseAdapter {
private Context mContext;
private List<Bitmap> mBitmapList;
public PictureListAdapter(Context context, List<Bitmap> bitmapList) {
mContext = context;
mBitmapList = bitmapList;
}
@Override
public int getCount() {
return mBitmapList.size();
}
@Override
public Object getItem(int position) {
return mBitmapList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView item = new ImageView(mContext);
item.setImageBitmap(mBitmapList.get(position));
return item;
}
}
PuzzleAdapter
public class PuzzleAdapter extends BaseAdapter {
private List<ItemBean> mItemBeanList;
public PuzzleAdapter() {
mItemBeanList = new ArrayList<>();
}
public void setData(List<ItemBean> itemBeanList) {
mItemBeanList.clear();
for (ItemBean itemBean : itemBeanList) {
try {
mItemBeanList.add((ItemBean) itemBean.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
@Override
public int getCount() {
return mItemBeanList.size();
}
@Override
public Object getItem(int position) {
return mItemBeanList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView item = new ImageView(parent.getContext());
/*item.setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.MATCH_PARENT, GridView.LayoutParams.MATCH_PARENT));
item.setScaleType(ImageView.ScaleType.FIT_XY);*/
item.setImageBitmap(mItemBeanList.get(position).getBitmap());
return item;
}
}
bean
ItemBean
public class ItemBean implements Cloneable {
private int mOriID; //表示拼图原始顺序
private int mPuzzleID; //表示拼图打乱后的顺序
private Bitmap mBitmap;
public ItemBean() {
}
public ItemBean(int oriID, int puzzleID, Bitmap bitmap) {
mOriID = oriID;
mPuzzleID = puzzleID;
mBitmap = bitmap;
}
public int getOriID() {
return mOriID;
}
public void setOriID(int oriID) {
mOriID = oriID;
}
public int getPuzzleID() {
return mPuzzleID;
}
public void setPuzzleID(int puzzleID) {
mPuzzleID = puzzleID;
}
public Bitmap getBitmap() {
return mBitmap;
}
public void setBitmap(Bitmap bitmap) {
mBitmap = bitmap;
}
@Override
public String toString() {
return "ItemBean{" +
"mOriID=" + mOriID +
", mPuzzleID=" + mPuzzleID +
", mBitmap=" + mBitmap +
'}';
}
@NonNull
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Presenter
IPuzzlePresenter
public interface IPuzzlePresenter {
enum STATE {
SUCCESS, FAILED_STEP, FAILED_TIME
}
void registerGameCallback(IGameCallback gameControl);
void unRegisterGameCallback();
//生成拼图数据
void loadPuzzleData(Context context, Bitmap oriBitmap);
//复位拼图
void resetGame();
//交换拼图
void swapPuzzle(int position);
//生成新的游戏
void restartGame();
}
PuzzlePresenterImpl
public class PuzzlePresenterImpl implements IPuzzlePresenter {
private static final String TAG = "PuzzlePresenterImpl";
private IGameCallback mCallback;
private ItemBean mLastBitmap;
private Bitmap mOriBitmap;
private List<ItemBean> mPuzzleList;
private List<ItemBean> mResetList;
private int mType;
private Map<Integer, Integer> mCountDownMap;
private Map<Integer, Integer> mStepCountMap;
private int mCurrentStep;
private int mCurrentTime;
private Timer mTimer;
private TimerTask mTimerTask;
public PuzzlePresenterImpl(int type) {
mPuzzleList = new ArrayList<>();
mResetList = new ArrayList<>();
mType = type;
mCountDownMap = new HashMap<>();
mCountDownMap.put(2, 180);
mCountDownMap.put(3, 300);
mCountDownMap.put(4, 600);
mStepCountMap = new HashMap<>();
mStepCountMap.put(2, 10);
mStepCountMap.put(3, 150);
mStepCountMap.put(4, 500);
}
@Override
public void registerGameCallback(IGameCallback callback) {
this.mCallback = callback;
}
@Override
public void unRegisterGameCallback() {
mTimer.cancel();
/*mPuzzleList.clear();
mResetList.clear();*/
this.mCallback = null;
}
@Override
public void loadPuzzleData(Context context, Bitmap oriBitmap) {
Log.d(TAG, "loadPuzzleData: ");
initPuzzle(context, oriBitmap);
startGame();
}
private void startGame() {
shufflePuzzle();
cloneItemBeanList(mPuzzleList, mResetList);
initCountDown();
if (mCallback != null) {
mCallback.onLoadPuzzleData(mOriBitmap, mPuzzleList);
}
startCountDown();
}
private void cloneItemBeanList(List<ItemBean> from, List<ItemBean> to) {
if (to != null && to.size() != 0) {
to.clear();
}
for (ItemBean itemBean : from) {
try {
to.add((ItemBean) itemBean.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
private void initCountDown() {
mCurrentTime = mCountDownMap.get(mType);
mCurrentStep = mStepCountMap.get(mType);
}
private void initPuzzle(Context context, Bitmap oriBitmap) {
mOriBitmap = ImagesUtils.resizeBitmap(oriBitmap, ScreenUtils.getScreenWidthPixels(context), ScreenUtils.getScreenWidthPixels(context));
int itemWidth = mOriBitmap.getWidth() / mType;
int itemHeight = mOriBitmap.getHeight() / mType;
for (int i = 1; i <= mType; i++) {
for (int j = 1; j <= mType; j++) {
Bitmap bitmap = Bitmap.createBitmap(
mOriBitmap,
(j - 1) * itemWidth,
(i - 1) * itemHeight,
itemWidth,
itemHeight);
mPuzzleList.add(new ItemBean((i - 1) * mType + j, (i - 1) * mType + j, bitmap));
}
}
//取出最后一个图片,当拼图完成时补充
mLastBitmap = mPuzzleList.remove(mType * mType - 1);
//将空的图片插入到最后
mPuzzleList.add(new ItemBean(mType * mType, 0,
ImagesUtils.createBitmap(
mOriBitmap.getWidth() / mType,
mOriBitmap.getHeight() / mType,
"空白格")));
}
private void startCountDown() {
mTimer = new Timer(true);
mTimerTask = new TimerTask() {
@Override
public void run() {
Log.d(TAG, "run: Thread = " + Thread.currentThread().getId() + ", mCurrentTime = " + mCurrentTime);
mCurrentTime--;
if (mCallback != null) {
mCallback.onCountDown(mCurrentTime, mCurrentStep);
if (mCurrentTime == 0) {
finishGame(STATE.FAILED_TIME);
}
}
}
};
mTimer.schedule(mTimerTask, 0, 1000);
}
@Override
public void resetGame() {
for (ItemBean itemBean : mPuzzleList) {
Log.d(TAG, "resetGame: mPuzzleList = " + itemBean);
}
for (ItemBean itemBean : mResetList) {
Log.d(TAG, "resetGame: mResetList = " + itemBean);
}
Log.d(TAG, "resetGame: --------------");
cloneItemBeanList(mResetList, mPuzzleList);
initCountDown();
if (mCallback != null) {
mCallback.onResetGame(mPuzzleList);
}
for (ItemBean itemBean : mPuzzleList) {
Log.d(TAG, "resetGame: mPuzzleList = " + itemBean);
}
for (ItemBean itemBean : mResetList) {
Log.d(TAG, "resetGame: mResetList = " + itemBean);
}
Log.d(TAG, "resetGame: --------------");
}
@Override
public void swapPuzzle(int position) {
if (mCallback != null) {
mCallback.onSwapPuzzle(isMovable(position), mPuzzleList);
mCurrentStep--;
mCallback.onCountDown(mCurrentTime, mCurrentStep);
if (isSuccess()) {
finishGame(STATE.SUCCESS);
} else if (mCurrentStep == 0) {
finishGame(STATE.FAILED_STEP);
}
}
}
private void finishGame(STATE state) {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
mTimerTask = null;
}
mCallback.onFinishGame(state);
}
@Override
public void restartGame() {
startGame();
}
private ItemBean getBlankBitmap() {
for (ItemBean itemBean : mPuzzleList) {
if (itemBean.getPuzzleID() == 0) {
return itemBean;
}
}
return null;
}
private boolean isMovable(int position) {
int blankPosition = getBlankBitmap().getOriID() - 1;
if ((Math.abs(blankPosition - position) == mType //判断上下
|| ((blankPosition / mType == position / mType) && Math.abs(blankPosition - position) == 1))) { //判断左右
swapItem(mPuzzleList.get(position), getBlankBitmap());
return true;
}
return false;
}
private void swapItem(ItemBean from, ItemBean blankBitmap) {
if (from == blankBitmap) {
return;
}
ItemBean temp = new ItemBean();
temp.setPuzzleID(from.getPuzzleID());
temp.setBitmap(from.getBitmap());
from.setPuzzleID(blankBitmap.getPuzzleID());
from.setBitmap(blankBitmap.getBitmap());
blankBitmap.setPuzzleID(temp.getPuzzleID());
blankBitmap.setBitmap(temp.getBitmap());
}
private boolean isSuccess() {
boolean isSuccess = true;
for (ItemBean bean : mPuzzleList) {
if (bean.getPuzzleID() != 0 && bean.getOriID() == bean.getPuzzleID()) { //非空白格,两个ID相等
continue;
} else if (bean.getPuzzleID() == 0 && bean.getOriID() == mType * mType) { //空白格,源ID等于最后一个
continue;
} else {
isSuccess = false;
}
}
return isSuccess;
}
private void shufflePuzzle() {
for (int i = 0; i < mPuzzleList.size(); i++) { //打乱顺序
int index = (int) (Math.random() * mPuzzleList.size());
swapItem(mPuzzleList.get(index), getBlankBitmap());
}
List<Integer> data = new ArrayList<>();
for (int i = 0; i < mPuzzleList.size(); i++) {
data.add(mPuzzleList.get(i).getPuzzleID());
}
if (!canSolve(data, getBlankBitmap().getOriID()) || isSuccess()) {
shufflePuzzle();
}
}
private boolean canSolve(List<Integer> data, int blankPosition) {
// 个数为奇数时,倒置和为偶数才有解
if (data.size() % 2 == 1) {
return getInversions(data) % 2 == 0;
} else { //个数为偶数时
if (((blankPosition - 1) / mType) % 2 == 1) { //空格位于奇数行,倒置和为偶数才有解
return getInversions(data) % 2 == 0;
} else { //空格位于偶数行,倒置和为奇数才有解
return getInversions(data) % 2 == 1;
}
}
}
//计算比第i位元素小的元素个数的总和,如[3,2,1],倒置和为[2,1,0] = 3
private int getInversions(List<Integer> data) {
int inversions = 0;
int inversionCount = 0;
for (int i = 0; i < data.size(); i++) {
for (int j = i + 1; j < data.size(); j++) {
int index = data.get(i);
if (data.get(j) != 0 && data.get(j) < index)
inversionCount++;
}
inversions += inversionCount;
inversionCount = 0;
}
return inversions;
}
}
ui
IGameCallback
public interface IGameCallback {
//获取拼图数据
void onLoadPuzzleData(Bitmap resizeOriBitmap, List<ItemBean> itemBeanList);
//交换拼图
void onSwapPuzzle(boolean isMovable, List<ItemBean> itemBeanList);
//倒计时
void onCountDown(int time, int step);
//结束游戏
void onFinishGame(IPuzzlePresenter.STATE state);
//复位游戏
void onResetGame(List<ItemBean> itemBeanList);
}
utils
Constant
public class Constant {
public static final String ORIGINAL_BITMAP = "Original_Bitmap";
public static final String PUZZLE_TYPE = "puzzle_type";
}
ImagesUtils
public class ImagesUtils {
//生成带文字的图片
public static Bitmap createBitmap(int bitmapWidth, int bitmapHeight, String text) {
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.GRAY);
if (!TextUtils.isEmpty(text)) {
Paint textPaint = new Paint();
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(bitmapWidth / text.length());
float textWidth = textPaint.measureText(text, 0, text.length()); //用于水平居中
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float offset = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; //用于垂直居中
canvas.drawText(text, (bitmapWidth - textWidth) / 2f, bitmapWidth / 2f + offset, textPaint);
}
return bitmap;
}
//修改图片大小
public static Bitmap resizeBitmap(Bitmap bitmap, float newWidth, float newHeight) {
Matrix matrix = new Matrix();
matrix.postScale(newWidth / bitmap.getWidth(), newHeight / bitmap.getHeight());
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
}
ScreenUtils
public class ScreenUtils {
public static DisplayMetrics getDisplayMetrics(Context context) {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
display.getMetrics(metrics);
return metrics;
}
public static int getScreenWidthPixels(Context context) {
return getDisplayMetrics(context).widthPixels;
}
public static int getScreenHeightPixels(Context context) {
return getDisplayMetrics(context).heightPixels;
}
}
View
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView mTypeSelector;
private GridView mPicSelector;
private static final int RESULT_IMAGE = 100;
private static final int RESULT_CAMERA = 200;
private int mCurrentType = 2;
private String[] mPicStrings = new String[]{
"赵", "钱", "孙", "李",
"周", "吴", "郑", "王",
"冯", "陈", "褚", "卫",
"蒋", "沈", "韩", "选择图片"
};
private int mPicListColumns = (int) Math.sqrt(mPicStrings.length);
private String mCameraTempPath;
private List<Bitmap> mPicList;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
initListener();
}
private void initListener() {
mTypeSelector.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCurrentType == 4) {
mCurrentType = 2;
} else {
mCurrentType++;
}
mTypeSelector.setText(mCurrentType + " × " + mCurrentType);
}
});
mPicSelector.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == mPicStrings.length - 1) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setItems(new String[]{"从相册选择", "拍摄"}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "onClick: which = " + which);
if (which == 0) {
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, RESULT_IMAGE);
} else {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoUri = Uri.fromFile(new File(mCameraTempPath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, RESULT_CAMERA);
}
}
});
builder.show();
} else {
PuzzleActivity.startPuzzleActivity(MainActivity.this, mPicList.get(position), mCurrentType);
}
}
});
}
private void initView() {
mTypeSelector = findViewById(R.id.tv_type_selector);
mPicSelector = findViewById(R.id.gv_pic_list);
}
private void initData() {
mCameraTempPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/temp.png";
Log.d(TAG, "onClick: mImagePath = " + mCameraTempPath);
//解决上面路径报错问题
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
mPicSelector.setNumColumns(mPicListColumns);
mPicList = new ArrayList<>();
for (String string : mPicStrings) {
mPicList.add(ImagesUtils.createBitmap(
ScreenUtils.getScreenWidthPixels(this) / mPicListColumns,
ScreenUtils.getScreenWidthPixels(this) / mPicListColumns,
string));
}
mPicSelector.setAdapter(new PictureListAdapter(this, mPicList));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: resultCode = " + resultCode);
if (resultCode == RESULT_OK) {
Bitmap oriBitmap = null;
InputStream inputStream = null;
Log.d(TAG, "onActivityResult: requestCode = " + requestCode);
if (requestCode == RESULT_IMAGE && data != null) {
try {
inputStream = getContentResolver().openInputStream(data.getData());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else if (requestCode == RESULT_CAMERA) {
try {
inputStream = new FileInputStream(mCameraTempPath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = 4; //图片太大,缩放到1/4
options.inJustDecodeBounds = false;
oriBitmap = BitmapFactory.decodeStream(inputStream, null, options);
Log.d(TAG, "onActivityResult: oriBitmap = " + oriBitmap);
PuzzleActivity.startPuzzleActivity(MainActivity.this, oriBitmap, mCurrentType);
}
}
}
PuzzleActivity
public class PuzzleActivity extends AppCompatActivity implements View.OnClickListener, IGameCallback {
private static final String TAG = "PuzzleActivity";
private TextView mStep;
private TextView mCountDown;
private GridView mPuzzleGv;
private ImageView mOriPic;
private Button mShowPicBtn;
private Button mResetBtn;
private Button mBackBtn;
private PuzzleAdapter mPuzzleAdapter;
private IPuzzlePresenter mPuzzlePresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_puzzle);
initView();
initData();
initListener();
}
private void initView() {
mStep = findViewById(R.id.tv_step_count);
mCountDown = findViewById(R.id.tv_countdown);
mPuzzleGv = findViewById(R.id.gv_puzzle);
mOriPic = findViewById(R.id.iv_ori_pic);
mShowPicBtn = findViewById(R.id.btn_ori_pic);
mResetBtn = findViewById(R.id.btn_reset);
mBackBtn = findViewById(R.id.btn_back);
}
public static void startPuzzleActivity(Context context, Bitmap oriBitmap, int type) {
Intent intent = new Intent(context, PuzzleActivity.class);
intent.putExtra(Constant.ORIGINAL_BITMAP, oriBitmap);
intent.putExtra(Constant.PUZZLE_TYPE, type);
context.startActivity(intent);
}
private void initData() {
Intent intent = getIntent();
Bitmap oriBitmap = intent.getParcelableExtra(Constant.ORIGINAL_BITMAP);
int type = intent.getIntExtra(Constant.PUZZLE_TYPE, 2);
mPuzzleGv.setNumColumns(type);
mPuzzlePresenter = new PuzzlePresenterImpl(type);
mPuzzlePresenter.registerGameCallback(this);
mPuzzlePresenter.loadPuzzleData(this, oriBitmap);
/* print log start */
Log.d(TAG, "initData: oriBitmap = " + oriBitmap);
Log.d(TAG, "initData: type = " + type);
/* print log end */
}
private void showFinishDialog(String msg) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(msg);
builder.setCancelable(false);
builder.setNegativeButton("再来一次", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mPuzzlePresenter.restartGame();
dialog.dismiss();
}
});
builder.setPositiveButton("重选图片", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
builder.show();
}
private void initListener() {
mShowPicBtn.setOnClickListener(this);
mResetBtn.setOnClickListener(this);
mBackBtn.setOnClickListener(this);
mPuzzleGv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "onItemClick: position = " + position);
mPuzzlePresenter.swapPuzzle(position);
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_ori_pic:
Log.d(TAG, "onClick: btn_ori_pic");
if (mOriPic.getVisibility() == View.INVISIBLE) {
mPuzzleGv.setVisibility(View.INVISIBLE);
mOriPic.setVisibility(View.VISIBLE);
mShowPicBtn.setText("隐藏原图");
} else if (mOriPic.getVisibility() == View.VISIBLE) {
mPuzzleGv.setVisibility(View.VISIBLE);
mOriPic.setVisibility(View.INVISIBLE);
mShowPicBtn.setText("显示原图");
}
break;
case R.id.btn_reset:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("是否将拼图还原到最开始的状态");
builder.setCancelable(false);
builder.setNegativeButton("还原", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mPuzzlePresenter.resetGame();
}
});
builder.setPositiveButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
break;
case R.id.btn_back:
finish();
break;
}
}
@Override
public void onLoadPuzzleData(Bitmap resizeOriBitmap, List<ItemBean> itemBeanList) {
mOriPic.setImageBitmap(resizeOriBitmap);
updateUI(itemBeanList);
}
private void updateUI(List<ItemBean> itemBeanList) {
if (mPuzzleAdapter == null) {
mPuzzleAdapter = new PuzzleAdapter();
mPuzzleAdapter.setData(itemBeanList);
mPuzzleGv.setAdapter(mPuzzleAdapter);
} else {
mPuzzleAdapter.setData(itemBeanList);
mPuzzleAdapter.notifyDataSetChanged();
}
}
@Override
public void onSwapPuzzle(boolean isMovable, List<ItemBean> itemBeanList) {
if (isMovable) {
updateUI(itemBeanList);
} else {
Toast.makeText(this, "请点击空白格附近的图片进行交换", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCountDown(int time, int step) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mCountDown.setText("剩余时间: " + time / 60 + "分" + time % 60 + "秒");
mStep.setText("剩余步数: " + step);
}
});
}
@Override
public void onFinishGame(IPuzzlePresenter.STATE state) {
switch (state) {
case SUCCESS:
showFinishDialog("拼图成功");
break;
case FAILED_STEP:
showFinishDialog("步数已用完");
break;
case FAILED_TIME:
showFinishDialog("倒计时结束");
break;
}
}
@Override
public void onResetGame(List<ItemBean> itemBeanList) {
updateUI(itemBeanList);
}
@Override
protected void onDestroy() {
super.onDestroy();
mPuzzlePresenter.unRegisterGameCallback();
}
}
布局
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_type_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="10dp"
android:padding="3dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选择难度"
android:textSize="30sp" />
<TextView
android:id="@+id/tv_type_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:background="#33000000"
android:padding="3dp"
android:text="2 × 2"
android:textSize="25sp" />
</LinearLayout>
<GridView
android:id="@+id/gv_pic_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/ll_type_container"
android:horizontalSpacing="1dp"
android:verticalSpacing="1dp" />
</RelativeLayout>
activity_puzzle.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".view.PuzzleActivity">
<LinearLayout
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:id="@+id/tv_step_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#33000000"
android:padding="10dp"
android:text="步数"
android:textSize="25sp" />
<TextView
android:id="@+id/tv_countdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#33000000"
android:padding="10dp"
android:text="时间"
android:textSize="25sp" />
</LinearLayout>
<GridView
android:id="@+id/gv_puzzle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/ll_btns"
android:layout_below="@id/ll_title"
android:horizontalSpacing="2dp"
android:verticalSpacing="2dp" />
<ImageView
android:id="@+id/iv_ori_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/gv_puzzle"
android:visibility="invisible" />
<LinearLayout
android:id="@+id/ll_btns"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center">
<Button
android:id="@+id/btn_ori_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:background="#33000000"
android:text="显示原图"
android:textSize="30sp" />
<Button
android:id="@+id/btn_reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:background="#33000000"
android:text="复位"
android:textSize="30sp" />
<Button
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:background="#33000000"
android:text="返回"
android:textSize="30sp" />
</LinearLayout>
</RelativeLayout>