package com.imooc.game2048.view; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences.Editor; import android.graphics.Point; import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.Display; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.ScaleAnimation; import android.widget.EditText; import android.widget.GridLayout; import com.imooc.game2048.activity.Game; import com.imooc.game2048.bean.GameItem; import com.imooc.game2048.config.Config; import java.util.ArrayList; import java.util.List; public class GameView extends GridLayout implements OnTouchListener { // GameView对应矩阵 private GameItem[][] mGameMatrix; // 空格List private List<Point> mBlanks; // 矩阵行列数 private int mGameLines; // 记录坐标 private int mStartX, mStartY, mEndX, mEndY; // 辅助数组 private List<Integer> mCalList; private int mKeyItemNum = -1; // 历史记录数组 private int[][] mGameMatrixHistory; // 历史记录分数 private int mScoreHistory; // 最高记录 private int mHighScore; // 目标分数 private int mTarget; public GameView(Context context) { super(context); mTarget = Config.mSp.getInt(Config.KEY_GAME_GOAL, 2048); initGameMatrix(); } public GameView(Context context, AttributeSet attrs) { super(context, attrs); initGameMatrix(); } public void startGame() { initGameMatrix(); initGameView(Config.mItemSize); } private void initGameView(int cardSize) { removeAllViews(); GameItem card; for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { card = new GameItem(getContext(), 0); addView(card, cardSize, cardSize); // 初始化GameMatrix全部为0 空格List为所有 mGameMatrix[i][j] = card; mBlanks.add(new Point(i, j)); } } // 添加随机数字 addRandomNum(); addRandomNum(); } /** * 撤销上次移动 */ public void revertGame() { // 第一次不能撤销 int sum = 0; for (int[] element : mGameMatrixHistory) { for (int i : element) { sum += i; } } if (sum != 0) { Game.getGameActivity().setScore(mScoreHistory, 0); Config.SCROE = mScoreHistory; for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { mGameMatrix[i][j].setNum(mGameMatrixHistory[i][j]); } } } } /** * 添加随机数字 */ private void addRandomNum() { getBlanks(); if (mBlanks.size() > 0) { int randomNum = (int) (Math.random() * mBlanks.size()); Point randomPoint = mBlanks.get(randomNum); mGameMatrix[randomPoint.x][randomPoint.y] .setNum(Math.random() > 0.2d ? 2 : 4); animCreate(mGameMatrix[randomPoint.x][randomPoint.y]); } } /** * 生成动画 * * @param target GameItem */ private void animCreate(GameItem target) { ScaleAnimation sa = new ScaleAnimation(0.1f, 1, 0.1f, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sa.setDuration(100); target.setAnimation(null); target.getItemView().startAnimation(sa); } /** * super模式下添加一个指定数字 */ private void addSuperNum(int num) { if (checkSuperNum(num)) { getBlanks(); if (mBlanks.size() > 0) { int randomNum = (int) (Math.random() * mBlanks.size()); Point randomPoint = mBlanks.get(randomNum); mGameMatrix[randomPoint.x][randomPoint.y].setNum(num); animCreate(mGameMatrix[randomPoint.x][randomPoint.y]); } } } /** * 检查添加的数是否是指定的数 * * @param num num * @return 添加的数 */ private boolean checkSuperNum(int num) { boolean flag = (num == 2 || num == 4 || num == 8 || num == 16 || num == 32 || num == 64 || num == 128 || num == 256 || num == 512 || num == 1024); return flag; } /** * 获取空格Item数组 */ private void getBlanks() { mBlanks.clear(); for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { if (mGameMatrix[i][j].getNum() == 0) { mBlanks.add(new Point(i, j)); } } } } /** * 初始化View */ private void initGameMatrix() { // 初始化矩阵 removeAllViews(); mScoreHistory = 0; Config.SCROE = 0; Config.mGameLines = Config.mSp.getInt(Config.KEY_GAME_LINES, 4); mGameLines = Config.mGameLines; mGameMatrix = new GameItem[mGameLines][mGameLines]; mGameMatrixHistory = new int[mGameLines][mGameLines]; mCalList = new ArrayList<Integer>(); mBlanks = new ArrayList<Point>(); mHighScore = Config.mSp.getInt(Config.KEY_HIGH_SCROE, 0); setColumnCount(mGameLines); setRowCount(mGameLines); setOnTouchListener(this); // 初始化View参数 DisplayMetrics metrics = new DisplayMetrics(); WindowManager wm = (WindowManager) getContext().getSystemService( Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); display.getMetrics(metrics); Config.mItemSize = metrics.widthPixels / Config.mGameLines; initGameView(Config.mItemSize); } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: saveHistoryMatrix(); mStartX = (int) event.getX(); mStartY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: mEndX = (int) event.getX(); mEndY = (int) event.getY(); judgeDirection(mEndX - mStartX, mEndY - mStartY); if (isMoved()) { addRandomNum(); // 修改显示分数 Game.getGameActivity().setScore(Config.SCROE, 0); } checkCompleted(); break; default: break; } return true; } /** * 保存历史记录 */ private void saveHistoryMatrix() { mScoreHistory = Config.SCROE; for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { mGameMatrixHistory[i][j] = mGameMatrix[i][j].getNum(); } } } private int getDeviceDensity() { DisplayMetrics metrics = new DisplayMetrics(); WindowManager wm = (WindowManager) getContext().getSystemService( Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(metrics); return (int) metrics.density; } /** * 根据偏移量判断移动方向 * * @param offsetX offsetX * @param offsetY offsetY */ private void judgeDirection(int offsetX, int offsetY) { int density = getDeviceDensity(); int slideDis = 5 * density; int maxDis = 200 * density; boolean flagNormal = (Math.abs(offsetX) > slideDis || Math.abs(offsetY) > slideDis) && (Math.abs(offsetX) < maxDis) && (Math.abs(offsetY) < maxDis); boolean flagSuper = Math.abs(offsetX) > maxDis || Math.abs(offsetY) > maxDis; if (flagNormal && !flagSuper) { if (Math.abs(offsetX) > Math.abs(offsetY)) { if (offsetX > slideDis) { swipeRight(); } else { swipeLeft(); } } else { if (offsetY > slideDis) { swipeDown(); } else { swipeUp(); } } } else if (flagSuper) { // 启动超级用户权限来添加自定义数字 AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); final EditText et = new EditText(getContext()); builder.setTitle("Back Door") .setView(et) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { if (!TextUtils.isEmpty(et.getText())) { addSuperNum(Integer.parseInt(et .getText().toString())); checkCompleted(); } } }) .setNegativeButton("ByeBye", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { arg0.dismiss(); } }).create().show(); } } /** * 检测所有数字 看是否有满足条件的 * * @return 0:结束 1:正常 2:成功 */ private int checkNums() { getBlanks(); if (mBlanks.size() == 0) { for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { if (j < mGameLines - 1) { if (mGameMatrix[i][j].getNum() == mGameMatrix[i][j + 1] .getNum()) { return 1; } } if (i < mGameLines - 1) { if (mGameMatrix[i][j].getNum() == mGameMatrix[i + 1][j] .getNum()) { return 1; } } } } return 0; } for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { if (mGameMatrix[i][j].getNum() == mTarget) { return 2; } } } return 1; } /** * 判断是否结束 * <p/> * 0:结束 1:正常 2:成功 */ private void checkCompleted() { int result = checkNums(); if (result == 0) { if (Config.SCROE > mHighScore) { Editor editor = Config.mSp.edit(); editor.putInt(Config.KEY_HIGH_SCROE, Config.SCROE); editor.apply(); Game.getGameActivity().setScore(Config.SCROE, 1); Config.SCROE = 0; } AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle("Game Over") .setPositiveButton("Again", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { startGame(); } }).create().show(); Config.SCROE = 0; } else if (result == 2) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle("Mission Accomplished") .setPositiveButton("Again", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { // 重新开始 startGame(); } }) .setNegativeButton("Continue", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { // 继续游戏 修改target Editor editor = Config.mSp.edit(); if (mTarget == 1024) { editor.putInt(Config.KEY_GAME_GOAL, 2048); mTarget = 2048; Game.getGameActivity().setGoal(2048); } else if (mTarget == 2048) { editor.putInt(Config.KEY_GAME_GOAL, 4096); mTarget = 4096; Game.getGameActivity().setGoal(4096); } else { editor.putInt(Config.KEY_GAME_GOAL, 4096); mTarget = 4096; Game.getGameActivity().setGoal(4096); } editor.apply(); } }).create().show(); Config.SCROE = 0; } } /** * 判断是否移动过(是否需要新增Item) * * @return 是否移动 */ private boolean isMoved() { for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { if (mGameMatrixHistory[i][j] != mGameMatrix[i][j].getNum()) { return true; } } } return false; } /** * 滑动事件:上 */ private void swipeUp() { for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { int currentNum = mGameMatrix[j][i].getNum(); if (currentNum != 0) { if (mKeyItemNum == -1) { mKeyItemNum = currentNum; } else { if (mKeyItemNum == currentNum) { mCalList.add(mKeyItemNum * 2); Config.SCROE += mKeyItemNum * 2; mKeyItemNum = -1; } else { mCalList.add(mKeyItemNum); mKeyItemNum = currentNum; } } } else { continue; } } if (mKeyItemNum != -1) { mCalList.add(mKeyItemNum); } // 改变Item值 for (int j = 0; j < mCalList.size(); j++) { mGameMatrix[j][i].setNum(mCalList.get(j)); } for (int m = mCalList.size(); m < mGameLines; m++) { mGameMatrix[m][i].setNum(0); } // 重置行参数 mKeyItemNum = -1; mCalList.clear(); } } /** * 滑动事件:下 */ private void swipeDown() { for (int i = mGameLines - 1; i >= 0; i--) { for (int j = mGameLines - 1; j >= 0; j--) { int currentNum = mGameMatrix[j][i].getNum(); if (currentNum != 0) { if (mKeyItemNum == -1) { mKeyItemNum = currentNum; } else { if (mKeyItemNum == currentNum) { mCalList.add(mKeyItemNum * 2); Config.SCROE += mKeyItemNum * 2; mKeyItemNum = -1; } else { mCalList.add(mKeyItemNum); mKeyItemNum = currentNum; } } } else { continue; } } if (mKeyItemNum != -1) { mCalList.add(mKeyItemNum); } // 改变Item值 for (int j = 0; j < mGameLines - mCalList.size(); j++) { mGameMatrix[j][i].setNum(0); } int index = mCalList.size() - 1; for (int m = mGameLines - mCalList.size(); m < mGameLines; m++) { mGameMatrix[m][i].setNum(mCalList.get(index)); index--; } // 重置行参数 mKeyItemNum = -1; mCalList.clear(); index = 0; } } /** * 滑动事件:左 */ private void swipeLeft() { for (int i = 0; i < mGameLines; i++) { for (int j = 0; j < mGameLines; j++) { int currentNum = mGameMatrix[i][j].getNum(); if (currentNum != 0) { if (mKeyItemNum == -1) { mKeyItemNum = currentNum; } else { if (mKeyItemNum == currentNum) { mCalList.add(mKeyItemNum * 2); Config.SCROE += mKeyItemNum * 2; mKeyItemNum = -1; } else { mCalList.add(mKeyItemNum); mKeyItemNum = currentNum; } } } else { continue; } } if (mKeyItemNum != -1) { mCalList.add(mKeyItemNum); } // 改变Item值 for (int j = 0; j < mCalList.size(); j++) { mGameMatrix[i][j].setNum(mCalList.get(j)); } for (int m = mCalList.size(); m < mGameLines; m++) { mGameMatrix[i][m].setNum(0); } // 重置行参数 mKeyItemNum = -1; mCalList.clear(); } } /** * 滑动事件:右 */ private void swipeRight() { for (int i = mGameLines - 1; i >= 0; i--) { for (int j = mGameLines - 1; j >= 0; j--) { int currentNum = mGameMatrix[i][j].getNum(); if (currentNum != 0) { if (mKeyItemNum == -1) { mKeyItemNum = currentNum; } else { if (mKeyItemNum == currentNum) { mCalList.add(mKeyItemNum * 2); Config.SCROE += mKeyItemNum * 2; mKeyItemNum = -1; } else { mCalList.add(mKeyItemNum); mKeyItemNum = currentNum; } } } else { continue; } } if (mKeyItemNum != -1) { mCalList.add(mKeyItemNum); } // 改变Item值 for (int j = 0; j < mGameLines - mCalList.size(); j++) { mGameMatrix[i][j].setNum(0); } int index = mCalList.size() - 1; for (int m = mGameLines - mCalList.size(); m < mGameLines; m++) { mGameMatrix[i][m].setNum(mCalList.get(index)); index--; } // 重置行参数 mKeyItemNum = -1; mCalList.clear(); index = 0; } } }