android拼图游戏制作,[Android]自己动手做个拼图游戏

本文详细介绍了如何在Android平台上实现一个拼图游戏。从获取屏幕尺寸、拉伸图片并切割成小块,到随机打乱拼图块并确保有解,再到允许用户操作拼图和判断游戏是否完成,每个步骤都有清晰的代码示例。同时,文章还提供了拼图游戏的技巧和总结,适合初学者练习和提升编程技能。
摘要由CSDN通过智能技术生成

目标

在做这个游戏之前,我们先定一些小目标列出来,一个一个的解决,这样,一个小游戏就不知不觉的完成啦。我们的目标如下:

游戏全屏,将图片拉伸成屏幕大小,并将其切成若干块。

将拼图块随机打乱,并保证其能有解。

在屏幕上留出一个空白块,当点空白块旁边的块,将这块移动到空白块。

判断是否已经拼好。

f5be67f2885c62d274971198c8360933.gif

实现目标

1.将图片拉伸成屏幕大小,并将其切成若干块。

想拉伸成屏幕大小,首先要知道屏幕的大小,Android获得屏幕大小的代码如下:

DisplayMetrics metrics =new DisplayMetrics();

getWindowManager().getDefaultDisplay().getRealMetrics(metrics);//sdk17+

int screenWidth = metrics.widthPixels;//屏幕宽

int screenHeight = metrics.heightPixels;//屏幕高

将图片拉伸到屏幕大小

Bitmap back=Bitmap.createScaledBitmap(bitmap,

MainActivity.getScreenWidth(),

MainActivity.getScreenHeight(),

true);

将图片切成若干块

private final int COL=3;//列,默认3列

private final int ROW=3;//行,默认3行

int tileWidth=back.getWidth()/COL;//每一块的宽

int tileHeight=back.getHeight()/ROW;//每一块的高

Bitmap[] bitmapTiles =new Bitmap[COL*ROW];

int idx=0;

