IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 第一个android程序——数独 -> 正文阅读

[移动开发]第一个android程序——数独

最近学习java开发,就编写第一个android程序 数独。

一、先了解一下数独规则:

  1. 9行9列,共81个小方格

  2. 每个小方格只能填1-9个数字

  3. 每一行数字不能重复,每一列数字不能重复,每一个小的九宫格也不能重复

二、设计思路:

1. 先生成一个完整的数独,并保存在一个二维数组中
2. 随机把n个小方格的值清空,二维数组对应小方格对应的值填0
3. 画图,绘制一个9行9列(共81个小方格),并根据二维数组绘制文本,0值绘制文本为空字符串
4. 选中小方格时,如果原始就有数字,则不做任何操作;否则改变被选中的小方格背景色,
   可对该方格填写1-9个的任何个数字
6. 验证填写的数字,行、列、小九宫格是否重复;若不重复,绘制该文本,否则予以提示

三、升级步骤及关键代码

  1. 创建一个数独类 DrawShuduku,该类主要作用是生成数独且验证填写值是否正确

    声明一个二维数组,9行9列

    	private final int ROWS=9; //九宫格行数
    	private final int COLS=9; //九宫格列数
    
        private int[][] currentArray;
        private int[][] resultArray;
    

    采用回溯方法,给每个小方格随机填写1-9(每一小方格都尝试填写),最终输出一个完整的数独二维数组,这个是本次的核心代码。

    定义一个方法backTrackShuduku(int n),n从0开始,也就是第一行第一列(第一个小方格)

    每个小方格都会尝试填写1-9的数字(随机填写),每个小方格都尝试9次(foreach循环),如果验证该数字不合法,则把该数字剔除,继续执行foreach下一个,

    尝试填写其他数字,满足就填写该值 并 执行 backTrackShuduku(n+1),不满足就剔除该数字,以此类推填写后面的空格。

    注意:不管所填写的数字是否合法,都需要把该foreach执行完。

    n=81时,即所有空格都填满,则验证该数独合法性(数字是否有重复);如果是一个完整且合法的数独,则拷贝到另一个二维数组。

    因为,此时,递归函数还没有执行完,会继续尝试填写其他数字,因为每一个小方格都会填写1-9共九次

        /**
         * 采用回溯方法,给每个单元格尝试1-9填值
         * @param n 目前需要填写的第n个单元格
         */
        private void backTrackShuduku(int n){
            if(n==81){
                //如果都已经填满,则校验填充的值是否都正确
                for(int row=0;row<ROWS;row++){
                    for(int col=0;col<COLS;col++){
                        int value=currentArray[row][col];
                        if(value==0 || !isValid(row,col,value,currentArray)){
                            return;
                        }
                    }
                }
    
                resultArray=new int[ROWS][COLS];
                for (int row = 0; row < ROWS; row++) {
                    for (int col = 0; col < COLS; col++) {
                        resultArray[row][col] = currentArray[row][col];
                    }
                }
            }
    
            if (resultArray != null) {
                return; // 若已经找到,则后面递归直接结束
            }
    
            // 获取n空格在Y方向第几个
            int row = n / ROWS;
    
            // 获取n空格在X方向第几个
            int col = n % COLS;
    
            // 判断该单元格是否有填充值
            if (currentArray[row][col] > 0) {
                backTrackShuduku(n + 1);
                return; // 如果已经填充,则填充下一个单元格
            }
    
            // 如果该方格需要填充值,则从1-9随机赋值
            ArrayList<Integer> randomList = new ArrayList<Integer>();
            for (int i = 1; i <= ROWS; i++) {
                randomList.add(i);
            }
    
            for (int i = 0; i < ROWS; i++) {
                Random rand = new Random();
                int index = rand.nextInt(randomList.size());
                int value = randomList.get(index);
                currentArray[row][col] = value;
                randomList.remove(index);
    
                if (isValid(row, col, value, currentArray)) {
                    // 如果该值满足条件,则填充下一个单元格
                    backTrackShuduku(n + 1);
                }
            }
    
            // 如果9个数字都不满足,则清空该单元格的值,等待其他递归进来,继续填充
            // 注意每个单元格都会尝试填充1-9个数字,每个数字都会产生一个递归算法
            currentArray[row][col] = 0;
        }
    

    验证所填写的值是否合法,代码如下:

        /**
         *
         * @param row   当前第几行
         * @param col   当前第几列
         * @param value 填充的值(1-9)
         * @param array 验证的二维数组
         * @return 如果对应行和对应列、以及对应小区域9个方格,值不重复,返回true,否则返回false
         */
        public boolean isValid(int row, int col, int value, int[][] array) {
            // 不能跟该列的其他单元格重复
            for (int i = 0; i < COLS; i++) {
                if (i == row) {
                    continue;// 排除它自己
                }
    
                if (array[i][col] == value) {
                    return false;
                }
            }
    
            // 不能跟该行其他单元格值相同
            for (int i = 0; i < ROWS; i++) {
                if (i == col) {
                    continue;
                }
    
                if (array[row][i] == value) {
                    return false;
                }
            }
    
            // 跟小区域其他单元格值不能重复
            int x = (row / 3) * 3;
            int y = (col / 3) * 3;
            for (int i = x; i < x + 3; i++) {
                for (int j = y; j < y + 3; j++) {
                    if (i == row && j == col) {
                        continue;
                    }
    
                    if (array[i][j] == value) {
                        return false;
                    }
                }
            }
    
            return true;
        }
    

    生成后的二维数组,随机清空n个小方格的值

        /**
         * 获取一个完整的数独
         * @return
         */
        private int[][] getSudokuArray() {
            currentArray = new int[ROWS][COLS];
            resultArray = null;
            for (int i = 0; i < 3; i++) {
                // 避免回溯完都没有把所有单元格填完 则重新再次开始回溯 限制3次
                // 一般都可一次回溯就可以把空格填完
                backTrackShuduku(0);
                if (resultArray != null) {
                    return resultArray;
                }
            }
    
            return null;
        }
    
        /**
         * 生成一个完整的数独 并 随机清空n个单元格
         * @param spaceNum  空单元格个数
         * @return 随机生成一个数独
         */
        public int[][] setSudokuArray(int spaceNum) {
            int[][] result = getSudokuArray();
            if (result == null) {
                return null;
            }
    
            ArrayList<Integer> randomList = new ArrayList<Integer>();
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLS; col++) {
                    randomList.add(row * ROWS + col);
                }
            }
    
            Random rand = new Random();
            for (int i = 0; i < spaceNum; i++) {
                int index = rand.nextInt(randomList.size());
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int num = randomList.get(index);
                result[num / ROWS][num % COLS] = 0;
                randomList.remove(index);
            }
    
            return result;
        }
    
  2. 创建数独自定义控件 ShudukuView

    绘制9行9列,81个小方格,并绘制文本

        @Override
        protected void onDraw(Canvas canvas) {
            //绘制背景色
            Paint background_paint = new Paint();
            background_paint.setColor(getResources().getColor(R.color.shuduku_background, null));
            canvas.drawRect(0, 0, getWidth(), getHeight(), background_paint);
    
            drawLine(canvas);
            drawBackGround(canvas);
            drawString(canvas);
            super.onDraw(canvas);
        }
        
        private void drawLine(Canvas canvas) {
            for (int row = 0; row <= 9; row++) {
                Paint p = new Paint();
    
                // 绘制横线
                if (row % 3 == 0) {
                    // 每三行绘制一条粗线
                    p.setColor(Color.DKGRAY);
                } else {
                    p.setColor(Color.LTGRAY);
                }
    
                float y = row * this.height;
                canvas.drawLine(0, y, this.width * 9, y, p);
            }
    
            for (int col = 0; col <= 9; col++) {
                Paint p = new Paint();
    
                // 绘制竖线
                if (col % 3 == 0) {
                    // 每三行绘制一条粗线
                    p.setColor(Color.DKGRAY);
                } else {
                    p.setColor(Color.LTGRAY);
                }
    
                float x = col * this.width;
                canvas.drawLine(x, 0, x, this.height * 9, p);
    
            }
        }
    
        private void drawBackGround(Canvas canvas ) {
            for (int row = 0; row < 9; row++) {
                for (int col = 0; col < 9; col++) {
                    // 当前选中的单元格,改变背景色
                    if (orginalArray[row][col] == -1) {
                        float x = col * width + 1;
                        float y = row * height + 1;
                        Paint p=new Paint();
                        p.setColor( Color.rgb(255, 250, 205));
                        //p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
                        canvas.drawRect(x ,  y, x+width - 2, y+height - 2,p);
                    }
                }
            }
        }
    
        private void drawString(Canvas canvas) {
            Paint number_paint=new Paint();
            number_paint.setColor(Color.BLACK);
            //number_paint.setStyle(Paint.Style.STROKE);
            number_paint.setTextSize(height*0.75f);
            number_paint.setTextAlign(Paint.Align.CENTER);
    
            Paint.FontMetrics fm=number_paint.getFontMetrics();
            float x=width/2;
            float y=height/2-(fm.ascent+fm.descent)/2;
    
            for (int row = 0; row < 9; row++) {
                for (int col = 0; col < 9; col++) {
                    if (orginalArray[row][col] > 0) {
                        number_paint.setColor(Color.BLACK); // 如果原始生成的字体为黑色
                    } else {
                        number_paint.setColor(Color.GREEN); // 如果手动填充的字体为橘色
                    }
    
                    String text = currentArray[row][col] > 0 ? "" + currentArray[row][col] : "";
                    canvas.drawText(text, width*col+x, height*row+y, number_paint);
                }
            }
        }
    
  3. 效果图如下:
    在这里插入图片描述

  4. 源代码路径: (源代码) Shuduku.zip-Java文档类资源-CSDN下载

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:45:21  更:2021-07-11 16:45:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 5:43:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码