Android實(shí)現(xiàn)九格智能拼圖算法
最近想業(yè)余做一款android游戲,發(fā)現(xiàn)我國(guó)一款古老好玩的智力游戲-九格智能拼圖挺好玩的,相信大多80后小時(shí)玩過(guò),因此有了開(kāi)發(fā)的想法。
一、九格智能拼圖
游戲規(guī)則:將一副圖片分割為9個(gè)子圖片,其中一個(gè)為空白圖片,隨機(jī)打亂。通過(guò)兩兩圖片的交換,合并為一張圖片,最后游戲完成。
二、開(kāi)發(fā)步驟
1、將一個(gè)圖片分割為9個(gè)子圖片,放入ArrayList中。
利用Bitmap.createBitmap()進(jìn)行圖片切割, 根據(jù)參數(shù)坐標(biāo)的不同,可以切圖一張圖片的任意部分。
2、采用自定義view,隨機(jī)打亂的畫(huà)出9個(gè)子圖片
選生成0-9的隨機(jī)排列。然后根據(jù)排列值畫(huà)出對(duì)應(yīng)的圖片
3、在自定義view中響應(yīng)點(diǎn)擊圖片是否可以移動(dòng)。
遍歷左右方塊數(shù)字,如果為0,則可以移動(dòng)。同時(shí)交換相連數(shù)字和數(shù)組中的位置。
4、判斷游戲完成的結(jié)束算法。
依次遍歷各個(gè)方塊,如何數(shù)字呈依次遞增排列,則游戲結(jié)束
代碼:
package org.diudiululu.magicSquare; ? import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Point; import android.os.Bundle; import android.util.Log; ? /** ?* @author a1623z ?*? ?*/ public class MagicSquareActivity extends Activity { ?? ?private static final String TAG = "MagicSquare"; ?? ?public static final int SQUARE_WIDTH = 3; ? ?? ?private int square[] = new int[SQUARE_WIDTH * SQUARE_WIDTH]; ? ?? ?private int steps = 0; ? ?? ?private MagicSquareView magicSquareView; ? ?? ?public int getTitleNumber(int x, int y) { ?? ??? ?return square[y * SQUARE_WIDTH + x]; ?? ?} ? ?? ?@Override ?? ?protected void onCreate(Bundle savedInstanceState) { ?? ??? ?super.onCreate(savedInstanceState); ?? ??? ?Log.d(this.TAG, "OnCreate"); ? ?? ??? ?initGame(); ? ?? ??? ?magicSquareView = new MagicSquareView(this); ? ?? ??? ?this.setContentView(magicSquareView); ?? ??? ?magicSquareView.requestFocus(); ?? ?} ? ?? ?private void initGame() { ?? ??? ?generateMagicSquare(); ?? ??? ?steps = 0; ?? ?} ? ?? ?private void generateMagicSquare() { ?? ??? ?java.util.ArrayList<Integer> numArray = new java.util.ArrayList<Integer>(); ? ?? ??? ?for (int i = 0; i < square.length; i++) { ?? ??? ??? ?numArray.add(new Integer(i)); ?? ??? ?} ? ?? ??? ?int i = 0; ?? ??? ?while (numArray.size() > 0) { ?? ??? ??? ?int index = (int) (Math.random() * numArray.size()); ?? ??? ??? ?Integer integer = numArray.get(index); ?? ??? ??? ?square[i] = integer.intValue(); ?? ??? ??? ?i++; ?? ??? ??? ?numArray.remove(index); ?? ??? ?} ?? ?} ? ?? ?public boolean moveable(int x, int y) { ?? ??? ?if (x < 0 || x >= SQUARE_WIDTH) ?? ??? ??? ?return false; ? ?? ??? ?if (y < 0 || y >= SQUARE_WIDTH) ?? ??? ??? ?return false; ? ?? ??? ?for (int i = x - 1; i <= x + 1; i++) { ?? ??? ??? ?for (int j = y - 1; j <= y + 1; j++) { ?? ??? ??? ??? ?if (i == x && j == y) // it's myself, skip ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (i != x && j != y) ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (i < 0 || i >= SQUARE_WIDTH) ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (j < 0 || j >= SQUARE_WIDTH) ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (square[j * SQUARE_WIDTH + i] == 0) ?? ??? ??? ??? ??? ?return true; ?? ??? ??? ?} ?? ??? ?} ? ?? ??? ?return false; ?? ?} ? ?? ?public Point move(int x, int y) { ?? ??? ?Log.d(TAG, "move" + ",x=" + x + ",y=" + y); ?? ??? ?if (!moveable(x, y)) ?? ??? ??? ?return new Point(-1, -1); ? ?? ??? ?steps++; ? ?? ??? ?for (int i = x - 1; i <= x + 1; i++) { ?? ??? ??? ?for (int j = y - 1; j <= y + 1; j++) { ?? ??? ??? ??? ?if (i == x && j == y) // it's myself, skip ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (i != x && j != y) ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (i < 0 || i >= SQUARE_WIDTH) ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (j < 0 || j >= SQUARE_WIDTH) ?? ??? ??? ??? ??? ?continue; ? ?? ??? ??? ??? ?if (square[j * SQUARE_WIDTH + i] == 0) { ?? ??? ??? ??? ??? ?int temp = square[j * SQUARE_WIDTH + i]; ?? ??? ??? ??? ??? ?square[j * SQUARE_WIDTH + i] = square[y * SQUARE_WIDTH + x]; ?? ??? ??? ??? ??? ?square[y * SQUARE_WIDTH + x] = temp; ?? ??? ??? ??? ??? ?return new Point(i, j); ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ? ?? ??? ?return new Point(-1, -1); ?? ?} ? ?? ?public boolean win() { ?? ??? ?for (int i = 0; i < square.length - 1; i++) { ?? ??? ??? ?if (square[i] != i + 1) ?? ??? ??? ??? ?return false; ?? ??? ?} ?? ??? ?return true; ?? ?} ?? ? ?? ?public class Pic{ ?? ??? ?private ?int id; ?? ??? ?private ?Bitmap subbitmap; ?? ?} }
MagicSquarView.java
/** ?*? ?*/ package org.diudiululu.magicSquare; ? import java.util.ArrayList; ? import org.diudiululu.magicSquare.R; ? import android.app.Dialog; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.*; import android.graphics.*; import android.graphics.Paint.FontMetrics; import android.graphics.Paint.Style; import android.util.*; ? /** ?* @author a1623z ?*? ?*/ public class MagicSquareView extends View { ?? ?private static final String TAG = "MagicSquare"; ?? ?private final MagicSquareActivity magicSquareActivity; ? ?? ?private float width; ?? ?private float height; ?? ?private int selX; ?? ?private int selY; ?? ?private final Rect selRect = new Rect(); ?? ?private final int pingtuheight = 200; ? ?? ?private ArrayList<Pic> pieces; ? ?? ?/** ?? ? * @param context ?? ? */ ?? ?public MagicSquareView(Context context) { ?? ??? ?super(context); ?? ??? ?this.magicSquareActivity = (MagicSquareActivity) context; ?? ??? ?this.setFocusable(true); ?? ??? ?this.setFocusableInTouchMode(true); ?? ??? ?// TODO Auto-generated constructor stub ?? ?} ? ?? ?// 切割圖片,放入ArrayList中 ?? ?{ ?? ??? ?pieces = new ArrayList<MagicSquareView.Pic>(); ?? ??? ?Bitmap bitmap = BitmapFactory.decodeResource(getResources(), ?? ??? ??? ??? ?R.drawable.pingtu); ?? ??? ?int bitmapwidth = bitmap.getWidth(); ?? ??? ?int bitmapheight = bitmap.getHeight(); ?? ??? ?int pieceWidth = bitmapwidth / 3; ?? ??? ?int pieceHeight = bitmapheight / 3; ?? ??? ?for (int i = 0; i < 3; i++) { ?? ??? ??? ?for (int j = 0; j < 3; j++) { ?? ??? ??? ??? ?Pic piece = new Pic(); ?? ??? ??? ??? ?piece.index = j + i * 3; ?? ??? ??? ??? ?int xValue = j * pieceWidth; ?? ??? ??? ??? ?int yValue = i * pieceHeight; ?? ??? ??? ??? ?piece.piece = Bitmap.createBitmap(bitmap, xValue, yValue, ?? ??? ??? ??? ??? ??? ?pieceWidth, pieceHeight); ?? ??? ??? ??? ?pieces.add(piece); ?? ??? ??? ?} ?? ??? ?} ?? ?} ? ?? ?@Override ?? ?protected void onSizeChanged(int w, int h, int oldw, int oldh) { ? ?? ??? ?width = w / 3f; ?? ??? ?height = (h - pingtuheight) / 3f; ?? ??? ?getRect(selX, selY, selRect); ?? ??? ?Log.d(TAG, "onSizeChanged: width=" + width + ", height=" + height ?? ??? ??? ??? ?+ ",selX=" + selX + ",selY=" + selY); ?? ??? ?super.onSizeChanged(w, h, oldw, oldh); ?? ?} ? ?? ?@Override ?? ?public boolean onKeyDown(int keyCode, KeyEvent event) { ?? ??? ?switch (keyCode) { ?? ??? ?case KeyEvent.KEYCODE_DPAD_UP: ?? ??? ??? ?select(selX, selY - 1); ?? ??? ??? ?break; ?? ??? ?case KeyEvent.KEYCODE_DPAD_DOWN: ?? ??? ??? ?select(selX, selY + 1); ?? ??? ??? ?break; ?? ??? ?case KeyEvent.KEYCODE_DPAD_LEFT: ?? ??? ??? ?select(selX - 1, selY); ?? ??? ??? ?break; ?? ??? ?case KeyEvent.KEYCODE_DPAD_RIGHT: ?? ??? ??? ?select(selX + 1, selY); ?? ??? ??? ?break; ?? ??? ?case KeyEvent.KEYCODE_ENTER: ?? ??? ?case KeyEvent.KEYCODE_DPAD_CENTER: ?? ??? ??? ?Point point = magicSquareActivity.move(selX, selY); ?? ??? ??? ?if (point.x >= 0 && point.y >= 0) { ?? ??? ??? ??? ?this.invalidate(selRect); ?? ??? ??? ??? ?Rect targetRect = new Rect(); ?? ??? ??? ??? ?this.getRect(point.x, point.y, targetRect); ?? ??? ??? ??? ?this.invalidate(targetRect); ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?default: ?? ??? ??? ?return super.onKeyDown(keyCode, event); ?? ??? ?} ?? ??? ?return true; ?? ?} ? ?? ?@Override ?? ?public boolean onTouchEvent(MotionEvent event) { ?? ??? ?if (event.getAction() != MotionEvent.ACTION_DOWN) ?? ??? ??? ?return super.onTouchEvent(event); ?? ??? ?if (event.getY() <= pingtuheight) ?? ??? ??? ?return false; ?? ??? ?Log.i(TAG, ?? ??? ??? ??? ?"event.getX()=" + event.getX() + ",event.getY=" + event.getY()); ?? ??? ?select((int) (event.getX() / width), ?? ??? ??? ??? ?(int) ((event.getY() - pingtuheight) / height)); ? ?? ??? ?Point point = magicSquareActivity.move(selX, selY); ?? ??? ?if (point.x >= 0 && point.y >= 0) { ?? ??? ??? ?this.invalidate(selRect); ?? ??? ??? ?Rect targetRect = new Rect(); ?? ??? ??? ?this.getRect(point.x, point.y, targetRect); ?? ??? ??? ?this.invalidate(targetRect); ?? ??? ?} ?? ??? ?return true; ?? ?} ? ?? ?@Override ?? ?protected void onDraw(Canvas canvas) { ?? ??? ?Paint backround = new Paint(); ?? ??? ?backround.setColor(getResources().getColor(R.color.ms_backgroud)); ?? ??? ?canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), backround); ?? ??? ?// 畫(huà)出原圖及圖片的介紹 ?? ??? ?Rect dst = new Rect();// 屏幕 >>目標(biāo)矩形 ?? ??? ?Bitmap pic = BitmapFactory.decodeResource(getResources(), ?? ??? ??? ??? ?R.drawable.pingtu); ? ?? ??? ?dst.left = 0; ?? ??? ?dst.top = 0; ?? ??? ?dst.right = (int) (width * 3) / 2; ?? ??? ?dst.bottom = pingtuheight; ?? ??? ?canvas.drawBitmap(pic, null, dst, null); ?? ??? ?// 繪制出圖片的介紹 ?? ??? ?Paint textpaint = new Paint(); ?? ??? ?textpaint.setTextSize(25); ?? ??? ?canvas.drawText("一副美麗的圖片,", dst.right, 30, textpaint); ?? ??? ?canvas.drawText("但已支離破碎......", dst.right, 70, textpaint); ? ?? ??? ?// draw the board ?? ??? ?Paint dark = new Paint(); ?? ??? ?dark.setColor(getResources().getColor(R.color.ms_dark)); ? ?? ??? ?Paint hilite = new Paint(); ?? ??? ?hilite.setColor(getResources().getColor(R.color.ms_hilite)); ? ?? ??? ?Paint light = new Paint(); ?? ??? ?light.setColor(getResources().getColor(R.color.ms_light)); ? ?? ??? ?// draw the minor grid lines ?? ??? ?for (int i = 0; i < 3; i++) { ?? ??? ??? ?canvas.drawLine(0, i * height + pingtuheight, getWidth(), i ?? ??? ??? ??? ??? ?* height + pingtuheight, light); ?? ??? ??? ?canvas.drawLine(0, i * height + 1 + pingtuheight, getWidth(), i ?? ??? ??? ??? ??? ?* height + pingtuheight + 1, hilite); ?? ??? ??? ?canvas.drawLine(i * width, pingtuheight, i * width, getHeight() ?? ??? ??? ??? ??? ?+ pingtuheight, light); ?? ??? ??? ?canvas.drawLine(i * width + 1, pingtuheight, i * width + 1, ?? ??? ??? ??? ??? ?getHeight() + pingtuheight, hilite); ?? ??? ?} ?? ??? ?Rect picrect = new Rect(); ?? ??? ?for (int i = 0; i < 3; i++) { ?? ??? ??? ?for (int j = 0; j < 3; j++) { ?? ??? ??? ?int n = this.magicSquareActivity.getTitleNumber(i, j);//根據(jù)坐標(biāo)依次取出0,1,2,3,4,5,6,7,8下標(biāo)數(shù)組對(duì)應(yīng)的值 ?? ??? ??? ??? ?if (n == 0) ?? ??? ??? ??? ??? ?continue; ?? ??? ??? ??? ?picrect.left = (int) (i * width); ?? ??? ??? ??? ?picrect.top = pingtuheight + (int) (j * height); ?? ??? ??? ??? ?picrect.right = (int) (i * width + width); ?? ??? ??? ??? ?picrect.bottom = (int) (pingtuheight + j * height + height); ?? ??? ??? ??? ?canvas.drawBitmap(pieces.get(n).getPiece(), null, picrect, null); ? ?? ??? ??? ?} ?? ??? ?} ? ?? ??? ?Paint selected = new Paint(); ?? ??? ?selected.setColor(getResources().getColor(R.color.ms_selected)); ?? ??? ?canvas.drawRect(selRect, selected); ? ?? ??? ?if (magicSquareActivity.win()) { ?? ??? ??? ?Dialog winDlg = new Win(magicSquareActivity); ?? ??? ??? ?winDlg.show(); ?? ??? ??? ?magicSquareActivity.finish(); ?? ??? ?} ?? ?} ? ?? ?private void getRect(int x, int y, Rect rect) { ?? ??? ?Log.i(TAG, "getRect" + x + "y" + y); ?? ??? ?rect.set((int) (x * width), (int) (y * height + pingtuheight), (int) (x ?? ??? ??? ??? ?* width + width), (int) (y * height + height + pingtuheight)); ?? ?} ? ?? ?private void select(int x, int y) { ?? ??? ?invalidate(selRect); ?? ??? ?selX = Math.min(Math.max(x, 0), 2); ?? ??? ?selY = Math.min(Math.max(y, 0), 2); ?? ??? ?getRect(selX, selY, selRect); ?? ??? ?invalidate(selRect); ?? ?} ? ?? ?public class Pic { ?? ??? ?public int getIndex() { ?? ??? ??? ?return index; ?? ??? ?} ? ?? ??? ?public void setIndex(int index) { ?? ??? ??? ?this.index = index; ?? ??? ?} ? ?? ??? ?public Bitmap getPiece() { ?? ??? ??? ?return piece; ?? ??? ?} ? ?? ??? ?public void setPiece(Bitmap piece) { ?? ??? ??? ?this.piece = piece; ?? ??? ?} ? ?? ??? ?int index; ?? ??? ?Bitmap piece; ?? ?} }
三、運(yùn)行結(jié)果
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android自定義view實(shí)現(xiàn)拖動(dòng)小球移動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android自定義view實(shí)現(xiàn)拖動(dòng)小球移動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11android dialog根據(jù)彈窗等級(jí)排序顯示的示例代碼
這篇文章主要介紹了android dialog根據(jù)彈窗等級(jí)排序顯示,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10安卓(android)怎么實(shí)現(xiàn)下拉刷新
這里我們將采取的方案是使用組合View的方式,先自定義一個(gè)布局繼承自LinearLayout,然后在這個(gè)布局中加入下拉頭和ListView這兩個(gè)子元素,并讓這兩個(gè)子元素縱向排列。對(duì)安卓(android)怎么實(shí)現(xiàn)下拉刷新的相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-04-04Android實(shí)現(xiàn)帶有指示器的自定義底部導(dǎo)航欄
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)帶有指示器的自定義底部導(dǎo)航欄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04Android操作存放在assets文件夾下SQLite數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了Android操作存放在assets文件夾下SQLite數(shù)據(jù)庫(kù)的方法,實(shí)例分析了Android操作SQLite數(shù)據(jù)庫(kù)的相關(guān)技巧,需要的朋友可以參考下2015-06-06使用Kotlin開(kāi)發(fā)Android應(yīng)用的初體驗(yàn)
本篇文章主要介紹了使用Kotlin開(kāi)發(fā)Android應(yīng)用的初體驗(yàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05