for(int i=0;i

{

for(int j=0;j

{

bitmapTiles[idx++]=Bitmap.createBitmap(back,

j*tileWidth,

i*tileHeight,

tileWidth,tileHeight);

}

}

###2. 将拼图块随机打乱,并保证其能有解。 这个问题应该是这个小游戏的核心了,有些人在做拼图的时候就随便乱摆,最后发现拼不回来,超级尴尬。要想打乱了还能拼回来,我们呢,就想到了模拟人打乱拼图的方法,就是将空白块与旁边的非空白块交换位置,与旁边哪个非空白块交换是随机的,然后将这个过程重复若干次,重复的次数也是随机的,这样一来,保证了图块的随机,又保证了能拼回来。在这里我们用数字0到N-1(N为块的数量)表示每一块,并用二维数组存储他们。

private void createIntegerArray(int row,int col)

{

array=new int[row][col];

int idx=0;

for(int i=0;i

for(int j=0;j

array[i][j]=idx++;

}

下面是打乱块的算法,最后一块是空白块,让它随机与旁边的某一块进行交换,这个过程中要检查数组边界,不要让它越界。

//四个方向

private int[][] dir={

{0,1},//下

{1,0},//右

{0,-1},//上

{-1,0}//左

};

/**

* 移动块的位置

* @param srcX 初始x位置

* @param srcY 初始y位置

* @param xOffset x偏移量

* @param yOffset y偏移量

* @return 新的位置,错误返回new Point(-1,-1);

*/

private Point move(int srcX,int srcY,int xOffset,int yOffset)

{

int x=srcX+xOffset;

int y=srcY+yOffset;

if(x<0||y<0||x>=col||y>=row)

return new Point(-1,-1);

int temp=array[y][x];

array[y][x]=array[srcY][srcX];

array[srcY][srcX]=temp;

return new Point(x,y);

}

/**

* 得到下一个可以移动的位置

* @param src 初始的点

* @return

*/

private Point getNextPoint(Point src)

{

Random rd=new Random();

int idx=rd.nextInt(4);//,因为有4个方向,所以产生0~3的随机数

int xOffset=dir[idx][0];

int yOffset=dir[idx][1];

Point newPoint=move(src.getX(),src.getY(),xOffset,yOffset);

if(newPoint.getX()!=-1&&newPoint.getY()!=-1) {

return newPoint;//找到了新的点

}

return getNextPoint(src);//没有找到,继续

}

/**

* 生成拼图数据

* @param row

* @param col

* @return

*/

public int[][] createRandomBoard(int row,int col)

{

if(row<2||col<2)

throw new IllegalArgumentException("行和列都不能小于2");

this.row=row;

this.col=col;

createIntegerArray(row,col);//初始化拼图数据

int count=0;

Point tempPoint=new Point(col-1,row-1);//最后一块是空白块

Random rd=new Random();

int num=rd.nextInt(100)+20;//产生20~119的随机数,表示重复的次数

while (count

{

tempPoint=getNextPoint(tempPoint);//获得下个点,并更新空白块位置

count++;

}

return array;

}

###3. 在屏幕上留出一个空白块,当点空白块旁边的块,将这块移动到空白块。 留出空白块很简单,由于上面我们将最后一块作为空白块。当我们绘图时,略过它即可。代码实现如下:

@Override

protected void onDraw(Canvas canvas) {

canvas.drawColor(Color.GRAY);

for(int i=0;i

for (int j = 0; j < COL; j++) {

int idx=dataTiles[i][j];

if(idx==ROW*COL-1&&!isSuccess)

continue;

canvas.drawBitmap(bitmapTiles[idx],

j*tileWidth,

i*tileHeight,paint);

}

}

}

移动块也很简单,当点击屏幕时,计算其在拼图数据中对应的索引。当计算到点击非空白块就寻找它旁边有没有空白块,有,则将拼图数据中表示空白块和非空白块的数据交换,并刷新View即可

/**

* 将屏幕上的点转换成,对应拼图块的索引

* @param x

* @param y

* @return

*/

private Point xyToIndex(int x,int y)

{

int extraX=x%tileWidth>0?1:0;

int extraY=x%tileWidth>0?1:0;

int col=x/tileWidth+extraX;

int row=y/tileHeight+extraY;

return new Point(col-1,row-1);

}

/**

*点击屏幕时发生

*/

@Override

public boolean onTouchEvent(MotionEvent event) {

if(event.getAction()==MotionEvent.ACTION_DOWN) {

Point point = xyToIndex((int) event.getX()

, (int) event.getY());

for(int i=0;i

{

int newX=point.getX()+dir[i][0];

int newY=point.getY()+dir[i][1];

if(newX>=0&&newX

=0&&newY

if(dataTiles[newY][newX]==COL*ROW-1)

{

int temp=dataTiles[point.getY()][point.getX()];

dataTiles[point.getY()][point.getX()]=dataTiles[newY][newX];

dataTiles[newY][newX]=temp;

invalidate();

}

}

}

}

return true;

}

###4. 判断是否已经拼好 我们初始化数据时,是从0开始,依次增加作为拼图数据。当拼好的时候,拼图数据也应该是一样的,所以我们比较数组中每一个数据与它的下一个数据,如果每一个数据都小于它的下一个数据,说明数组里面的数据已经从小到大排列好。

/**

* 判断是否拼图成功

* @param arr

* @return

*/

public boolean isSuccess(int[][] arr)

{

int idx=0;

for(int i=0;i

{

for(int j=0;j

{

if(arr[idx/row][idx%col]>arr[(idx+1)/row][(idx+1)%col])

{

return false;

}

idx++;

}

}

return true;

}

##拼图游戏技巧 拼图技巧觉得也有必要说一下,不然有些人就会说:你的算法有问题,这根本拼不好!我也是超级无奈啊!拼图的技巧是,我们先把上面的第一行拼好,然后再把第二行拼好,这样,一直下去~就能完全拼好了。

##总结 这个小游戏简单,可以拿来练手,还可以拿来装(liao)逼(mei),如果不会,何乐而不看呢。这个小游戏也是将视图和数据分开,代码容易移植。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值