Android拼图游戏开发全纪录3

今天我们要继续开发Android游戏拼图,今天同样是做一些准备工作,昨天我们把界面的准备工作做好了,今天呢,我们想想,要完成一个拼图,我们还需要做哪些准备。

首先,我们需要一个工具类,去获取屏幕的相关信息,让我们的程序去自动适应不同分辨率大小的屏幕:

package com.xys.xpuzzle.util;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;

/**
 * 屏幕工具类:实现获取屏幕相关参数
 *
 * @author xys
 *
 */
public class ScreenUtil {

    /**
     * 获取屏幕相关参数
     *
     * @param context
     * @return DisplayMetrics 屏幕宽高
     */
    public static DisplayMetrics getScreenSize(Context context) {
	DisplayMetrics metrics = new DisplayMetrics();
	WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
	Display display = wm.getDefaultDisplay();
	display.getMetrics(metrics);
	return metrics;
    }
}

下面我们要开始设计一个实体bean,去封装我们的拼图,这里的方法有很多,我只是举个砖头。

我们知道,拼图时会把图片分割成NXN个方块,移动方块以完成拼图,所以我将每个分割后的方块做成一个对象,我们所有的实体bean都是基于每个分割后的方块,所以自然的我们可以抽象出一个实体bean:

package com.xys.xpuzzle.bean;

import android.graphics.Bitmap;

/**
 * 拼图Item逻辑实体类:封装逻辑相关属性
 *
 * @author xys
 *
 */
public class ItemBean {

    // Item的Id
    private int itemId;
    // bitmap的Id
    private int bitmapId;
    // bitmap
    private Bitmap bitmap;

    public int getItemId() {
	return itemId;
    }

    public void setItemId(int itemId) {
	this.itemId = itemId;
    }

    public ItemBean() {
    }

    public int getBitmapId() {
	return bitmapId;
    }

    public void setBitmapId(int bitmapId) {
	this.bitmapId = bitmapId;
    }

    public Bitmap getBitmap() {
	return bitmap;
    }

    public void setBitmap(Bitmap bitmap) {
	this.bitmap = bitmap;
    }

    public ItemBean(int itemId, int bitmapId, Bitmap bitmap) {
	this.itemId = itemId;
	this.bitmapId = bitmapId;
	this.bitmap = bitmap;
    }

}

bean里面封装了

1、方块对应在NXN格中的序号

2、分割后的图片的ID和对应的图片

接下来就是对图片的分割:

package com.xys.xpuzzle.util;

import java.util.ArrayList;
import java.util.List;

import com.xys.xpuzzle.R;
import com.xys.xpuzzle.activity.PuzzleMain;
import com.xys.xpuzzle.bean.ItemBean;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;

/**
 * 图像工具类:实现图像的分割与自适应
 *
 * @author xys
 *
 */
public class ImagesUtil {

    public ItemBean itemBean;

    /**
     * 切图、初始状态(正常顺序)
     *
     * @param type
     * @param picSelected
     * @param context
     */
    public void createInitBitmaps(int type, Bitmap picSelected, Context context) {
	Bitmap bitmap = null;
	List<Bitmap> bitmapItems = new ArrayList<Bitmap>();
	// 每个Item的宽高
	int itemWidth = picSelected.getWidth() / type;
	int itemHeight = picSelected.getHeight() / type;
	for (int i = 1; i <= type; i++) {
	    for (int j = 1; j <= type; j++) {
		bitmap = Bitmap.createBitmap(picSelected, (j - 1) * itemWidth, (i - 1) * itemHeight, itemWidth, itemHeight);
		bitmapItems.add(bitmap);
		itemBean = new ItemBean((i - 1) * type + j, (i - 1) * type + j, bitmap);
		GameUtil.itemBeans.add(itemBean);
	    }
	}
	// 保存最后一个图片在拼图完成时填充
	PuzzleMain.lastBitmap = bitmapItems.get(type * type - 1);
	// 设置最后一个为空Item
	bitmapItems.remove(type * type - 1);
	GameUtil.itemBeans.remove(type * type - 1);
	Bitmap blankBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.blank);
	blankBitmap = Bitmap.createBitmap(blankBitmap, 0, 0, itemWidth, itemHeight);

