欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数独游戏实战学习

程序员文章站 2024-03-16 20:46:34
...

一、使用基础

1.使用画笔paint在画布canvas上画一条线

Paint paint = new Paint();
// 向画笔赋予颜色,使用color类自带的颜色
paint.setColor(Color.RED);
// 向画笔赋予颜色,使用argb方法(透明度,颜色3位参数)0-255
paint.setARGB(200,0,100,200);
// 是否打开抗锯齿参数(true:打开;false:关闭)打开效果会更好,不打开适用于像素点游戏
paint.setAntiAlias(true);
// 使用画笔paint在画布canvas上画一条起点0,200重点200,0的线
canvas.drawLine(0,200,200,0,paint);

2.使用画笔paint在画布canvas上画一个矩形

// 使用画笔paint在画布canvas上画一个距离左边界100,上边界200,宽度50,高度300的实心矩形
canvas.drawRect(100,200,50,300,paint);

3.使用画笔paint在画布canvas上画一个空心矩形

// 设置画笔画出的为空心图形
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(100,200,50,300,paint);

4.使用画笔paint在画布canvas上画一个空心矩形,并加粗边框

paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
canvas.drawRect(100,200,50,300,paint);

5.使用画笔paint在画布canvas上画一个圆

// 使用画笔paint在画布canvas上画一个X轴坐标300,Y轴坐标300,半径100的圆
canvas.drawCircle(300,300,100,paint);

6.使用另一支画笔paint2在画布canvas上画一个圆

// 当想要与前一个或其他图形样式不同的图形时,可以新建一个画笔对象,使用新的画笔对象画想要的图形
Paint paint2 = new Paint();
paint2.setARGB(200,1,100,200);
paint2.setAntiAlias(true);
canvas.drawCircle(300,300,100,paint2);

7.使用一支画笔paint在画布canvas上画文字图形,同时画出文字图形基准线

Paint paint = new Paint();
// 向画笔赋予颜色,使用color类自带的颜色
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setTextSize(50);
// 文字内容,起始X轴坐标,Y轴坐标,画笔
canvas.drawText(“iphone”,200,200,paint);
canvas.drawLine(0,200,500,200,paint);

8.使用一支画笔paint在画布canvas上绘制图形

    Paint paint = new Paint();
    // 向画笔赋予颜色,使用color类自带的颜色
    paint.setColor(Color.RED);
    paint.setAntiAlias(true);
    // 指定图片,X轴起始坐标,Y轴起始坐标,画笔对象
    canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher),100,200,paint);

二、绘制数独游戏基础九宫格并且放入数字

// 记录单元格宽高
private float width,height;

