在此之前,先修复以往的一个bug,因为前面的MapList是通过static方法得到二维数组的,因此不论调用
public static int[][] getMap(int grade)该方法多少此,都将得到同一块二维数组的引用,如果一个改变,则应一个也会改变。而判断某一关是否过关比较的way[][]和may[][]的目标位置是否都变成了箱子,因此就会有一个bug. 解决办法,修改MapList,从三维数组重新拷贝出一个二维数组。 MapList.java
package edu.pushbox;public class MapList { /** * 0 nothing * 1 wall * 2 goal * 3 road * 4 box * 5 box at goal * 6 worker * */ public static int[][][] map = { { { 0, 0, 1, 1, 1, 0, 0, 0 }, { 0, 0, 1, 2, 1, 0, 0, 0 }, { 0, 0, 1, 3, 1, 1, 1, 1 }, { 1, 1, 1, 4, 3, 4, 2, 1 }, { 1, 2, 3, 4, 6, 1, 1, 1 }, { 1, 1, 1, 1, 4, 1, 0, 0 }, { 0, 0, 0, 1, 2, 1, 0, 0 }, { 0, 0, 0, 1, 1, 1, 0, 0 } }, { { 1, 1, 1, 1, 1, 0, 0, 0, 0 }, { 1, 6, 3, 3, 1, 0, 0, 0, 0 }, { 1, 3, 4, 4, 1, 0, 1, 1, 1 }, { 1, 3, 4, 3, 1, 0, 1, 2, 1 }, { 1, 1, 1, 3, 1, 1, 1, 2, 1 }, { 0, 1, 1, 3, 3, 3, 3, 2, 1 }, { 0, 1, 3, 3, 3, 1, 3, 3, 1 }, { 0, 1, 3, 3, 3, 1, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 0, 0, 0 } } }; public static int count = map.length; public static int getCount() { return count; } /* * 判断是否到最后一关 */ public static boolean isEnd(int grade) { if(grade==count){ return true; }else{ return false; } }/* * 从MapList分离出int map[][] */ public static int[][] getMap(int grade) { int row = map[grade].length; int col = map[grade][0].length; int[][] result = new int[row][col]; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result[i][j] = map[grade][i][j]; } } return result; } /* * CopyMap return int[][] */ public static int[][] copyMap(int[][] src) { int row = src.length; int col = src[0].length; int[][] result = new int[row][col]; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result[i][j] = src[i][j]; } } return result; }}
本节: 当某一步走错是需要有一个back返回功能,这就要记录下上一次的map存起来,当用户需要返回时,再取回。这就要求每一次推之前就要先记录当前map[][]然后再更新。特别添加map助手类。
CurrentMap.java(把map[][]包装,以便存入mapUtil中)
package edu.pushbox.util;public class CurrentMap { private int[][] currentMap; public int[][] getCurrentMap() { int row = currentMap.length; int col = currentMap[0].length; int[][] result = new int[row][col]; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result[i][j] = currentMap[i][j]; } } return result; } public void setCurrentMap(int[][] currentMap) { this.currentMap = currentMap; } public CurrentMap(int[][] currentMap) { int row = currentMap.length; int col = currentMap[0].length; int[][] result = new int[row][col]; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { result[i][j] = currentMap[i][j]; } } this.currentMap = result; }}
MapUtils.java
package edu.pushbox.util;import java.util.ArrayList;public class MapUtils { private ArrayListlist; private int size=10; public int getSize() { return size; } public void setSize(int size) { this.size = size; } private static MapUtils mapUtils = new MapUtils(); private MapUtils() { list = new ArrayList (); } public static MapUtils getSingleton() { return mapUtils; } /* * 判断是否能回 */ public boolean canBack() { boolean flag = false; if (list.size() > 0) { flag = true; } return flag; } /* * 储存一步 */ public void storeOneMap(CurrentMap currentMap) { list.add(currentMap); if (list.size() > size) { list.remove(0); } } /* * 退回一步 */ public CurrentMap returnBack() { CurrentMap currentMap = list.get(list.size() - 1); list.remove(list.size() - 1); return currentMap; } /* * 清空路 */ public void clear() { list.clear(); }}
GameView.java
package edu.pushbox;import android.annotation.SuppressLint;import android.app.AlertDialog;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.KeyEvent;import android.view.View;import android.view.WindowManager;import android.widget.Toast;import edu.phshbox.R;import edu.pushbox.service.PreferencesService;import edu.pushbox.util.CurrentMap;import edu.pushbox.util.MapUtils;import edu.pushbox.util.Point;import edu.pushbox.util.Position;public class GameView extends View { private int count = 0;// count private long beginTime = 0;// time private long currentTime = 0;// time int width = 0; int oxOff = 15; int oyOff = 30; GameMain gameMain = null; public final int WALL = 1;// 墙 public final int GOAL = 2;// 目标 public final int ROAD = 3;// 路 public final int BOX = 4;// 锟斤拷锟斤拷 public final int BOX_AT_GOAL = 5;// 锟斤拷锟接碉拷目锟斤拷位锟斤拷 public final int WORKER = 6;// public final int BACK = 7; public final int UP = 8; public final int DOWN = 9; public final int LEFT = 10; public final int RIGHT = 11; public final int EXIT = 12; public final int SETTING = 13; private MapUtils mapUtils = MapUtils.getSingleton();; private Point workPoint; int wrow, wcolumn; public static int picSize = 30; private int map[][] = null;// 路锟斤拷位锟斤拷 private int way[][] = null;// 原始路锟斤拷位锟斤拷 private int row = 0; private int col = 0; private static int grade = 0; private String[] arrayGrade = null; private static final int GRADE = 2; private Bitmap picture[] = null; private PreferencesService preferencesService = null; private int selectedGradeIndex = 0; public GameView(Context context, AttributeSet attrs) { super(context, attrs); gameMain = (GameMain) context; preferencesService = new PreferencesService(context); WindowManager win = gameMain.getWindowManager(); width = win.getDefaultDisplay().getWidth(); grade = Integer.parseInt(preferencesService.getPreferences("grade")); Log.d("GRADE", grade + ""); init(); } public void init() { initMap(); initWay(); initMapUtils(); initWorkerPosition(); initTimeAndCount(); reset(); initPicture(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { moveDown(); } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { moveUp(); } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { moveLeft(); } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { moveRight(); } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { if (mapUtils.canBack()) { count--; returnBack(); } else { Toast.makeText(this.getContext(), "Can't return more", Toast.LENGTH_LONG).show(); } } if (Position.isSuccess(map, way, GOAL)) { Dialog alterDialog = new AlertDialog.Builder(getContext()) .setTitle(R.string.tip) .setMessage(R.string.continue_next) .setIcon(getResources().getDrawable(R.drawable.tip)) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { GameView.grade = GameView.grade + 1; preferencesService.save("grade", grade); // Log.d("Grade",grade+""); if (MapList.isEnd(grade)) { resetGrade(); } Log.d("Grade", grade + ""); init(); initMapUtils(); } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }).create(); alterDialog.show(); } invalidate(); currentTime = System.currentTimeMillis(); invalidate(); return super.onKeyDown(keyCode, event); } private void returnBack() { map = mapUtils.returnBack().getCurrentMap(); initWay(); initWorkerPosition(); } /* * 重置关数 */ private void resetGrade() { grade = 0; } /** *移动之前先保存当前路径 */ private void moveDown() { if (map[wrow + 1][wcolumn] == ROAD || map[wrow + 1][wcolumn] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow + 1][wcolumn] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wrow++; return; } else if (map[wrow + 1][wcolumn] == BOX || map[wrow + 1][wcolumn] == BOX_AT_GOAL) { if (map[wrow + 2][wcolumn] == ROAD || map[wrow + 2][wcolumn] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow + 2][wcolumn] = map[wrow + 2][wcolumn] == GOAL ? BOX_AT_GOAL : BOX; map[wrow + 1][wcolumn] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wrow++; return; } } } private void moveUp() { if (map[wrow - 1][wcolumn] == ROAD || map[wrow - 1][wcolumn] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow - 1][wcolumn] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wrow--; return; } else if (map[wrow - 1][wcolumn] == BOX || map[wrow - 1][wcolumn] == BOX_AT_GOAL) { if (map[wrow - 2][wcolumn] == ROAD || map[wrow - 2][wcolumn] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow - 2][wcolumn] = map[wrow - 2][wcolumn] == GOAL ? BOX_AT_GOAL : BOX; map[wrow - 1][wcolumn] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wrow--; return; } } } private void moveLeft() { if (map[wrow][wcolumn - 1] == ROAD || map[wrow][wcolumn - 1] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow][wcolumn - 1] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wcolumn--; return; } else if (map[wrow][wcolumn - 1] == BOX || map[wrow][wcolumn - 1] == BOX_AT_GOAL) { if (map[wrow][wcolumn - 2] == ROAD || map[wrow][wcolumn - 2] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow][wcolumn - 2] = map[wrow][wcolumn - 2] == GOAL ? BOX_AT_GOAL : BOX; map[wrow][wcolumn - 1] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wcolumn--; return; } } } private void moveRight() { if (map[wrow][wcolumn + 1] == ROAD || map[wrow][wcolumn + 1] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow][wcolumn + 1] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wcolumn++; return; } else if (map[wrow][wcolumn + 1] == BOX || map[wrow][wcolumn + 1] == BOX_AT_GOAL) { if (map[wrow][wcolumn + 2] == ROAD || map[wrow][wcolumn + 2] == GOAL) { count++; mapUtils.storeOneMap(new CurrentMap(map)); map[wrow][wcolumn + 2] = map[wrow][wcolumn + 2] == GOAL ? BOX_AT_GOAL : BOX; map[wrow][wcolumn + 1] = WORKER; map[wrow][wcolumn] = roadOrGoal(); wcolumn++; return; } } } private int roadOrGoal() { int result = ROAD; if (way[wrow][wcolumn] == GOAL) result = GOAL; return result; } public void reset() { row = map.length; col = map[0].length; picSize = (int) Math.floor((width - oxOff - oyOff) / col); } private void initMap() { map = MapList.getMap(grade); } // private void initTimeAndCount() { beginTime = System.currentTimeMillis(); currentTime = System.currentTimeMillis(); count = 0; } /* * copy map to way */ private void initWay() { way = MapList.copyMap(map); } /* * getWorkPosition */ private void initWorkerPosition() { workPoint = Position.getPosition(map, WORKER);// 找到人的位置 wrow = workPoint.row; wcolumn = workPoint.column; } /* * initMapUtils */ private void initMapUtils() { mapUtils.clear(); } private void initPicture() { picture = new Bitmap[14]; loadPicture(WALL, R.drawable.wall); loadPicture(GOAL, R.drawable.goal); loadPicture(ROAD, R.drawable.road); loadPicture(BOX, R.drawable.box); loadPicture(BOX_AT_GOAL, R.drawable.box_at_goal); loadPicture(WORKER, R.drawable.worker); loadPicture(BACK, R.drawable.back); loadPicture(UP, R.drawable.up); loadPicture(DOWN, R.drawable.down); loadPicture(LEFT, R.drawable.left); loadPicture(RIGHT, R.drawable.right); loadPicture(EXIT, R.drawable.exit); loadPicture(SETTING, R.drawable.setting); } private void loadPicture(int key, int pictureId) { Drawable drawable = getResources().getDrawable(pictureId); Bitmap bitMap = Bitmap.createBitmap(picSize, picSize, Bitmap.Config.ARGB_8888); drawable.setBounds(0, 0, picSize, picSize); Canvas canvas = new Canvas(bitMap); drawable.draw(canvas); picture[key] = bitMap; } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.RED); paint.setTextSize(14); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (map[i][j] > 0) canvas.drawBitmap(picture[map[i][j]], oxOff + picSize * j, oyOff + picSize * i, paint); } } canvas.drawText(getContext().getString(R.string.time) + "" + (currentTime - beginTime) / 1000, 6, 16, paint); canvas.drawText(getContext().getString(R.string.count) + "" + count, 190, 16, paint); canvas.drawBitmap(picture[BACK], oxOff, oyOff + row * picSize + 20, paint); canvas.drawBitmap(picture[UP], oxOff + picSize, oyOff + row * picSize + 20, paint); canvas.drawBitmap(picture[DOWN], oxOff + 2 * picSize, oyOff + row * picSize + 20, paint); canvas.drawBitmap(picture[LEFT], oxOff + 3 * picSize, oyOff + row * picSize + 20, paint); canvas.drawBitmap(picture[RIGHT], oxOff + 4 * picSize, oyOff + row * picSize + 20, paint); canvas.drawBitmap(picture[EXIT], oxOff + 5 * picSize + 10, oyOff + row * picSize + 20, paint); canvas.drawBitmap(picture[SETTING], oxOff + 7 * picSize, oyOff + row * picSize + 20, paint); super.onDraw(canvas); }}