Android 小游戏2048 代码简单实现

package com.my2048;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

/**
2048简单实现的小游戏 —> 在布局里的引用下就可以了
*/

public class My2048View extends View {

//TODO 先画出一个整体的视图出来  --> 整体的一个图案画出来
//TODO 创建画笔,缓存一个数组,记录数字以便下一次计算
//TODO 创建四个方向的计算算法 上下左右不同的移动的计算(最核心的)  ---> 关联手势
//TODO 绘制
//TODO 这里主要使用了一个二维数组进行对方格的数字管理,进行一个变化
//TODO 例如:进行一个右移,我对二维数组的第一个以为数组进行处理 ---> 即判断数是否要相加
//这里没有做回退上一步的功能,你可以用一个ArrayList储存 每一步的 数组arr就可以
Paint strokePaint; //画线的笔
Paint textPaint;  //画数字的笔
int width; //记录屏幕容器给我分配的宽
int height; //记录屏幕容器分配的高
int gridWidth; //格子的宽高  --->一般为屏幕宽度的四分之一
int[][] arr = new int[4][4]; //对格子的数进行对应
int textSize = 50;  //数字的大小,这里没采用sp,最好可以采用sp单位
float textHeight;   //记录数字大小文本的高度
public My2048View(Context context) {
    this(context, null);
}

public My2048View(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public My2048View(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(); //初始化一些配置
}

private void init() { //初始化一些配置
    strokePaint = new Paint();
    strokePaint.setAntiAlias(true); //设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢
    strokePaint.setColor(Color.GRAY); //设置颜色为灰色
    strokePaint.setStrokeCap(Paint.Cap.ROUND);//设置线开始和结束点为圆弧样式
    strokePaint.setStyle(Paint.Style.STROKE); //设置为线条样式
    textPaint = new Paint();
    textPaint.setAntiAlias(true); //设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢
    textPaint.setColor(Color.BLUE); //设置颜色为蓝色
    textPaint.setStyle(Paint.Style.STROKE); //设置线条样式
    textPaint.setTextSize(textSize); //最好可以转成sp
    textPaint.setFakeBoldText(true);//设置文本为粗体
    textPaint.setTextAlign(Paint.Align.CENTER);//设置为画文字的x轴为中心点,y轴向下扩展 所以后面y轴向下点才可以

    Rect rect=new Rect();
    textPaint.getTextBounds(arr[0][0]+"", 0, 1, rect);
    textHeight = rect.height();//文本的高度
    randomNumber();//随机位置生成数
}

@Override//布局
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
}

@Override//测量
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

int startX;
int startY;
int endX;
int endY;

@Override//测量之后调用的方法  ----> 一般在这里得到view的宽高
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    width = w; //屏幕分配给我的width
    height = h; //屏幕分配给我的height
    gridWidth = w / 4;  //设置为宽度的四分之一,可以自己更改
    startX = (width - gridWidth * 4) / 2;  //记录我开始画框的坐标点 -->X轴
    startY = 0;  //记录我开始画框的坐标点 -->Y轴
    endX = w - startX; //记录我结束画框的坐标点 -->X轴
    endY = 4 * gridWidth;  //记录我结束画框的坐标点 -->Y轴
}