/*设置单元格宽高*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
	// 每个小单元格宽高均为当前屏幕的1/9
    this.width = w /9f;
    this.height = h /9f;
    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas) {
    // 绘制数独游戏基础九宫格并且放入数字
    Paint paint_bg = new Paint();
    // 绘制background颜色
    paint_bg.setColor(getResources().getColor(R.color.background));
    canvas.drawRect(0,0,getWidth(),getHeight(),paint_bg);

	// 绘制粗线颜色
    Paint paint_blackLines = new Paint();
    paint_blackLines.setColor(getResources().getColor(R.color.black));

	// 绘制两种不同颜色用于拼接显示单元格
    Paint paint_hiliteLines = new Paint();
    paint_hiliteLines.setColor(getResources().getColor(R.color.hiliteLines));

    Paint paint_lightLines = new Paint();
    paint_lightLines.setColor(getResources().getColor(R.color.lightLines));
    for (int i = 0; i < 9; i++) {
        canvas.drawLine(0,i*height,getWidth(),i*height,paint_lightLines);
        canvas.drawLine(0,i*height+1,getWidth(),i*height+1,paint_hiliteLines);
        canvas.drawLine(i*width,0,i*width,getHeight(),paint_lightLines);
        canvas.drawLine(i*width+1,0,i*width+1,getHeight(),paint_hiliteLines);
    }
    // 绘制切割线,切割为9个小单元格
    for (int i = 0; i < 9; i++) {
        if (i%3 != 0){
            continue;
        }
        canvas.drawLine(0,i*height,getWidth(),i*height,paint_blackLines);
        canvas.drawLine(0,i*height+1,getWidth(),i*height+1,paint_blackLines);
        canvas.drawLine(i*width,0,i*width,getHeight(),paint_blackLines);
        canvas.drawLine(i*width+1,0,i*width+1,getHeight(),paint_blackLines);
    }

	// 绘制文字
    Paint numberPaint = new Paint();
    numberPaint.setColor(Color.BLACK);
    numberPaint.setStyle(Paint.Style.STROKE);
    numberPaint.setTextSize(height*0.75f);
    numberPaint.setTextAlign(Paint.Align.CENTER);

    float x = width/2;
    canvas.drawText("1",3*width + x ,100,numberPaint);
    super.onDraw(canvas);
}

数独游戏实战学习

1.使用FontMetrics获得真正的居中Y轴位置

    Paint.FontMetrics fm = numberPaint.getFontMetrics();
    float x = width/2;
    // 真正的居中高度:fm.ascent(基准线到图形顶部的距离:负数) + fm.descent(基准线到图形底部的距离:正数) /2
    float y = height/2 - (fm.ascent + fm.descent) / 2;

    canvas.drawText("1",3*width + x ,y,numberPaint);

2.初始化数独假数据

public class Number {
//共计81位
private final String str = “123000000000456000000000078900012346547897426465487893146548745678912300000001527”;

private int[] shudu = new int[9*9];

public Number(){
    shudu = fromPuzzleString(str);
}
// 根据坐标轴返回对应数字
private int getTittle(int x,int y){
    return shudu[y*9 + x];
}
// 当返回的数据是0时,返回空
public String getTittleStr(int x,int y){
    int value = getTittle(x,y);
    if (value == 0){
        return "";
    }
    else {
        return String.valueOf(value);
    }
}
// 将字符串数据拆成int数组
protected int[] fromPuzzleString(String src){
    int[] shudu = new int[src.length()];
    for (int i = 0; i < shudu.length; i++) {
        shudu[i] = src.charAt(i) - '0';
    }
    return shudu;
}
}

3.将获得的假数据放入每个单元格中

	Paint.FontMetrics fm = numberPaint.getFontMetrics();
    float x = width/2;
    float y = height/2 - (fm.ascent + fm.descent) / 2;
    Number number = new Number();
    // 使用冒泡循环,i:横向坐标,j:竖向坐标
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            canvas.drawText(number.getTittleStr(i,j),i*width + x ,j*height + y,numberPaint);
        }
    }

数独游戏实战学习

4.根据单元格获得不可使用的数字(横竖当前九宫格)

public class Number {

private final  String str = "123000000000456000000000078900012346547897426465487893146548745678912300000001527";

private int[] shudu = new int[9*9];
// 用于存放已经不可用的数据 [X轴][Y轴][已经不可用的数据]
private int used[][][] = new int[9][9][];

public Number(){
    shudu = fromPuzzleString(str);
    checkAllUseTiles();
}

private int getTittle(int x,int y){
    return shudu[y*9 + x];
}

public String getTittleStr(int x,int y){
    int value = getTittle(x,y);
    if (value == 0){
        return "";
    }
    else {
        return String.valueOf(value);
    }
}

protected int[] fromPuzzleString(String src){
    int[] shudu = new int[src.length()];
    for (int i = 0; i < shudu.length; i++) {
        shudu[i] = src.charAt(i) - '0';
    }
    return shudu;
}

/*计算某一单元格中已经不可用的数据*/
public int[] checkUseTiles(int x,int y){
    int c[] = new int[9];

    for (int i = 0; i < 9; i++) {
        if (i == y){
            continue;
        }
        int t = getTittle(x,i);
        if (t != 0){
            c[t-1] = t;
        }
    }

    for (int i = 0; i < 9; i++) {
        if (i == x){
            continue;
        }
        int t = getTittle(i,y);
        if (t != 0){
            c[t-1] = t;
        }
    }

    int startX = (x/3)*3;
    int startY = (y/3)*3;
    for (int i = startX; i < startX + 3; i++) {
        for (int j = startY; j < startY + 3; j++) {
            if (i == x && j == y){
                continue;
            }
            int t = getTittle(i,j);
            if (t != 0){
                c[t-1] = t;
            }
        }
    }

    int nused = 0;
    for (int t : c){
        if (t != 0){
            nused += 1;
        }
    }
    int c1[] = new int[nused];
    nused = 0;
    for (int t : c){
        if (t != 0){
            c1[nused++] = t;
        }
    }
    return c1;
}

/*计算所有单元格中不可用数据*/
public void checkAllUseTiles(){
    for (int x = 0; x < 9; x++) {
        for (int y = 0; y < 9; y++) {
            used[x][y] = checkUseTiles(x,y);
        }
    }
}
// 取出某一单元格中不可用数据
public int[] getUsedTilesByCoor(int x,int y){
    return used[x][y];
}
}

4.获取点击事件同时获取不可用数据并打印(碰撞事件)

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() != MotionEvent.ACTION_DOWN){
        return super.onTouchEvent(event);
    }

    int selectedX = (int)(event.getX() / width);
    int selectedY = (int)(event.getY() / height);

    int used[] = number.getUsedTilesByCoor(selectedX,selectedY);
    for (int i = 0; i < used.length; i++) {
        System.out.println(used[i]);
    }
    return true;
}

4.设置弹窗提示已使用的数字有哪些(碰撞事件)

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() != MotionEvent.ACTION_DOWN){
        return super.onTouchEvent(event);
    }

    int selectedX = (int)(event.getX() / width);
    int selectedY = (int)(event.getY() / height);

    int used[] = number.getUsedTilesByCoor(selectedX,selectedY);
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < used.length; i++) {
        sb.append(used[i]);
    }

    LayoutInflater layoutInflater = LayoutInflater.from(this.getContext());
    View layoutView = layoutInflater.inflate(R.layout.dialog_number,null);
    TextView textView = (TextView) layoutView.findViewById(R.id.tv_number);
    textView.setText(sb.toString());
    AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
    builder.setView(layoutView);
    AlertDialog dialog = builder.create();
    dialog.show();
    return true;
}
剩下的都是原生的乱七八糟的东西,就不写了