Android移动拼图小游戏

XMl布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    >
    <GridLayout 
        android:id="@+id/jigsaw"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:columnCount="5"
        android:rowCount="3"/>
</RelativeLayout>

MainActivity代码:

public class MainActivity extends Activity {

	private boolean isAnimRun = false;
	/**判断游戏是否开始*/
	private boolean isGameStart = false;
	/**利用二维数组创建若干个游戏小方块**/
	private ImageView[][] iv_game_arr = new ImageView[3][5];
	/**游戏主界面**/
	private GridLayout gl_game;
	/**当前空方块的实例保存*/
	private ImageView iv_null;
	/**当前手势*/
	private GestureDetector mDetector;
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		return mDetector.onTouchEvent(event);
	}
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		mDetector.onTouchEvent(ev);
		return super.dispatchTouchEvent(ev);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mDetector = new GestureDetector(this, new OnGestureListener() {
			
			@Override
			public boolean onSingleTapUp(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
			
			@Override
			public void onShowPress(MotionEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
				// TODO Auto-generated method stub
				return false;
			}
			
			@Override
			public void onLongPress(MotionEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
				// TODO Auto-generated method stub
				Log.d("TAG", ""+getDirByGes(e1.getX(), e1.getY(), e2.getX(), e2.getY()));
				int type = getDirByGes(e1.getX(), e1.getY(), e2.getX(), e2.getY());
				changeByDir(type);
				return false;
			}
			
			@Override
			public boolean onDown(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
		});
		/*初始化游戏的若干个小方块*/
		//获取一张大图
		Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.pic1)).getBitmap();
		int wh = bitmap.getWidth()/5;
		//小方块的宽高是整个屏幕的宽除以5
		int ivWH = getWindow().getWindowManager().getDefaultDisplay().getWidth()/5;
		for(int i = 0;i<iv_game_arr.length;i++){
			for(int j = 0;j<iv_game_arr[0].length;j++){
				//根据行和列来切成若干个游戏小图片
				Bitmap bm = Bitmap.createBitmap(bitmap,j*wh,i*wh,wh,wh);
				iv_game_arr[i][j] = new ImageView(this);
				iv_game_arr[i][j].setImageBitmap(bm);//设置每个小方块的图案
				
				iv_game_arr[i][j].setLayoutParams(new RelativeLayout.LayoutParams(ivWH,ivWH));
				iv_game_arr[i][j].setPadding(2, 2, 2, 2);//设置方块之间的间距
				iv_game_arr[i][j].setTag(new GameData(i, j, bm));//绑定自定义的数据
			
				iv_game_arr[i][j].setOnClickListener(new OnClickListener() {
					
					@Override
					public void onClick(View v) {
						// TODO Auto-generated method stub
						boolean flag = isHasByNullImage((ImageView)v);
						if(flag){
							changeDataByImage((ImageView)v);
						}
					}
				});
			}
		}
		/*初始化游戏主界面,并添加若干个小方块*/
		gl_game = (GridLayout) findViewById(R.id.jigsaw);
		for(int i = 0;i<iv_game_arr.length;i++){
			for(int j = 0;j<iv_game_arr[0].length;j++){
				gl_game.addView(iv_game_arr[i][j]);
			}
		}
		/*设置最后一个方块为空方块*/
		setNullImage(iv_game_arr[2][4]);
		randomOrder();
		isGameStart = true;
	}
	
	/**
	 * 根据手势的方向,获取空方块相应的相邻位置,如果存在方块,则进行数据狡猾
	 * 
	 * @param type 1:上 2:下 3:左 4:右
	 */
	public void changeByDir(int type){
		changeByDir(type, true);
	}
	
	/**
	 * 根据手势的方向,获取空方块相应的相邻位置,如果存在方块,则进行数据狡猾
	 * 
	 * @param type 1:上 2:下 3:左 4:右
	 * @param isAnim true:有动画 false:无动画
	 */
	public void changeByDir(int type,boolean isAnim){
		//获取当前空方块的位置
		GameData mNullGameData = (GameData) iv_null.getTag();
		//根据方向,设置相应的相邻位置的坐标
		int new_x = mNullGameData.x;
		int new_y = mNullGameData.y;
		if(type==1){//要移动的方块在当前空方块的下面
			new_x++;
		}else if(type==2){
			new_x--;
		}else if(type==3){
			new_y++;
		}else if(type==4){
			new_y--;
		}
		//判断这个新坐标,是否存在
		if(new_x>=0 && new_x<iv_game_arr.length && new_y>=0 && new_y<iv_game_arr[0].length){
			//存在的话开始移动
			if(isAnim){
				changeDataByImage(iv_game_arr[new_x][new_y]);
			}else{
				changeDataByImage(iv_game_arr[new_x][new_y],false);
			}
		}else{
			//什么也不做
		}
	}
	
	/***
	 * 判断游戏结束
	 */
	public void isGameOver(){
		boolean isOver = true;
		//要遍历每个游戏小方块
		for(int i = 0;i<iv_game_arr.length;i++){
			for(int j =0;j<iv_game_arr[0].length;j++){
				//为空的方块数据不判断跳过
				if(iv_game_arr[i][j] == iv_null){
					continue;
				}
				GameData mGameData = (GameData) iv_game_arr[i][j].getTag();
				if(!mGameData.isTrue()){
					isOver = false;
					break;
				}
		}
		}
		//根据一个开关变量决定游戏是否结束,结束时给提示
		if(isOver){
			Toast.makeText(MainActivity.this, "GameOver", Toast.LENGTH_LONG).show();
		}
	}
	
	/**
	 * 手势判断
	 * @param start_x 手势起始点x
	 * @param start_y 手势起始点y
	 * @param end_x 手势终止点x
	 * @param end_y 手势终止点y
	 * @return 1:上 2:下 3:左 4:右
	 */
	public int getDirByGes(float start_x,float start_y,float end_x,float end_y){
		boolean isLeftOrRight = (Math.abs(start_x - end_x) > Math.abs(start_y - end_y)) ? true:false;//判断左右
		if(isLeftOrRight){//左右
			boolean isLeft = start_x - end_x > 0 ? true : false;
			if(isLeft){
				return 3;
			}else{
				return 4;
			}
		}else{//上下
			boolean isUp = start_y - end_y > 0 ? true : false;
			if(isUp){
				return 1;
			}else{
				return 2;
			}
		}
	}
	
	/**
	 * 随机打乱顺序
	 */
	public void randomOrder(){
		//打乱的次数
		for (int i = 0; i < 100; i++) {
			//根据手势开始交换,无动画
			int type = (int)(Math.random()*4)+1;
			changeByDir(type, false);
		}
	}
	
	public void changeDataByImage(final ImageView mImageView){
		changeDataByImage(mImageView, true);
	}
	
	/**
	 * 利用动画结束之后,交换亮给方块的数据
	 * @param mImageView 点击的方块
	 * @param isAnim true:有动画 false:无动画
	 */
	public void changeDataByImage(final ImageView mImageView,boolean isAnim){
		if(isAnimRun)
			return;
		if(!isAnim){
			GameData mGameData = (GameData) mImageView.getTag();
			iv_null.setImageBitmap(mGameData.bitmap);
			
			GameData mNullGameData = (GameData) iv_null.getTag();
			mNullGameData.bitmap = mGameData.bitmap;
			mNullGameData.p_x = mGameData.p_x;
			mNullGameData.p_y = mGameData.p_y;
			iv_null.setTag(mNullGameData);
			
			//设置当前点击的是空方块
			setNullImage(mImageView);
			return;
		}
		//创建一个动画,设置好方向,移动的距离
		TranslateAnimation translateAnimation = null;
		if(mImageView.getX()>iv_null.getX()){//当前点击方块在空方块的下面
			//往上移动
			translateAnimation = new TranslateAnimation(0.1f, -mImageView.getWidth(), 0.1f, 0.1f);
		}else if(mImageView.getX()<iv_null.getX()){//当前点击方块在空方块的上面
			//往下移动
			translateAnimation = new TranslateAnimation(0.1f, mImageView.getWidth(), 0.1f, 0.1f);
		}else if(mImageView.getY()>iv_null.getY()){//当前点击方块在空方块的右面
			//往左移动
			translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f, -mImageView.getWidth());
		}else if(mImageView.getY()<iv_null.getY()){//当前点击方块在空方块的左面
			//往右移动
			translateAnimation = new TranslateAnimation(0.1f,0.1f, 0.1f, mImageView.getWidth());
		}
		//设置动画的时长
		translateAnimation.setDuration(70);
		//设置动画结束之后是否停留
		translateAnimation.setFillAfter(true);
		//设置动画结束之后要真正的把数据交换了
		translateAnimation.setAnimationListener(new AnimationListener() {
			
			@Override
			public void onAnimationStart(Animation animation) {
				// TODO Auto-generated method stub
				isAnimRun = true;
			}
			
			@Override
			public void onAnimationRepeat(Animation animation) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onAnimationEnd(Animation animation) {
				// TODO Auto-generated method stub
				isAnimRun = false;
				mImageView.clearAnimation();
				GameData mGameData = (GameData) mImageView.getTag();
				iv_null.setImageBitmap(mGameData.bitmap);
				
				GameData mNullGameData = (GameData) iv_null.getTag();
				mNullGameData.bitmap = mGameData.bitmap;
				mNullGameData.p_x = mGameData.p_x;
				mNullGameData.p_y = mGameData.p_y;
				iv_null.setTag(mNullGameData);
				
				//设置当前点击的是空方块
				setNullImage(mImageView);
				if(isGameStart){
					isGameOver();//成功时会弹出一个Toas
				}
			}
		});
		//执行动画
		mImageView.startAnimation(translateAnimation);
	}
	
	/**
	 * 设置某个空方块
	 * mImageView当前要设置空方块的实例
	 */
	public void setNullImage(ImageView mImageView){
		mImageView.setImageBitmap(null);
		iv_null = mImageView;
	}
	
	/**
	 * 判断当前点击的方块,是否与空方块的位置关系为相邻关系
	 * @param mImageView 所点击的方块
	 * @return true:相邻 false:不相邻
	 */
	public boolean isHasByNullImage(ImageView mImageView){
		//分别获取当前空方块的位置与点击方块的位置,通过x与y两边都差1的方式判断
		GameData mNullGameData = (GameData) iv_null.getTag();
		GameData mGameData = (GameData) mImageView.getTag();
		if(mNullGameData.y==mGameData.y&&mGameData.x+1==mNullGameData.x){//当前点击的方块在空方块的上边
			return true;
		}else if(mNullGameData.y==mGameData.y&&mGameData.x-1==mNullGameData.x){//当前点击的方块在空方块的下边
			return true;
		}else if(mNullGameData.y==mGameData.y+1&&mGameData.x==mNullGameData.x){//当前点击的方块在空方块的左边
			return true;
		}else if(mNullGameData.y==mGameData.y-1&&mGameData.x==mNullGameData.x){//当前点击的方块在空方块的右边
			return true;
		}
		
		return false;
	}
	/**每个游戏小方块上要绑定的数据*/
	class GameData{
		/**每个小方块的实际位置x*/
		public int x;
		/**每个小方块的实际位置y*/
		public int y;
		/**每个小方块的图片*/
		public Bitmap bitmap;
		/**每个小方块的图片的位置x*/
		public int p_x;
		/**每个小方块的图片的位置y*/
		public int p_y;
		public GameData(int x, int y, Bitmap bitmap) {
			super();
			this.x = x;
			this.y = y;
			this.bitmap = bitmap;
			this.p_x = x;
			this.p_y = y;
		}
		
		public boolean isTrue(){
			if(x==p_x && y==p_y){
				return true;
			}
			return false;
		}
		
	}
}
源码下载

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
①主界面 开始游戏(可点击) 游戏设置(可点击) 关于游戏(可点击) ②点击“关于游戏”弹出对话框 “对话框内容”(不可点击) 确定(可点击,点击后关闭对话框) ③点击“游戏设置”进入游戏设置界面 返回(可点击,点击后返回主界面。于左上角) 难度设置(可点击,设置为下拉框(3x3起,先到8x8止)) 图片选择(可点击,可选择游戏自带或者本地) ④点击“游戏开始”进入选择界面 ⑤选择界面 单人拼图模式(可点击,点击后进入游戏界面) 联机模式(放一个可点击的按钮即可) 剧情模式(放一个可点击的按钮即可) ⑥点击“单人拼图模式”进入游戏界面 返回(可点击,点击后返回主界面。于左上角)(返回主界面再开始游戏不会继续上次的进度) 计时(不可点击,于右上角) 重新开始(可点击,点击后刷新游戏界面重新开始(计时重新开始),于主体下方) 游戏主体(于界面中间,正方形):选好的图片,切割成NxN个相同大小碎片,再随机交换位置,然后呈现出来。玩家控制鼠标,拽拉一个碎片到任意另一个碎片的位置,可使两个碎片交换位置。最后将图片成功还原就成功。弹出对话框(您已完成此次拼图,用时xx),点击确定关闭对话框(此时依旧在游戏界面)。点击重新开始就重新玩,点击返回就回到主界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值