	bitmapItems.add(blankBitmap);
	GameUtil.itemBeans.add(new ItemBean(type * type, 0, blankBitmap));

	GameUtil.blankItemBean = GameUtil.itemBeans.get(type * type - 1);
    }

    /**
     * 处理图片 放大、缩小到合适位置
     *
     * @param newWidth
     * @param newHeight
     * @param bitmap
     * @return
     */
    public Bitmap resizeBitmap(float newWidth, float newHeight, Bitmap bitmap) {
	Matrix matrix = new Matrix();
	matrix.postScale(newWidth / bitmap.getWidth(), newHeight / bitmap.getHeight());
	Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
	return newBitmap;
    }
}

这个工具类主要完成这两件事:

1、切图、初始状态(正常顺序)

2、处理图片 放大、缩小到合适位置

根据上一篇讲的算法,我们需要将图片进行分割,然后生成一个切好图后的Items集合,当然,还要对要拼图的图片进行下大小的处理,因为我们除了有默认的图片,还可以自定义图片

图片工具类完成后,接下来我们就要在一个工具类中实现这些算法,同时还要做一些对游戏的封装:

package com.xys.xpuzzle.util;

import java.util.ArrayList;
import java.util.List;

import com.xys.xpuzzle.activity.PuzzleMain;
import com.xys.xpuzzle.bean.ItemBean;

/**
 * 拼图工具类:实现拼图的交换与生成算法
 *
 * @author xys
 *
 */
public class GameUtil {

    // 游戏信息单元格Bean
    public static List<ItemBean> itemBeans = new ArrayList<ItemBean>();
    // 空格单元格
    public static ItemBean blankItemBean = new ItemBean();

    /**
     * 判断点击的Item是否可移动
     *
     * @param position
     * @return 能否移动
     */
    public static boolean isMoveable(int position) {
	int type = PuzzleMain.type;
	// 获取空格Item
	int blankId = GameUtil.blankItemBean.getItemId() - 1;
	// 不同行 相差为type
	if (Math.abs(blankId - position) == type) {
	    return true;
	}
	// 相同行 相差为1
	if ((blankId / type == position / type) && Math.abs(blankId - position) == 1) {
	    return true;
	}
	return false;
    }

    /**
     * 交换空格与点击Item的位置
     *
     * @param from
     * @param blank
     */
    public static void swapItems(ItemBean from, ItemBean blank) {
	ItemBean tempItemBean = new ItemBean();
	// 交换BitmapId
	tempItemBean.setBitmapId(from.getBitmapId());
	from.setBitmapId(blank.getBitmapId());
	blank.setBitmapId(tempItemBean.getBitmapId());
	// 交换Bitmap
	tempItemBean.setBitmap(from.getBitmap());
	from.setBitmap(blank.getBitmap());
	blank.setBitmap(tempItemBean.getBitmap());
	// 设置新的Blank
	GameUtil.blankItemBean = from;
    }

    /**
     * 生成随机的Item
     */
    public static void getPuzzleGenerator() {
	int index = 0;
	for (int i = 0; i < itemBeans.size(); i++) {
	    index = (int) (Math.random() * PuzzleMain.type * PuzzleMain.type);
	    swapItems(itemBeans.get(index), GameUtil.blankItemBean);
	}
	List<Integer> data = new ArrayList<Integer>();
	for (int i = 0; i < itemBeans.size(); i++) {
	    data.add(itemBeans.get(i).getBitmapId());
	}
	// 判断生成是否有解
	if (canSolve(data)) {
	    return;
	} else {
	    getPuzzleGenerator();
	}
    }

