├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lius │ │ └── puzzlegame │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lius │ │ │ └── puzzlegame │ │ │ ├── activity │ │ │ ├── MainActivity.java │ │ │ └── PuzzleMain.java │ │ │ ├── adapter │ │ │ ├── GridItemsAdapter.java │ │ │ └── GridPicListAdapter.java │ │ │ ├── bean │ │ │ └── ItemBean.java │ │ │ └── util │ │ │ ├── GameUtil.java │ │ │ ├── ImagesUtil.java │ │ │ └── ScreenUtil.java │ └── res │ │ ├── anim │ │ ├── image_hide_anim.xml │ │ └── image_show_anim.xml │ │ ├── drawable-hdpi │ │ ├── blank.png │ │ ├── pic1.jpg │ │ ├── pic10.jpg │ │ ├── pic11.jpg │ │ ├── pic12.jpg │ │ ├── pic13.jpg │ │ ├── pic14.jpg │ │ ├── pic15.jpg │ │ ├── pic2.jpg │ │ ├── pic3.jpg │ │ ├── pic4.jpg │ │ ├── pic5.jpg │ │ ├── pic6.jpg │ │ ├── pic7.jpg │ │ ├── pic8.jpg │ │ ├── pic9.jpg │ │ └── plus.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── beautybutton.xml │ │ ├── ic_launcher_background.xml │ │ └── textview_click.xml │ │ ├── layout │ │ ├── xpuzzle_main.xml │ │ ├── xpuzzle_main_type_selected.xml │ │ └── xpuzzle_puzzle_detail_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lius │ └── puzzlegame │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PuzzleGame 2 | 一个九宫格的拼图游戏。安卓练手小项目。 3 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "com.lius.puzzlegame" 7 | minSdkVersion 15 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:27.1.1' 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.1' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 28 | } 29 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lius/puzzlegame/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.lius.puzzlegame", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.activity; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.database.Cursor; 8 | import android.graphics.Bitmap; 9 | import android.graphics.BitmapFactory; 10 | import android.graphics.Color; 11 | import android.graphics.drawable.ColorDrawable; 12 | import android.graphics.drawable.Drawable; 13 | import android.net.Uri; 14 | import android.os.Bundle; 15 | import android.os.Environment; 16 | import android.provider.MediaStore; 17 | import android.view.Gravity; 18 | import android.view.LayoutInflater; 19 | import android.view.View; 20 | import android.view.View.OnClickListener; 21 | import android.widget.AdapterView; 22 | import android.widget.AdapterView.OnItemClickListener; 23 | import android.widget.GridView; 24 | import android.widget.PopupWindow; 25 | import android.widget.TextView; 26 | 27 | import com.lius.puzzlegame.R; 28 | import com.lius.puzzlegame.adapter.GridPicListAdapter; 29 | import com.lius.puzzlegame.util.ScreenUtil; 30 | 31 | import java.io.File; 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | /** 36 | * 程序主界面:显示默认图片列表、自选图片按钮 37 | * 38 | * @author chris 39 | */ 40 | public class MainActivity extends Activity implements OnClickListener { 41 | 42 | // 返回码:系统图库 43 | private static final int RESULT_IMAGE = 100; 44 | // 返回码:相机 45 | private static final int RESULT_CAMERA = 200; 46 | // IMAGE TYPE 47 | private static final String IMAGE_TYPE = "image/*"; 48 | // Temp照片路径 49 | public static String TEMP_IMAGE_PATH; 50 | // GridView 显示图片 51 | private GridView mGvPicList; 52 | private List mPicList; 53 | // 主页图片资源ID 54 | private int[] mResPicId; 55 | // 显示Type 56 | private TextView mTvPuzzleMainTypeSelected; 57 | private LayoutInflater mLayoutInflater; 58 | private PopupWindow mPopupWindow; 59 | private View mPopupView; 60 | private TextView mTvType2; 61 | private TextView mTvType3; 62 | private TextView mTvType4; 63 | // 游戏类型N*N 64 | private int mType = 2; 65 | // 本地图册、相机选择 66 | private String[] mCustomItems = new String[]{"本地图册", "相机拍照"}; 67 | 68 | @Override 69 | protected void onCreate(Bundle savedInstanceState) { 70 | super.onCreate(savedInstanceState); 71 | setContentView(R.layout.xpuzzle_main); 72 | 73 | TEMP_IMAGE_PATH = 74 | Environment.getExternalStorageDirectory().getPath() + 75 | "/temp.png"; 76 | mPicList = new ArrayList(); 77 | // 初始化Views 78 | initViews(); 79 | // 数据适配器 80 | mGvPicList.setAdapter(new GridPicListAdapter( 81 | MainActivity.this, mPicList)); 82 | // Item点击监听 83 | mGvPicList.setOnItemClickListener(new OnItemClickListener() { 84 | 85 | @Override 86 | public void onItemClick(AdapterView arg0, View view, 87 | int position, long arg3) { 88 | if (position == mResPicId.length - 1) { 89 | // 选择本地图库 相机 90 | showDialogCustom(); 91 | } else { 92 | // 选择默认图片 93 | Intent intent = new Intent( 94 | MainActivity.this, 95 | PuzzleMain.class); 96 | intent.putExtra("picSelectedID", mResPicId[position]); 97 | intent.putExtra("mType", mType); 98 | startActivity(intent); 99 | } 100 | } 101 | }); 102 | 103 | /** 104 | * 显示难度Type 105 | */ 106 | mTvPuzzleMainTypeSelected.setOnClickListener( 107 | new OnClickListener() { 108 | 109 | @Override 110 | public void onClick(View v) { 111 | // 弹出popup window 112 | popupShow(v); 113 | } 114 | }); 115 | } 116 | 117 | // 显示选择系统图库 相机对话框 118 | private void showDialogCustom() { 119 | AlertDialog.Builder builder = new AlertDialog.Builder( 120 | MainActivity.this); 121 | builder.setTitle("选择:"); 122 | builder.setItems(mCustomItems, 123 | new DialogInterface.OnClickListener() { 124 | 125 | @Override 126 | public void onClick(DialogInterface dialog, int which) { 127 | if (0 == which) { 128 | // 本地图册 129 | Intent intent = new Intent( 130 | Intent.ACTION_PICK, null); 131 | intent.setDataAndType( 132 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 133 | IMAGE_TYPE); 134 | startActivityForResult(intent, RESULT_IMAGE); 135 | } else if (1 == which) { 136 | // 系统相机 137 | Intent intent = new Intent( 138 | MediaStore.ACTION_IMAGE_CAPTURE); 139 | Uri photoUri = Uri.fromFile( 140 | new File(TEMP_IMAGE_PATH)); 141 | intent.putExtra( 142 | MediaStore.EXTRA_OUTPUT, 143 | photoUri); 144 | startActivityForResult(intent, RESULT_CAMERA); 145 | } 146 | } 147 | }); 148 | builder.create().show(); 149 | } 150 | 151 | /** 152 | * 调用图库相机回调方法 153 | */ 154 | @Override 155 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 156 | super.onActivityResult(requestCode, resultCode, data); 157 | if (resultCode == RESULT_OK) { 158 | if (requestCode == RESULT_IMAGE && data != null) { 159 | // 相册 160 | Cursor cursor = this.getContentResolver().query( 161 | data.getData(), null, null, null, null); 162 | cursor.moveToFirst(); 163 | String imagePath = cursor.getString( 164 | cursor.getColumnIndex("_data")); 165 | Intent intent = new Intent( 166 | MainActivity.this, 167 | PuzzleMain.class); 168 | intent.putExtra("picPath", imagePath); 169 | intent.putExtra("mType", mType); 170 | cursor.close(); 171 | startActivity(intent); 172 | } else if (requestCode == RESULT_CAMERA) { 173 | // 相机 174 | Intent intent = new Intent( 175 | MainActivity.this, 176 | PuzzleMain.class); 177 | intent.putExtra("mPicPath", TEMP_IMAGE_PATH); 178 | intent.putExtra("mType", mType); 179 | startActivity(intent); 180 | } 181 | } 182 | } 183 | 184 | /** 185 | * 显示popup window 186 | * 187 | * @param view popup window 188 | */ 189 | private void popupShow(View view) { 190 | int density = (int) ScreenUtil.getDeviceDensity(this); 191 | // 显示popup window 192 | mPopupWindow = new PopupWindow(mPopupView, 193 | 200 * density, 50 * density); 194 | mPopupWindow.setFocusable(true); 195 | mPopupWindow.setOutsideTouchable(true); 196 | // 透明背景 197 | Drawable transpent = new ColorDrawable(Color.TRANSPARENT); 198 | mPopupWindow.setBackgroundDrawable(transpent); 199 | // 获取位置 200 | int[] location = new int[2]; 201 | view.getLocationOnScreen(location); 202 | mPopupWindow.showAtLocation( 203 | view, 204 | Gravity.NO_GRAVITY, 205 | location[0] - 40 * density, 206 | location[1] + 30 * density); 207 | } 208 | 209 | /** 210 | * 初始化Views 211 | */ 212 | private void initViews() { 213 | mGvPicList = (GridView) findViewById( 214 | R.id.gv_xpuzzle_main_pic_list); 215 | // 初始化Bitmap数据 216 | mResPicId = new int[]{ 217 | R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, 218 | R.drawable.pic4, R.drawable.pic5, R.drawable.pic6, 219 | R.drawable.pic7, R.drawable.pic8, R.drawable.pic9, 220 | R.drawable.pic10, R.drawable.pic11, R.drawable.pic12, 221 | R.drawable.pic13, R.drawable.pic14, 222 | R.drawable.pic15, R.mipmap.ic_launcher}; 223 | Bitmap[] bitmaps = new Bitmap[mResPicId.length]; 224 | for (int i = 0; i < bitmaps.length; i++) { 225 | bitmaps[i] = BitmapFactory.decodeResource( 226 | getResources(), mResPicId[i]); 227 | mPicList.add(bitmaps[i]); 228 | } 229 | // 显示type 230 | mTvPuzzleMainTypeSelected = (TextView) findViewById( 231 | R.id.tv_puzzle_main_type_selected); 232 | mLayoutInflater = (LayoutInflater) getSystemService( 233 | LAYOUT_INFLATER_SERVICE); 234 | // mType view 235 | mPopupView = mLayoutInflater.inflate( 236 | R.layout.xpuzzle_main_type_selected, null); 237 | mTvType2 = (TextView) mPopupView.findViewById(R.id.tv_main_type_2); 238 | mTvType3 = (TextView) mPopupView.findViewById(R.id.tv_main_type_3); 239 | mTvType4 = (TextView) mPopupView.findViewById(R.id.tv_main_type_4); 240 | // 监听事件 241 | mTvType2.setOnClickListener(this); 242 | mTvType3.setOnClickListener(this); 243 | mTvType4.setOnClickListener(this); 244 | } 245 | 246 | /** 247 | * popup window item点击事件 248 | */ 249 | @Override 250 | public void onClick(View v) { 251 | switch (v.getId()) { 252 | // Type 253 | case R.id.tv_main_type_2: 254 | mType = 2; 255 | mTvPuzzleMainTypeSelected.setText("2 X 2"); 256 | break; 257 | case R.id.tv_main_type_3: 258 | mType = 3; 259 | mTvPuzzleMainTypeSelected.setText("3 X 3"); 260 | break; 261 | case R.id.tv_main_type_4: 262 | mType = 4; 263 | mTvPuzzleMainTypeSelected.setText("4 X 4"); 264 | break; 265 | default: 266 | break; 267 | } 268 | mPopupWindow.dismiss(); 269 | } 270 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/activity/PuzzleMain.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.activity; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.Message; 9 | import android.view.View; 10 | import android.view.View.OnClickListener; 11 | import android.view.animation.Animation; 12 | import android.view.animation.AnimationUtils; 13 | import android.widget.AdapterView; 14 | import android.widget.AdapterView.OnItemClickListener; 15 | import android.widget.Button; 16 | import android.widget.GridView; 17 | import android.widget.ImageView; 18 | import android.widget.RelativeLayout; 19 | import android.widget.RelativeLayout.LayoutParams; 20 | import android.widget.TextView; 21 | import android.widget.Toast; 22 | 23 | import com.lius.puzzlegame.R; 24 | import com.lius.puzzlegame.adapter.GridItemsAdapter; 25 | import com.lius.puzzlegame.bean.ItemBean; 26 | import com.lius.puzzlegame.util.GameUtil; 27 | import com.lius.puzzlegame.util.ImagesUtil; 28 | import com.lius.puzzlegame.util.ScreenUtil; 29 | 30 | import java.io.File; 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | import java.util.Timer; 34 | import java.util.TimerTask; 35 | 36 | /** 37 | * 拼图逻辑主界面:面板显示 38 | * 39 | * @author xys 40 | */ 41 | public class PuzzleMain extends Activity implements OnClickListener { 42 | 43 | // 拼图完成时显示的最后一个图片 44 | public static Bitmap mLastBitmap; 45 | // 设置为N*N显示 46 | public static int TYPE = 2; 47 | // 步数显示 48 | public static int COUNT_INDEX = 0; 49 | // 计时显示 50 | public static int TIMER_INDEX = 0; 51 | /** 52 | * UI更新Handler 53 | */ 54 | private Handler mHandler = new Handler() { 55 | 56 | @Override 57 | public void handleMessage(Message msg) { 58 | switch (msg.what) { 59 | case 1: 60 | // 更新计时器 61 | TIMER_INDEX++; 62 | mTvTimer.setText("" + TIMER_INDEX); 63 | break; 64 | default: 65 | break; 66 | } 67 | } 68 | }; 69 | // 选择的图片 70 | private Bitmap mPicSelected; 71 | // PuzzlePanel 72 | private GridView mGvPuzzleMainDetail; 73 | private int mResId; 74 | private String mPicPath; 75 | private ImageView mImageView; 76 | // Button 77 | private Button mBtnBack; 78 | private Button mBtnImage; 79 | private Button mBtnRestart; 80 | // 显示步数 81 | private TextView mTvPuzzleMainCounts; 82 | // 计时器 83 | private TextView mTvTimer; 84 | // 切图后的图片 85 | private List mBitmapItemLists = new ArrayList(); 86 | // GridView适配器 87 | private GridItemsAdapter mAdapter; 88 | // Flag 是否已显示原图 89 | private boolean mIsShowImg; 90 | // 计时器类 91 | private Timer mTimer; 92 | /** 93 | * 计时器线程 94 | */ 95 | private TimerTask mTimerTask; 96 | 97 | @Override 98 | protected void onCreate(Bundle savedInstanceState) { 99 | super.onCreate(savedInstanceState); 100 | setContentView(R.layout.xpuzzle_puzzle_detail_main); 101 | // 获取选择的图片 102 | Bitmap picSelectedTemp; 103 | // 选择默认图片还是自定义图片 104 | mResId = getIntent().getExtras().getInt("picSelectedID"); 105 | mPicPath = getIntent().getExtras().getString("mPicPath"); 106 | if (mResId != 0) { 107 | picSelectedTemp = BitmapFactory.decodeResource( 108 | getResources(), mResId); 109 | } else { 110 | picSelectedTemp = BitmapFactory.decodeFile(mPicPath); 111 | } 112 | TYPE = getIntent().getExtras().getInt("mType", 2); 113 | // 对图片处理 114 | handlerImage(picSelectedTemp); 115 | // 初始化Views 116 | initViews(); 117 | // 生成游戏数据 118 | generateGame(); 119 | // GridView点击事件 120 | mGvPuzzleMainDetail.setOnItemClickListener(new OnItemClickListener() { 121 | 122 | @Override 123 | public void onItemClick(AdapterView arg0, View view, 124 | int position, long arg3) { 125 | // 判断是否可移动 126 | if (GameUtil.isMoveable(position)) { 127 | // 交换点击Item与空格的位置 128 | GameUtil.swapItems( 129 | GameUtil.mItemBeans.get(position), 130 | GameUtil.mBlankItemBean); 131 | // 重新获取图片 132 | recreateData(); 133 | // 通知GridView更改UI 134 | mAdapter.notifyDataSetChanged(); 135 | // 更新步数 136 | COUNT_INDEX++; 137 | mTvPuzzleMainCounts.setText("" + COUNT_INDEX); 138 | // 判断是否成功 139 | if (GameUtil.isSuccess()) { 140 | // 将最后一张图显示完整 141 | recreateData(); 142 | mBitmapItemLists.remove(TYPE * TYPE - 1); 143 | mBitmapItemLists.add(mLastBitmap); 144 | // 通知GridView更改UI 145 | mAdapter.notifyDataSetChanged(); 146 | Toast.makeText(PuzzleMain.this, "拼图成功!", 147 | Toast.LENGTH_LONG).show(); 148 | mGvPuzzleMainDetail.setEnabled(false); 149 | mTimer.cancel(); 150 | mTimerTask.cancel(); 151 | } 152 | } 153 | } 154 | }); 155 | // 返回按钮点击事件 156 | mBtnBack.setOnClickListener(this); 157 | // 显示原图按钮点击事件 158 | mBtnImage.setOnClickListener(this); 159 | // 重置按钮点击事件 160 | mBtnRestart.setOnClickListener(this); 161 | } 162 | 163 | /** 164 | * Button点击事件 165 | */ 166 | @Override 167 | public void onClick(View v) { 168 | switch (v.getId()) { 169 | // 返回按钮点击事件 170 | case R.id.btn_puzzle_main_back: 171 | PuzzleMain.this.finish(); 172 | break; 173 | // 显示原图按钮点击事件 174 | case R.id.btn_puzzle_main_img: 175 | Animation animShow = AnimationUtils.loadAnimation( 176 | PuzzleMain.this, R.anim.image_show_anim); 177 | Animation animHide = AnimationUtils.loadAnimation( 178 | PuzzleMain.this, R.anim.image_hide_anim); 179 | if (mIsShowImg) { 180 | mImageView.startAnimation(animHide); 181 | mImageView.setVisibility(View.GONE); 182 | mIsShowImg = false; 183 | } else { 184 | mImageView.startAnimation(animShow); 185 | mImageView.setVisibility(View.VISIBLE); 186 | mIsShowImg = true; 187 | } 188 | break; 189 | // 重置按钮点击事件 190 | case R.id.btn_puzzle_main_restart: 191 | cleanConfig(); 192 | generateGame(); 193 | recreateData(); 194 | // 通知GridView更改UI 195 | mTvPuzzleMainCounts.setText("" + COUNT_INDEX); 196 | mAdapter.notifyDataSetChanged(); 197 | mGvPuzzleMainDetail.setEnabled(true); 198 | break; 199 | default: 200 | break; 201 | } 202 | } 203 | 204 | /** 205 | * 生成游戏数据 206 | */ 207 | private void generateGame() { 208 | // 切图 获取初始拼图数据 正常顺序 209 | new ImagesUtil().createInitBitmaps( 210 | TYPE, mPicSelected, PuzzleMain.this); 211 | // 生成随机数据 212 | GameUtil.getPuzzleGenerator(); 213 | // 获取Bitmap集合 214 | for (ItemBean temp : GameUtil.mItemBeans) { 215 | mBitmapItemLists.add(temp.getBitmap()); 216 | } 217 | // 数据适配器 218 | mAdapter = new GridItemsAdapter(this, mBitmapItemLists); 219 | mGvPuzzleMainDetail.setAdapter(mAdapter); 220 | // 启用计时器 221 | mTimer = new Timer(true); 222 | // 计时器线程 223 | mTimerTask = new TimerTask() { 224 | 225 | @Override 226 | public void run() { 227 | Message msg = new Message(); 228 | msg.what = 1; 229 | mHandler.sendMessage(msg); 230 | } 231 | }; 232 | // 每1000ms执行 延迟0s 233 | mTimer.schedule(mTimerTask, 0, 1000); 234 | } 235 | 236 | /** 237 | * 添加显示原图的View 238 | */ 239 | private void addImgView() { 240 | RelativeLayout relativeLayout = (RelativeLayout) findViewById( 241 | R.id.rl_puzzle_main_main_layout); 242 | mImageView = new ImageView(PuzzleMain.this); 243 | mImageView.setImageBitmap(mPicSelected); 244 | int x = (int) (mPicSelected.getWidth() * 0.9F); 245 | int y = (int) (mPicSelected.getHeight() * 0.9F); 246 | LayoutParams params = new LayoutParams(x, y); 247 | params.addRule(RelativeLayout.CENTER_IN_PARENT); 248 | mImageView.setLayoutParams(params); 249 | relativeLayout.addView(mImageView); 250 | mImageView.setVisibility(View.GONE); 251 | } 252 | 253 | /** 254 | * 返回时调用 255 | */ 256 | @Override 257 | protected void onStop() { 258 | super.onStop(); 259 | // 清空相关参数设置 260 | cleanConfig(); 261 | this.finish(); 262 | } 263 | 264 | /** 265 | * 清空相关参数设置 266 | */ 267 | private void cleanConfig() { 268 | // 清空相关参数设置 269 | GameUtil.mItemBeans.clear(); 270 | // 停止计时器 271 | mTimer.cancel(); 272 | mTimerTask.cancel(); 273 | COUNT_INDEX = 0; 274 | TIMER_INDEX = 0; 275 | // 清除拍摄的照片 276 | if (mPicPath != null) { 277 | // 删除照片 278 | File file = new File(MainActivity.TEMP_IMAGE_PATH); 279 | if (file.exists()) { 280 | file.delete(); 281 | } 282 | } 283 | } 284 | 285 | /** 286 | * 重新获取图片 287 | */ 288 | private void recreateData() { 289 | mBitmapItemLists.clear(); 290 | for (ItemBean temp : GameUtil.mItemBeans) { 291 | mBitmapItemLists.add(temp.getBitmap()); 292 | } 293 | } 294 | 295 | /** 296 | * 对图片处理 自适应大小 297 | * 298 | * @param bitmap bitmap 299 | */ 300 | private void handlerImage(Bitmap bitmap) { 301 | // 将图片放大到固定尺寸 302 | int screenWidth = ScreenUtil.getScreenSize(this).widthPixels; 303 | int screenHeigt = ScreenUtil.getScreenSize(this).heightPixels; 304 | mPicSelected = new ImagesUtil().resizeBitmap( 305 | screenWidth * 0.8f, screenHeigt * 0.6f, bitmap); 306 | } 307 | 308 | /** 309 | * 初始化Views 310 | */ 311 | private void initViews() { 312 | // Button 313 | mBtnBack = (Button) findViewById(R.id.btn_puzzle_main_back); 314 | mBtnImage = (Button) findViewById(R.id.btn_puzzle_main_img); 315 | mBtnRestart = (Button) findViewById(R.id.btn_puzzle_main_restart); 316 | // Flag 是否已显示原图 317 | mIsShowImg = false; 318 | // GridView 319 | mGvPuzzleMainDetail = (GridView) findViewById( 320 | R.id.gv_puzzle_main_detail); 321 | // 设置为N*N显示 322 | mGvPuzzleMainDetail.setNumColumns(TYPE); 323 | LayoutParams gridParams = new LayoutParams( 324 | mPicSelected.getWidth(), 325 | mPicSelected.getHeight()); 326 | // 水平居中 327 | gridParams.addRule(RelativeLayout.CENTER_HORIZONTAL); 328 | // 其他格式属性 329 | gridParams.addRule( 330 | RelativeLayout.BELOW, 331 | R.id.ll_puzzle_main_spinner); 332 | // Grid显示 333 | mGvPuzzleMainDetail.setLayoutParams(gridParams); 334 | mGvPuzzleMainDetail.setHorizontalSpacing(0); 335 | mGvPuzzleMainDetail.setVerticalSpacing(0); 336 | // TV步数 337 | mTvPuzzleMainCounts = (TextView) findViewById( 338 | R.id.tv_puzzle_main_counts); 339 | mTvPuzzleMainCounts.setText("" + COUNT_INDEX); 340 | // TV计时器 341 | mTvTimer = (TextView) findViewById(R.id.tv_puzzle_main_time); 342 | mTvTimer.setText("0秒"); 343 | // 添加显示原图的View 344 | addImgView(); 345 | } 346 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/adapter/GridItemsAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.adapter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.GridView; 9 | import android.widget.ImageView; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * 拼图主界面数据适配器 15 | * 16 | * @author Chris 17 | */ 18 | public class GridItemsAdapter extends BaseAdapter { 19 | 20 | // 映射List 21 | private List mBitmapItemLists; 22 | private Context mContext; 23 | 24 | public GridItemsAdapter(Context mContext, List picList) { 25 | this.mContext = mContext; 26 | this.mBitmapItemLists = picList; 27 | } 28 | 29 | @Override 30 | public int getCount() { 31 | return mBitmapItemLists.size(); 32 | } 33 | 34 | @Override 35 | public Object getItem(int position) { 36 | return mBitmapItemLists.get(position); 37 | } 38 | 39 | @Override 40 | public long getItemId(int position) { 41 | return position; 42 | } 43 | 44 | @Override 45 | public View getView(int position, View convertView, ViewGroup parent) { 46 | ImageView iv_pic_item = null; 47 | if (convertView == null) { 48 | iv_pic_item = new ImageView(mContext); 49 | // 设置布局 图片 50 | iv_pic_item.setLayoutParams(new GridView.LayoutParams( 51 | mBitmapItemLists.get(position).getWidth(), 52 | mBitmapItemLists.get(position).getHeight())); 53 | // 设置显示比例类型 54 | iv_pic_item.setScaleType(ImageView.ScaleType.FIT_CENTER); 55 | } else { 56 | iv_pic_item = (ImageView) convertView; 57 | } 58 | iv_pic_item.setImageBitmap(mBitmapItemLists.get(position)); 59 | return iv_pic_item; 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/adapter/GridPicListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.adapter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Color; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.BaseAdapter; 9 | import android.widget.GridView; 10 | import android.widget.ImageView; 11 | 12 | import com.lius.puzzlegame.util.ScreenUtil; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * 程序主界面数据适配器 18 | * 19 | * @author Chris 20 | */ 21 | public class GridPicListAdapter extends BaseAdapter { 22 | // 映射List 23 | private List picList; 24 | private Context context; 25 | 26 | public GridPicListAdapter(Context context, List picList) { 27 | this.context = context; 28 | this.picList = picList; 29 | } 30 | 31 | @Override 32 | public int getCount() { 33 | return picList.size(); 34 | } 35 | 36 | @Override 37 | public Object getItem(int position) { 38 | return picList.get(position); 39 | } 40 | 41 | @Override 42 | public long getItemId(int position) { 43 | return position; 44 | } 45 | 46 | @Override 47 | /** 48 | * 该方法在每个子项被滚动到屏幕内的时候会被调用 49 | * @param convertView 用于将之前加载好的布局进行缓存 50 | */ 51 | public View getView(int position, View convertView, ViewGroup arg2) { 52 | ImageView iv_pic_item = null; 53 | int density = (int) ScreenUtil.getDeviceDensity(context); 54 | if (convertView == null) { 55 | iv_pic_item = new ImageView(context); 56 | // 设置布局图片 57 | iv_pic_item.setLayoutParams(new GridView.LayoutParams( 58 | 80 * density, 59 | 100 * density)); 60 | // 设置显示比例类型 61 | iv_pic_item.setScaleType(ImageView.ScaleType.FIT_XY); 62 | } else { 63 | iv_pic_item = (ImageView) convertView; 64 | } 65 | iv_pic_item.setBackgroundColor(Color.BLACK); 66 | iv_pic_item.setImageBitmap(picList.get(position)); 67 | return iv_pic_item; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/bean/ItemBean.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.bean; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | /** 6 | * 拼图Item逻辑实体类:封装逻辑相关属性 7 | * 8 | * @author Chris 9 | */ 10 | public class ItemBean { 11 | 12 | // Item的Id 13 | private int mItemId; 14 | // bitmap的Id 15 | private int mBitmapId; 16 | // mBitmap 17 | private Bitmap mBitmap; 18 | 19 | public ItemBean() { 20 | } 21 | 22 | public ItemBean(int mItemId, int mBitmapId, Bitmap mBitmap) { 23 | this.mItemId = mItemId; 24 | this.mBitmapId = mBitmapId; 25 | this.mBitmap = mBitmap; 26 | } 27 | 28 | public int getItemId() { 29 | return mItemId; 30 | } 31 | 32 | public void setItemId(int mItemId) { 33 | this.mItemId = mItemId; 34 | } 35 | 36 | public int getBitmapId() { 37 | return mBitmapId; 38 | } 39 | 40 | public void setBitmapId(int mBitmapId) { 41 | this.mBitmapId = mBitmapId; 42 | } 43 | 44 | public Bitmap getBitmap() { 45 | return mBitmap; 46 | } 47 | 48 | public void setBitmap(Bitmap mBitmap) { 49 | this.mBitmap = mBitmap; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/util/GameUtil.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.util; 2 | 3 | import com.lius.puzzlegame.activity.PuzzleMain; 4 | import com.lius.puzzlegame.bean.ItemBean; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author: Chris Liu 11 | * @date: 2018/6/12 23:51 12 | */ 13 | public class GameUtil { 14 | // 游戏信息单元格Bean 15 | public static List mItemBeans = new ArrayList(); 16 | // 空格单元格 17 | public static ItemBean mBlankItemBean = new ItemBean(); 18 | 19 | /** 20 | * 判断点击的Item是否可移动 21 | * 22 | * @param position position 23 | * @return 能否移动 24 | */ 25 | public static boolean isMoveable(int position) { 26 | int type = PuzzleMain.TYPE; 27 | // 获取空格Item 28 | int blankId = GameUtil.mBlankItemBean.getItemId() - 1; 29 | // 不同行 相差为type 30 | if (Math.abs(blankId - position) == type) { 31 | return true; 32 | } 33 | // 相同行 相差为1 34 | if ((blankId / type == position / type) && 35 | Math.abs(blankId - position) == 1) { 36 | return true; 37 | } 38 | return false; 39 | } 40 | 41 | /** 42 | * 交换空格与点击Item的位置 43 | * 44 | * @param from 交换图 45 | * @param blank 空白图 46 | */ 47 | public static void swapItems(ItemBean from, ItemBean blank) { 48 | ItemBean tempItemBean = new ItemBean(); 49 | // 交换BitmapId 50 | tempItemBean.setBitmapId(from.getBitmapId()); 51 | from.setBitmapId(blank.getBitmapId()); 52 | blank.setBitmapId(tempItemBean.getBitmapId()); 53 | // 交换Bitmap 54 | tempItemBean.setBitmap(from.getBitmap()); 55 | from.setBitmap(blank.getBitmap()); 56 | blank.setBitmap(tempItemBean.getBitmap()); 57 | // 设置新的Blank 58 | GameUtil.mBlankItemBean = from; 59 | } 60 | 61 | /** 62 | * 生成随机的Item 63 | */ 64 | public static void getPuzzleGenerator() { 65 | int index = 0; 66 | // 随机打乱顺序 67 | for (int i = 0; i < mItemBeans.size(); i++) { 68 | index = (int) (Math.random() * 69 | PuzzleMain.TYPE * PuzzleMain.TYPE); 70 | swapItems(mItemBeans.get(index), GameUtil.mBlankItemBean); 71 | } 72 | List data = new ArrayList(); 73 | for (int i = 0; i < mItemBeans.size(); i++) { 74 | data.add(mItemBeans.get(i).getBitmapId()); 75 | } 76 | // 判断生成是否有解 77 | if (canSolve(data)) { 78 | return; 79 | } else { 80 | getPuzzleGenerator(); 81 | } 82 | } 83 | 84 | /** 85 | * 是否拼图成功 86 | * 87 | * @return 是否拼图成功 88 | */ 89 | public static boolean isSuccess() { 90 | for (ItemBean tempBean : GameUtil.mItemBeans) { 91 | if (tempBean.getBitmapId() != 0 && 92 | (tempBean.getItemId()) == tempBean.getBitmapId()) { 93 | continue; 94 | } else if (tempBean.getBitmapId() == 0 && 95 | tempBean.getItemId() == PuzzleMain.TYPE * PuzzleMain.TYPE) { 96 | continue; 97 | } else { 98 | return false; 99 | } 100 | } 101 | return true; 102 | } 103 | 104 | /** 105 | * 该数据是否有解 106 | * 107 | * @param data 拼图数组数据 108 | * @return 该数据是否有解 109 | */ 110 | public static boolean canSolve(List data) { 111 | // 获取空格Id 112 | int blankId = GameUtil.mBlankItemBean.getItemId(); 113 | // 可行性原则 114 | if (data.size() % 2 == 1) { 115 | return getInversions(data) % 2 == 0; 116 | } else { 117 | // 从底往上数,空格位于奇数行 118 | if (((blankId - 1) / PuzzleMain.TYPE) % 2 == 1) { 119 | return getInversions(data) % 2 == 0; 120 | } else { 121 | // 从底往上数,空位位于偶数行 122 | return getInversions(data) % 2 == 1; 123 | } 124 | } 125 | } 126 | 127 | /** 128 | * 计算倒置和算法 129 | * 130 | * @param data 拼图数组数据 131 | * @return 该序列的倒置和 132 | */ 133 | public static int getInversions(List data) { 134 | int inversions = 0; 135 | int inversionCount = 0; 136 | for (int i = 0; i < data.size(); i++) { 137 | for (int j = i + 1; j < data.size(); j++) { 138 | int index = data.get(i); 139 | if (data.get(j) != 0 && data.get(j) < index) { 140 | inversionCount++; 141 | } 142 | } 143 | inversions += inversionCount; 144 | inversionCount = 0; 145 | } 146 | return inversions; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/util/ImagesUtil.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.util; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Matrix; 7 | 8 | import com.lius.puzzlegame.R; 9 | import com.lius.puzzlegame.activity.PuzzleMain; 10 | import com.lius.puzzlegame.bean.ItemBean; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * @author: Chris Liu 17 | * @date: 2018/6/12 23:46 18 | */ 19 | public class ImagesUtil { 20 | 21 | public ItemBean itemBean; 22 | 23 | /** 24 | * 切图、初始状态(正常顺序) 25 | * 26 | * @param type 游戏种类 27 | * @param picSelected 选择的图片 28 | * @param context context 29 | */ 30 | public void createInitBitmaps(int type, Bitmap picSelected, 31 | Context context) { 32 | Bitmap bitmap = null; 33 | List bitmapItems = new ArrayList(); 34 | // 每个Item的宽高 35 | int itemWidth = picSelected.getWidth() / type; 36 | int itemHeight = picSelected.getHeight() / type; 37 | for (int i = 1; i <= type; i++) { 38 | for (int j = 1; j <= type; j++) { 39 | bitmap = Bitmap.createBitmap( 40 | picSelected, 41 | (j - 1) * itemWidth, 42 | (i - 1) * itemHeight, 43 | itemWidth, 44 | itemHeight); 45 | bitmapItems.add(bitmap); 46 | itemBean = new ItemBean( 47 | (i - 1) * type + j, 48 | (i - 1) * type + j, 49 | bitmap); 50 | GameUtil.mItemBeans.add(itemBean); 51 | } 52 | } 53 | // 保存最后一个图片在拼图完成时填充 54 | PuzzleMain.mLastBitmap = bitmapItems.get(type * type - 1); 55 | // 设置最后一个为空Item 56 | bitmapItems.remove(type * type - 1); 57 | GameUtil.mItemBeans.remove(type * type - 1); 58 | Bitmap blankBitmap = BitmapFactory.decodeResource( 59 | context.getResources(), R.drawable.blank); 60 | blankBitmap = Bitmap.createBitmap( 61 | blankBitmap, 0, 0, itemWidth, itemHeight); 62 | 63 | bitmapItems.add(blankBitmap); 64 | GameUtil.mItemBeans.add(new ItemBean(type * type, 0, blankBitmap)); 65 | GameUtil.mBlankItemBean = GameUtil.mItemBeans.get(type * type - 1); 66 | } 67 | 68 | /** 69 | * 处理图片 放大、缩小到合适位置 70 | * 71 | * @param newWidth 缩放后Width 72 | * @param newHeight 缩放后Height 73 | * @param bitmap bitmap 74 | * @return bitmap 75 | */ 76 | public Bitmap resizeBitmap(float newWidth, float newHeight, Bitmap bitmap) { 77 | Matrix matrix = new Matrix(); 78 | matrix.postScale( 79 | newWidth / bitmap.getWidth(), 80 | newHeight / bitmap.getHeight()); 81 | Bitmap newBitmap = Bitmap.createBitmap( 82 | bitmap, 0, 0, 83 | bitmap.getWidth(), 84 | bitmap.getHeight(), 85 | matrix, true); 86 | return newBitmap; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/lius/puzzlegame/util/ScreenUtil.java: -------------------------------------------------------------------------------- 1 | package com.lius.puzzlegame.util; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.view.Display; 6 | import android.view.WindowManager; 7 | 8 | /** 9 | * @author: Chris Liu 10 | * @date: 2018/6/9 17:18 11 | */ 12 | public class ScreenUtil { 13 | /** 14 | * 获取屏幕相关参数 15 | * @param context context 16 | * @return DisplayMetrics 屏幕宽高 17 | */ 18 | public static DisplayMetrics getScreenSize(Context context) { 19 | DisplayMetrics metrics = new DisplayMetrics(); 20 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 21 | Display display = wm.getDefaultDisplay(); 22 | display.getMetrics(metrics); 23 | return metrics; 24 | } 25 | 26 | /** 27 | * 获取屏幕density 28 | * 29 | * @param context context 30 | * @return density 屏幕density 31 | */ 32 | public static float getDeviceDensity(Context context) { 33 | DisplayMetrics metrics = new DisplayMetrics(); 34 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 35 | wm.getDefaultDisplay().getMetrics(metrics); 36 | return metrics.density; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/res/anim/image_hide_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/image_show_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/blank.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic1.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic10.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic11.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic12.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic13.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic14.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic15.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic2.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic3.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic4.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic5.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic6.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic7.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic8.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/pic9.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liusgeekdev/PuzzleGame/41428411401bc0015b9a7085f0d3b907bebe9377/app/src/main/res/drawable-hdpi/plus.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/beautybutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/textview_click.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/xpuzzle_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 24 | 25 | 35 | 36 | 37 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/xpuzzle_main_type_selected.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 27 | 28 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/xpuzzle_puzzle_detail_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 22 | 23 | 33 | 34 | 41 | 42 | 51 | 52 | 53 | 60 | 61 |