@Override//绘制
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.parseColor("#FFFFFFAA")); //绘制背景
    drawStroke(canvas); //绘制线条,整体的一个框架
    drawText(canvas); //绘制格子中间的数字变化
}
private void drawStroke(Canvas canvas) {
    for (int i = 0; i < 5; i++) {
        canvas.drawLine(startX + i * gridWidth, startY, startX + i * gridWidth, endY, strokePaint);//画横线
        canvas.drawLine(startX, startY + i * gridWidth, endX, startY + i * gridWidth, strokePaint);//画竖线
    }
}
private void drawText(Canvas canvas) { //画数字
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (arr[i][j]!=0)
            canvas.drawText(arr[i][j]+"", startX +gridWidth/2+gridWidth*j, startY +gridWidth/2+gridWidth*i+textHeight/2,textPaint);
        }
    }
}
float downX,downY,moveX,moveY; //   记录手势点下/移动的坐标
@Override
public boolean onTouchEvent(MotionEvent event) { //这里的处理不怎么好 ---> 你可能点动一下就有反应了
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downX =event.getX();
            downY =event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            moveX=event.getX();
            moveY =event.getY();
            break;
        case MotionEvent.ACTION_UP:
            float v = Math.abs(downX - moveX) - Math.abs(downY - moveY); //手势判断用户向哪里移动
            if(v > 0) {
                if(downX > moveX) {
                    left(); //左移
                }else {
                    right();//右移
                }
            }else{
                if(downY > moveY) {
                    up(); //向上移动
                }else {
                    down();//向下移动
                }
            }
            downX=0;downY=0;moveX=0;moveY=0;
            randomNumber(); //随机位置生数
            break;
    }
    invalidate(); //重绘制
    return true;
}
Random r = new Random();        //生成随机数的类
int[] value = new int[2];
HashMap hashMap = new HashMap<>();
private void randomNumber() {    //随机位置生成一个2
    hashMap.clear();
    int count = 0;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (0==arr[i][j]) {
               value=new int[2];//一定要不同的对象,不然会有问题
               value[0]=i;
               value[1]=j;
               hashMap.put(count,value); //记录可以随机生成的坐标点 的集合
               count++;
            }
        }
    }
    if (hashMap.size() > 0) {   //随机选一个坐标点生成数
        int i = r.nextInt(hashMap.size());//生成的数包头不包尾
        int[] ints = hashMap.get(i);
        arr[ints[0]][ints[1]]=2;  //生成一个数为2
    } else {    //做了个简单的提示
        //判断是不是输了 --- 可以自己做的更好点 --->可以缓存上一步数,看是否可以移动
        Toast.makeText(getContext(),"你要输了哦",Toast.LENGTH_SHORT).show();
    }

}
ArrayList myData = new ArrayList<>(); //缓存的集合
Integer filed;
private void down() {       //向下移动实现
    //返回一个装满不是0数字的集合
    for (int i = 0; i < 4; i++) {
        myData.clear(); //清除以前的数据
        for (int j = 0; j < 4; j++) { //遍历竖的格子里的数
            if (arr[j][i]!=0) { //如果不是0,在这竖的格子里要进行一个重新赋值
                myData.add(arr[j][i]);
                arr[j][i]=0; //把以前记录的数给清除,然后后面 进行一个重新赋值
            }
        }
        getFinalNumber2(myData); //对数据是否要相加要处理
        setNumberDown(i, myData); //数据处理之后进行一个重新赋值
    }
}
private void up() {     //向上移动实现
    for (int i = 0; i < 4; i++) {
        myData.clear();
        for (int j = 0; j < 4; j++) {
            if (arr[j][i]!=0) {
                myData.add(arr[j][i]);
                arr[j][i]=0;
            }
        }
        getFinalNumber(myData);
        setNumberUp(i, myData);
    }
}

private void right() {  //向右滑
    for (int i = 0; i < 4; i++) {
        myData.clear();
        for (int j = 0; j < 4; j++) {
            if (arr[i][j]!=0) {
                myData.add(arr[i][j]);
                arr[i][j]=0;
            }
        }
        getFinalNumber2(myData);//
        setNumberRight(i, myData);
    }
}

private void left() {  //向左滑
    for (int i = 0; i < 4; i++) {
        myData.clear();
        for (int j = 0; j < 4; j++) {
            if (arr[i][j]!=0) {
                myData.add(arr[i][j]);
                arr[i][j]=0;
            }
        }
        getFinalNumber(myData);
        setNumberLeft(i,myData);
    }
}
private void setNumberDown(int i, ArrayList myData) {
    // 重新赋值
    int size = myData.size();
    for (int j = 0; j < size; j++) {
        arr[4-1-j][i] = myData.get(size-1-j);
    }
}
private void setNumberUp(int i, ArrayList myData) {
    // 重新赋值
    int size = myData.size();
    for (int j = 0; j < size; j++) {
        arr[j][i]=myData.get(j);
    }
}
private void setNumberRight(int i, ArrayList myData) {
    int size = myData.size(); //重新赋值
    for (int j = 0; j < size; j++) {
        arr[i][4-j-1] = myData.get(size-j-1);
    }
}
private void setNumberLeft(int i, ArrayList myData) {
    // 重新赋值
    int size = myData.size();
    for (int j = 0; j < size; j++) {
        arr[i][j] = myData.get(j);
    }
}

private void getFinalNumber(ArrayList myData) {
    for (int i = 0; i < myData.size() - 1; i++) {
        filed = myData.get(i);
        if (filed.equals(myData.get(i + 1))) {//是Integer对象不能用==相比较,当integer对象小于128可以用==号相比较,因为小于128是取常量池里的
            myData.set(i, filed * 2);
            myData.remove(i + 1);
            getFinalNumber(myData);
        }
    }
}
private void getFinalNumber2(ArrayList myData) {
    int mySize = myData.size() - 1;//求出集合的size
    for (int i = mySize; i > 0; --i) {
        filed = myData.get(i);
        if (filed.equals(myData.get(i - 1))) {//是Integer对象不能用==相比较,当integer对象小于128可以用==号相比较,因为小于128是取常量池里的
            myData.set(i - 1, filed * 2);
            myData.remove(i);
            getFinalNumber2(myData);
            break;
        }
    }
}

}
//这是一个自定义的View,你直接在layout文件中直接引用就可以了,也可修改这个view的代码实现自己的要求,这个只是简单实现功能
Android 小游戏2048 代码简单实现_第1张图片

你可能感兴趣的:(游戏)