    /**
     * 是否拼图成功
     *
     * @return 是否拼图成功
     */
    public static boolean isSuccess() {
	for (ItemBean tempBean : GameUtil.itemBeans) {
	    if (tempBean.getBitmapId() != 0 && (tempBean.getItemId()) == tempBean.getBitmapId()) {
		continue;
	    } else if (tempBean.getBitmapId() == 0 && tempBean.getItemId() == PuzzleMain.type * PuzzleMain.type) {
		continue;
	    } else {
		return false;
	    }
	}
	return true;
    }

    /**
     * 该数据是否有解
     *
     * @param data
     * @return 该数据是否有解
     */
    public static boolean canSolve(List<Integer> data) {
	// 获取空格Id
	int blankId = GameUtil.blankItemBean.getItemId();
	// 可行性原则
	if (data.size() % 2 == 1) {
	    return getInversions(data) % 2 == 0;
	} else {
	    // 从底往上数,空格位于奇数行
	    if (((int) (blankId - 1) / PuzzleMain.type) % 2 == 1) {
		return getInversions(data) % 2 == 0;
	    } else {
		// 从底往上数,空位位于偶数行
		return getInversions(data) % 2 == 1;
	    }
	}
    }

    /**
     * 计算倒置和算法
     *
     * @param data
     * @return 该序列的倒置和
     */
    public static 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;
    }
}

可以看到,游戏工具类中,我们主要有以下几个功能:

1、判断点击的Item是否可移动:主要难点是判断需要分同行与不同行,否则会出现上一行的最后一个和本行的第一个可以移动的BUG

2、交换空格与点击Item的位置:实际上是交换GridView中的某2个Item的背景

3、生成随机的Item:根据上一篇讲的算法,打随机打乱分割后的图片

4、判断是否拼图成功:根据上一篇讲的算法的结论判断

5、判断该数据是否有解:根据上一篇讲的算法的结论判断

6、计算倒置和算法:算法的核心注意要踢出空格

到目前为止,我们的准备工作就基本结束了,很多人可能会说开始的时候准备这么多干嘛,其实这是我真实的思考顺序,刚开始项目的时候,一定要先把项目整体规划一下,而不是上手就做,当你有了一个清晰的思路后,coding只是一个体力活而已。所以,工欲善其事,必先利其器,画竹需要成竹在胸。

ps : 需要源码的朋友请留言。

时间: 2024-10-01 03:09:30

Android拼图游戏开发全纪录3的相关文章

Android拼图游戏开发全纪录0

最近刚完成一个Android的小项目--拼图游戏.项目并不复杂,但也是一个完整的项目,用到的知识点还是比较丰富的. 做完之后照例进行下总结: 需求定义: 1.选择图片后进入拼图界面,可以选择默认图片或者自定义图片,即从图库选择或者从相机拍照. 2.可以设置游戏的难度,即选择拼图为NXN结构. 3.自动打乱拼图的顺序,利用倒置和算法,确保生成的数据有解. 4.拼图过程中可以查看原图. 5.拼图具有计时.记步功能. 6.完成拼图后显示全部图片并提升拼图成功. 7.可以查看历史记录. *8.利用IDA

Android拼图游戏开发全纪录2

今天我们主要来讨论下拼图游戏的可行性解的问题,其实不要小看拼图游戏,他其实是人工智能算法中很著名的15puzzle问题,网上已经有很多关于这个问题的解释,我就做个搬运工好了. 随机生成的15puzzle大约有%50是无解的,本文将就随机生成的谜题的可解性加以讨论. 设有如下矩阵: 12 1 10 2 7 11 4 14 5 x 9 15 8 13 6 3 将其排成水平的,有:12,1,10,2,7,11,4,14,5,X,9,15,8,13,6,3.并记该序列为A 定义:"倒置变量值"

Android拼图游戏开发全纪录5

今天我们终于可以把这个项目给结束掉啦,有了前几天的准备,相信最后一天还是比较轻松的,国际惯例: 最后要完成的就是我们的主要功能--拼图界面. 布局比较简单,在前几天就已经做好了,现在我们要做的是以下几件事情: 1.计时记步:这个是游戏基本都有的功能,其实也比较简单,记录成功移动的步数.显示一个计时器就行了. 2.处理图片,调整为合适的大小比例:这个方法在前几天已经实现了 3.点击GridView后移动图片:是否能移动的方法已经在前几天实现了 4.判断是否拼图完成:唉,也已经实现了 5.点击原图按

