2048游戏
来源:互联网 发布:sql log shipping 编辑:程序博客网 时间:2024/06/07 19:42
//条目布局 就是里面的控件
//主要逻辑
package com.example.liuan.ceshi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.Rect;import android.util.AttributeSet;import android.util.Log;import android.view.View;/** * 2048的每个Item * * @author zhy * */public class Game2048Item extends View{/** * 该View上的数字 */private int mNumber;private String mNumberVal;private Paint mPaint;/** * 绘制文字的区域 */private Rect mBound;public Game2048Item(Context context, AttributeSet attrs, int defStyle){super(context, attrs, defStyle);mPaint = new Paint();}public Game2048Item(Context context){this(context, null);}public Game2048Item(Context context, AttributeSet attrs){this(context, attrs, 0);}public void setNumber(int number){mNumber = number;mNumberVal = mNumber + "";mPaint.setTextSize(30.0f);mBound = new Rect();mPaint.getTextBounds(mNumberVal, 0, mNumberVal.length(), mBound);invalidate();}public int getNumber(){return mNumber;}@Overrideprotected void onDraw(Canvas canvas){super.onDraw(canvas);String mBgColor = "";switch (mNumber){case 0:mBgColor = "#CCC0B3";break;case 2:mBgColor = "#EEE4DA";break;case 4:mBgColor = "#EDE0C8";break;case 8:mBgColor = "#F2B179";// #F2B179break;case 16:mBgColor = "#F49563";break;case 32:mBgColor = "#F5794D";break;case 64:mBgColor = "#F55D37";break;case 128:mBgColor = "#EEE863";break;case 256:mBgColor = "#EDB04D";break;case 512:mBgColor = "#ECB04D";break;case 1024:mBgColor = "#EB9437";break;case 2048:mBgColor = "#EA7821";break;default:mBgColor = "#EA7821";break;}mPaint.setColor(Color.parseColor(mBgColor));mPaint.setStyle(Style.FILL);canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);if (mNumber != 0)drawText(canvas);}/** * 绘制文字 * * @param canvas */private void drawText(Canvas canvas){mPaint.setColor(Color.BLACK);float x = (getWidth() - mBound.width()) / 2;float y = getHeight() / 2 + mBound.height() / 2;canvas.drawText(mNumberVal, x, y, mPaint);}}
//大布局 就是外面的控件
package com.example.liuan.ceshi;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.GestureDetector;import android.view.MotionEvent;import android.widget.RelativeLayout;import java.util.ArrayList;import java.util.List;import java.util.Random;/** * 2048的游戏面板,加入布局文件即可开始游戏 * * @author zhy * */public class Game2048Layout extends RelativeLayout{/** * 设置Item的数量n*n;默认为4 */private int mColumn = 4;/** * 存放所有的Item */private Game2048Item[] mGame2048Items;/** * Item横向与纵向的边距 */private int mMargin = 10;/** * 面板的padding */private int mPadding;/** * 检测用户滑动的手势 */private GestureDetector mGestureDetector;// 用于确认是否需要生成一个新的值private boolean isMergeHappen = true;private boolean isMoveHappen = true;/** * 记录分数 */private int mScore;public interface OnGame2048Listener{void onScoreChange(int score);void onGameOver();}private OnGame2048Listener mGame2048Listener;public void setOnGame2048Listener(OnGame2048Listener mGame2048Listener){this.mGame2048Listener = mGame2048Listener;}/** * 运动方向的枚举 * * @author zhy * */private enum ACTION{LEFT, RIGHT, UP, DOWM}public Game2048Layout(Context context, AttributeSet attrs, int defStyle){super(context, attrs, defStyle);mMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,mMargin, getResources().getDisplayMetrics());// 设置Layout的内边距,四边一致,设置为四内边距中的最小值mPadding = min(getPaddingLeft(), getPaddingTop(), getPaddingRight(),getPaddingBottom());mGestureDetector = new GestureDetector(context , new MyGestureDetector());}/** * 根据用户运动,整体进行移动合并值等 */private void action(ACTION action){// 行|列for (int i = 0; i < mColumn; i++){List<Game2048Item> row = new ArrayList<Game2048Item>();// 行|列//记录不为0的数字for (int j = 0; j < mColumn; j++){// 得到下标int index = getIndexByAction(action, i, j);Game2048Item item = mGame2048Items[index];// 记录不为0的数字if (item.getNumber() != 0){row.add(item);}}//判断是否发生移动for (int j = 0; j < mColumn && j < row.size(); j++){int index = getIndexByAction(action, i, j);Game2048Item item = mGame2048Items[index];if (item.getNumber() != row.get(j).getNumber()){isMoveHappen = true;}}// 合并相同的mergeItem(row);// 设置合并后的值for (int j = 0; j < mColumn; j++){int index = getIndexByAction(action, i, j);if (row.size() > j){mGame2048Items[index].setNumber(row.get(j).getNumber());} else{mGame2048Items[index].setNumber(0);}}}//生成数字generateNum();}/** * 根据Action和i,j得到下标 * * @param action * @param i * @param j * @return */private int getIndexByAction(ACTION action, int i, int j){int index = -1;switch (action){case LEFT:index = i * mColumn + j;break;case RIGHT:index = i * mColumn + mColumn - j - 1;break;case UP:index = i + j * mColumn;break;case DOWM:index = i + (mColumn - 1 - j) * mColumn;break;}return index;}/** * 合并相同的Item * * @param row */private void mergeItem(List<Game2048Item> row){if (row.size() < 2)return;for (int j = 0; j < row.size() - 1; j++){Game2048Item item1 = row.get(j);Game2048Item item2 = row.get(j + 1);if (item1.getNumber() == item2.getNumber()){isMergeHappen = true;int val = item1.getNumber() + item2.getNumber();item1.setNumber(val);// 加分mScore += val;if (mGame2048Listener != null){mGame2048Listener.onScoreChange(mScore);}// 向前移动for (int k = j + 1; k < row.size() - 1; k++){row.get(k).setNumber(row.get(k + 1).getNumber());}row.get(row.size() - 1).setNumber(0);return;}}}/** * 得到多值中的最小值 * * @param params * @return */private int min(int... params){int min = params[0];for (int param : params){if (min > param){min = param;}}return min;}@Overridepublic boolean onTouchEvent(MotionEvent event){mGestureDetector.onTouchEvent(event);return true;}public Game2048Layout(Context context){this(context, null);}public Game2048Layout(Context context, AttributeSet attrs){this(context, attrs, 0);}private boolean once;/** * 测量Layout的宽和高,以及设置Item的宽和高,这里忽略wrap_content 以宽、高之中的最小值绘制正方形 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 获得正方形的边长int length = Math.min(getMeasuredHeight(), getMeasuredWidth());// 获得Item的宽度int childWidth = (length - mPadding * 2 - mMargin * (mColumn - 1))/ mColumn;if (!once){if (mGame2048Items == null){mGame2048Items = new Game2048Item[mColumn * mColumn];}// 放置Itemfor (int i = 0; i < mGame2048Items.length; i++){Game2048Item item = new Game2048Item(getContext());mGame2048Items[i] = item;item.setId(i + 1);LayoutParams lp = new LayoutParams(childWidth,childWidth);// 设置横向边距,不是最后一列if ((i + 1) % mColumn != 0){lp.rightMargin = mMargin;}// 如果不是第一列if (i % mColumn != 0){lp.addRule(RelativeLayout.RIGHT_OF,//mGame2048Items[i - 1].getId());}// 如果不是第一行,//设置纵向边距,非最后一行if ((i + 1) > mColumn){lp.topMargin = mMargin;lp.addRule(RelativeLayout.BELOW,//mGame2048Items[i - mColumn].getId());}addView(item, lp);}generateNum();}once = true;setMeasuredDimension(length, length);}/** * 是否填满数字 * * @return */private boolean isFull(){// 检测是否所有位置都有数字for (int i = 0; i < mGame2048Items.length; i++){if (mGame2048Items[i].getNumber() == 0){return false;}}return true;}/** * 检测当前所有的位置都有数字,且相邻的没有相同的数字 * * @return */private boolean checkOver(){// 检测是否所有位置都有数字if (!isFull()){return false;}for (int i = 0; i < mColumn; i++){for (int j = 0; j < mColumn; j++){int index = i * mColumn + j;// 当前的ItemGame2048Item item = mGame2048Items[index];// 右边if ((index + 1) % mColumn != 0){Log.e("TAG", "RIGHT");// 右边的ItemGame2048Item itemRight = mGame2048Items[index + 1];if (item.getNumber() == itemRight.getNumber())return false;}// 下边if ((index + mColumn) < mColumn * mColumn){Log.e("TAG", "DOWN");Game2048Item itemBottom = mGame2048Items[index + mColumn];if (item.getNumber() == itemBottom.getNumber())return false;}// 左边if (index % mColumn != 0){Log.e("TAG", "LEFT");Game2048Item itemLeft = mGame2048Items[index - 1];if (itemLeft.getNumber() == item.getNumber())return false;}// 上边if (index + 1 > mColumn){Log.e("TAG", "UP");Game2048Item itemTop = mGame2048Items[index - mColumn];if (item.getNumber() == itemTop.getNumber())return false;}}}return true;}/** * 产生一个数字 */public void generateNum(){if (checkOver()){Log.e("TAG", "GAME OVER");if (mGame2048Listener != null){mGame2048Listener.onGameOver();}return;}if (!isFull()){if (isMoveHappen || isMergeHappen){Random random = new Random();int next = random.nextInt(16);Game2048Item item = mGame2048Items[next];while (item.getNumber() != 0){next = random.nextInt(16);item = mGame2048Items[next];}item.setNumber(Math.random() > 0.75 ? 4 : 2);isMergeHappen = isMoveHappen = false;}}}/** * 重新开始游戏 */public void restart(){for (Game2048Item item : mGame2048Items){item.setNumber(0);}mScore = 0;if (mGame2048Listener != null){mGame2048Listener.onScoreChange(mScore);}isMoveHappen = isMergeHappen = true;generateNum();}class MyGestureDetector extends GestureDetector.SimpleOnGestureListener{final int FLING_MIN_DISTANCE = 50;@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY){float x = e2.getX() - e1.getX();float y = e2.getY() - e1.getY();if (x > FLING_MIN_DISTANCE&& Math.abs(velocityX) > Math.abs(velocityY)){action(ACTION.RIGHT);// Toast.makeText(getContext(), "toRight",// Toast.LENGTH_SHORT).show();} else if (x < -FLING_MIN_DISTANCE&& Math.abs(velocityX) > Math.abs(velocityY)){action(ACTION.LEFT);// Toast.makeText(getContext(), "toLeft",// Toast.LENGTH_SHORT).show();} else if (y > FLING_MIN_DISTANCE&& Math.abs(velocityX) < Math.abs(velocityY)){action(ACTION.DOWM);// Toast.makeText(getContext(), "toDown",// Toast.LENGTH_SHORT).show();} else if (y < -FLING_MIN_DISTANCE&& Math.abs(velocityX) < Math.abs(velocityY)){action(ACTION.UP);// Toast.makeText(getContext(), "toUp",// Toast.LENGTH_SHORT).show();}return true;}}}//布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.liuan.ceshi.Game2048Layout android:id="@+id/id_game2048" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerInParent="true" android:background="#ffffff" android:padding="10dp"></com.example.liuan.ceshi.Game2048Layout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/id_game2048" android:layout_centerHorizontal="true" android:layout_marginBottom="20dp" android:background="#EEE4DA" android:orientation="horizontal"> <TextView android:id="@+id/id_score" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="4dp" android:text="Score: 0" android:textColor="#EA7821" android:textSize="30sp" android:textStyle="bold" /> </LinearLayout></RelativeLayout>
//主要逻辑
package com.example.liuan.ceshi;import android.content.DialogInterface;import android.os.Bundle;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;import android.widget.TextView;public class MainActivity extends AppCompatActivity implements Game2048Layout.OnGame2048Listener { private TextView mScore; private Game2048Layout mGame2048Layout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mScore = (TextView) findViewById(R.id.id_score); mGame2048Layout = (Game2048Layout) findViewById(R.id.id_game2048); mGame2048Layout.setOnGame2048Listener(this); } @Override public void onScoreChange(int score) { mScore.setText("分数: " + score); } @Override public void onGameOver() { new AlertDialog.Builder(this).setTitle("游戏结束") .setMessage("你的最后得分是: " + mScore.getText()) .setPositiveButton("重新开始", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mGame2048Layout.restart(); } }).setNegativeButton("退出游戏", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }).show(); }}
1 0
- 2048游戏
- 游戏2048
- 2048游戏
- 2048游戏
- c++版2048游戏
- android 2048 游戏 源码
- javascript版 2048游戏
- 游戏源码2048
- 网页版<2048>游戏
- cocos2dx开发2048游戏
- android 2048游戏实现
- 2048游戏java版
- 2048 Puzzle游戏攻略
- 2048游戏的逻辑
- C++控制台游戏2048
- HTML5开发游戏“2048”
- 游戏2048的实现
- Cocos2dx------2048游戏
- Docker 基本命令
- 在CentOS 6.5上升级PHP5.5
- 设计模式学习之模版方法模式
- 百度地图生成
- 使用ADB命令安装apk出现问题:Failure [INSTALL_FAILED_NO_MATCHING_ABIS:Failed to etract native libraries
- 2048游戏
- 自学
- 数组根据一个字段排序
- 【表达式求值】中缀表达式变后缀+后缀表达式的求法 (NYOJ 35+NYOJ 1272表达式求值)
- google vr 入门之制作简易的VR播放器(二)
- 字符串函数
- web中文件上传下载
- 转载php in_array()问题
- Xcode8 打印:AQDefaultDevice (173): skipping input stream