拼图小游戏
来源:互联网 发布:听广播的软件 编辑:程序博客网 时间:2024/04/30 14:58
自己动手,写出一个拼图类的小游戏。主要步骤如下:
1.将一张完整图片进行有序切割成若干小块;单个图片需要唯一标识itemId,以及拼图成功时的校验Id——bitmapId.
2.图片数组已经具备了,接下来就是打乱有序图片集合,这里进行两两置换,会用到2个bean进行数据交换
3.打乱图片集合后需要判断该集合是否有解,这个就根据唯一表示itemId来进行倒置和算法判断。
4.循环判断每个图片条目是否恢复到了原始状态,鉴别拼图成功与否。
以下是具体代码逻辑:
本项目中的图片来源通过拍照或者相册里面取,所以第一步是读取相册图片或者拍照获取到对应图片。注意在6.0以上的系统中,系统权限有了改变,所以到读取照片或者拍照的时候会用到读写内存卡的权限,所以第一件事是检验是否开放了权限:
/** * 检查权限 */ @TargetApi(Build.VERSION_CODES.M) private boolean checkNeededPermission() { if (checkSelfPermission( READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission( WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONCODE); return false; } else return true; }
还需要权限开启结果的回调来判断是否真的开启了权限:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == PERMISSIONCODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { selPic(); } else { Toast.makeText(PictureGameAct.this, "Permission Denied", Toast.LENGTH_SHORT).show(); } return; } super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
selPic()方法就是调起相机或者拍照:
public void selPic() { if (isTackPhoto) {//拍照 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/img.png"; Uri uri = Uri.fromFile(new File(path)); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, IMAGE_TACK_PICK_CODE); } else {//相册 Intent intent = new Intent(Intent.ACTION_PICK, null);//Intent.ACTION_PICK相册的action intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_TYPE); startActivityForResult(intent, IMAGE_PIC_CODE); } }
然后就是在onActivityResult中接收结果:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { if (requestCode == IMAGE_PIC_CODE) {//相册 if (data != null && data.getData() != null) { String filePath; Cursor cursor = getContentResolver().query(data.getData(), null, null, null, null); if (cursor != null) { cursor.moveToFirst(); filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); cursor.close(); } else { filePath = data.getData().getPath(); } getBitmapList(filePath); generateMapList(); setBitmapData(); } } else if (requestCode == IMAGE_TACK_PICK_CODE) {//拍照 getBitmapList(path); generateMapList(); setBitmapData(); } } }
getBitmapList方法是初始化图片资源,有序等分图片;generateMapList方法是打乱有序的图片资源;
setBitmapData是展示数据
/** * 初始化图片资源,有序等分图片 * * @param filePath */ private void getBitmapList(String filePath) { datas.clear(); Bitmap bitmap = BitmapFactory.decodeFile(filePath);//获取源文件 int itemWidth = bitmap.getWidth() / TYPE; int itemHeight = bitmap.getHeight() / TYPE; for (int i = 0; i < TYPE; i++) { for (int j = 0; j < TYPE; j++) { PicItemBean item = new PicItemBean(); item.bitmap = Bitmap.createBitmap(bitmap, itemWidth * j, itemHeight * i, itemWidth, itemHeight);//逐步剪裁图片 item.bitmapId = i*TYPE+j+1; item.itemId = i*TYPE+j+1; datas.add(item); } } datas.remove(TYPE * TYPE - 1);//移除最后一张图片,然后添加一张空白图片 PicItemBean item = new PicItemBean(); item.bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.back); item.itemId = TYPE * TYPE; item.bitmapId = 0; datas.add(item); mBlackItem = item;//先将最后一个item赋值给空白的item }
然后就是混合图片变成无序,并判断混合后的结果是否有解:
/** * 将图片进行混合成无序的 */ private void generateMapList() { for (int i = 0; i < datas.size(); i++) { int pos = (int) (Math.random() * TYPE * TYPE); swipeData(mBlackItem, datas.get(pos)); } List<Integer> idDatas = new ArrayList<Integer>(); for (int i = 0; i < datas.size(); i++) { idDatas.add(datas.get(i).bitmapId); } //判断生成是否有解 if (canSolve(idDatas)) { return; } else { generateMapList(); } } /** * 判断是否有解 * * @param data 拼图id数组数据 * @return */ public boolean canSolve(List<Integer> data) { //获取空格id int blackId = mBlackItem.itemId; if (data.size() % 2 == 1) { return getInversions(data) % 2 == 0; } else { //从下往上数,空格位于奇数行, if (((blackId - 1) / TYPE) % 2 == 1) { return getInversions(data) % 2 == 0; } else { //从下往上数,空格位于偶数行, return getInversions(data) % 2 == 1; } } } /** * 倒置和算法 * * @param data * @return 该序列的倒置和 */ public 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; } /** * 交换空白格数据和点击条目的数据 * * @param blackItem * @param item */ private void swipeData(PicItemBean blackItem, PicItemBean item) { int bitmapId = item.bitmapId; Bitmap bitmap = item.bitmap; item.bitmapId = blackItem.bitmapId; item.bitmap = blackItem.bitmap; blackItem.bitmap = bitmap; blackItem.bitmapId = bitmapId; mBlackItem = item;//注意,这里需要将空白格的值重新赋值,值为新的需要交换数据的item,这样就保证了空白格条目和集合中的空白格数据同步 }
这里补充一下图片bean:
public class PicItemBean { public Bitmap bitmap; public int bitmapId; public int itemId; @Override public String toString() { return "bitmap=" + bitmap.hashCode() + ",bitmapId==" + bitmapId + ",itemId=" + itemId; }}
最后就是显示数据了:
/** * 显示数据 */ public void setBitmapData() { adapter = new BitmapAdapter(this); gv.setAdapter(adapter); gv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { PicItemBean bean = datas.get(position); //判断四周是否有空格 if (couldChange(bean)) { swipeData(mBlackItem, bean); if (isSucceed()) {//拼图成功,将缺省的图片还原 datas.get(TYPE * TYPE - 1).bitmap = lastBimtap; } adapter.notifyDataSetChanged(); } } }); } /** * 点击条目是否可以和空白格交换位置数据 * 依据是当处于同一行的时候,他们的itemId相差1就说明两者可以交换位置,如果是不同行,只有相差TYPE时 * 才可以交换位置 * * @param bean * @return */ private boolean couldChange(PicItemBean bean) { if (Math.abs(bean.itemId - mBlackItem.itemId) == TYPE) { return true;//不同行的时候两个相差3就可以交换 } else if (Math.abs(bean.itemId - mBlackItem.itemId) == 1) {//同行相差1 return true; } return false; } /** * 拼图是否完成 * * @return */ private boolean isSucceed() { boolean result = true; for (int i = 0; i < datas.size(); i++) { PicItemBean item = datas.get(i); if (i < TYPE * TYPE - 1) { if (item.bitmapId != item.itemId) { result = false; break; } } else { if (item.bitmapId == 0 && item.itemId == TYPE * TYPE) { result = true; } else { result = false; } } } return result; }
在条目的点击事件中就需要判断是否可以交换数据,并且交换后拼图是否完成。
还有一个适配器就完成了
private class BitmapAdapter extends BaseAdapter { public BitmapAdapter(Context context) { } @Override public int getCount() { Log.d(TAG, "SIZE====" + datas.size()); return datas == null ? 0 : datas.size(); } @Override public Object getItem(int position) { return datas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(PictureGameAct.this).inflate(R.layout.item_img, null); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.iv = (ImageView) convertView.findViewById(R.id.iv); ViewGroup.LayoutParams layoutParams = holder.iv.getLayoutParams(); layoutParams.height = getScreenWidth() / 3; holder.iv.setLayoutParams(layoutParams); holder.iv.setImageBitmap(datas.get(position).bitmap); return convertView; } } private static class ViewHolder { ImageView iv; } public int getScreenWidth() { DisplayMetrics metrics = new DisplayMetrics(); WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(metrics); return metrics.widthPixels; }
整个拼图就已经完成了
源码下载地址
阅读全文
0 0
- 拼图小游戏
- 拼图小游戏
- java拼图小游戏
- JS数字拼图小游戏
- JavaScript拼图小游戏
- swift 拼图小游戏
- android 美女拼图小游戏
- iOS之拼图小游戏
- VS,C#--拼图小游戏
- java智力拼图小游戏
- 美女拼图小游戏
- Android—拼图小游戏
- Android移动拼图小游戏
- android-拼图小游戏
- Android 小游戏 :撸啊撸拼图
- java拼图小游戏
- Android-拼图小游戏
- c#拼图小游戏
- Hadoop集群搭建之二 集群环境部署说明+SSH
- 异常 java.lang.IllegalArgumentException:unexpected url:
- [Algorithms] 证明支配集问题是NP完全问题
- 排序算法之插入排序
- 数据结构之Kruskal算法(并查集的应用)
- 拼图小游戏
- 第一天,我在前进
- CIFS, NFS, iSCSI, UNC
- caffe如何做卷积
- CSS基础小仓库
- 30分钟部署以太坊私有链
- iOS开发中压缩图片的质量以及缩小图片尺寸
- UVA 140 带宽
- java 中为什么实体类需要实现序列化