Android拼图游戏开发全纪录4

今天我们主要实现我们的主界面:国际惯例: 界面我们已经在第一天做好了,今天我们就要实现这个界面的功能, 分析一下,这个界面包含以下几个功能: 1.显示游戏的难度:使用popupwindow,选择后改变显示的数字 2.显示默认的待拼图图片,包含一张选择自定义的图片:这个比较简单,只是GridView的最简单应用而已 3.自定义按钮功能:调用系统图册和相机 4.查看记录和了解更多:这个也是一般的应用需求,比较简单 package com.xys.xpuzzle.activity; import ja

Android拼图游戏的设计逻辑,从切图到交互动画,从关卡到倒计时,实例提高!

Android拼图游戏的设计逻辑,从切图到交互动画,从关卡到倒计时,实例提高! 群英传的最后一章,我大致的看了一下这个例子,发现鸿洋大神也做过,就参考两个人的设计逻辑,感觉都差不多,就这样实现起来了 一.切图工具类 我们九宫格嘛,肯定要一个切图的工具,把一个图片给切成九张,那具体是怎么实现呢?我们先写一个bean来存储一切的状态 ImagePiece package com.lgl.ninegame.utils; import android.graphics.Bitmap; /** * * C

《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——2.5节2D动画的开发

2.5 2D动画的开发 Android 3D游戏开发技术宝典--OpenGL ES 2.0 虽然本书是着重介绍3D的开发技术,但在大部分的3D应用中也需要有不少的2D界面,如菜单.帮助等.本节将介绍一般用于开发游戏中2D界面的SurfaceView类的使用.其继承自View类,但与View的不同之处在于,View更新画面必须是在UI线程中(也可以理解为主线程中),而SurfaceView更新画面可以在自定义线程中进行,大大方便了开发. 提示 关于Android下的多线程问题,读者可以参考笔者在人

《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——1.5节Android应用程序运行的机制

1.5 Android应用程序运行的机制 Android 3D游戏开发技术宝典--OpenGL ES 2.0 上一节介绍了如何搭建Android开发环境.如何开发Hello Android应用程序以及Android应用程序的调试,接下来在本节中将简要地介绍Android应用程序的运行机制. 1.5.1 应用程序的系统架构 Android平台由应用程序.应用程序框架.Android运行时.系统库以及底层Linux内核构成,详细结构如图1-54所示. 说明 应用程序层里面包含的就是需要读者去发挥创意

《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——1.4节Hello Android应用程序的开发

1.4 Hello Android应用程序的开发 Android 3D游戏开发技术宝典--OpenGL ES 2.0 本节首先将介绍如何在Eclipse中创建一个基于Android的Hello World应用程序,之后将简单介绍Android应用程序的调试,为读者以后学习高级开发铺平道路. 1.4.1 第一个Android应用程序 本小节将向读者介绍如何在Eclipse中创建一个基于Android的Hello World应用程序,基本步骤如下所列. (1)首先打开Eclipse,然后依次选择Fi

《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——2.1节游戏中的音效

2.1 游戏中的音效 Android 3D游戏开发技术宝典--OpenGL ES 2.0 一款好游戏,除了具备优质的画面和较高的可玩性之外,还应该有出色的音效.音效一般指的是游戏中发生特定行为或进行特定操作时播放的效果音乐或为了渲染整体气氛播放的背景音,如远处隆隆的炮声.怪物死亡的惨叫声.由远而近的脚步声等. 通过开发人员精心准备的声音特效,结合游戏的场景,可以渲染出一种紧张刺激的氛围,使玩家产生身临其境的感觉.这就像电影中的声音特效一样,假如没有了合适的音效,那么游戏和电影一样,真实感会大打折