zoukankan      html  css  js  c++  java
  • 就业培训学习记录-day009

    课堂任务

    方法

    在前面使用的 System.out.println(),具体是什么呢?这句话的意思是调用系统类 System 中的标准输出对象 out 中的方法 println()。方法是语句的集合,它们在一起执行一个功能。

    • 方法是解决一类问题的步骤的有序组合
    • 方法包含于类或对象中
    • 方法在程序中被创建,在其他地方被引用

    方法的优点

    1. 使程序变得更简短而清晰。
    2. 有利于程序维护。
    3. 可以提高程序开发的效率。
    4. 提高了代码的重用性。

    方法的命名规则

    1. 方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。
    2. 下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test_,例如 testPop_emptyStack。

    方法的定义

    一般情况下,定义一个方法包含以下语法:

    修饰符 返回值类型 方法名(参数类型 参数名){
        ...
        方法体
        ...
        return 返回值;
    }
    

    方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

    • 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
    • 返回值类型:方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
    • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
    • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
    • 方法体:方法体包含具体的语句,定义该方法的功能。

    无参方法

    public class Run {
    	public static void main(String[] args) {
    		System.out.println("before say hello");
    		sayHello();
    		System.out.println("after say hello");
    	}
    
    	public static void sayHello() {
    		System.out.println("Hello");
    	}
    }
    

    运行结果如下,方法在被调用时,会先把方法内的流程执行完毕,然后再回到被调用处,接着运行后面的代码。

    有参方法

    public class Run {
    	public static void main(String[] args) {
    		System.out.println("before say something");
    		say("有参方法");
    		System.out.println("after say someting");
    	}
    
    	public static void say(String content) {
    		System.out.println(content);
    	}
    }
    

    也可以这样写:

    public class Run {
    	public static void main(String[] args) {
    		System.out.println("before say something");
    		String word = "有参方法"; // 先定义一个字符串,并赋值
    		say(word); // 将刚刚定义的字符串传到say方法中
    		System.out.println("after say someting");
    	}
    
    	public static void say(String content) {
    		System.out.println(content);
    	}
    }
    

    方法返回值

    public class Run {
    	public static void main(String[] args) {
    		int numA = 6, numB = 8, numC;
    		numC = add(numA, numB); // 用int型的numC来接受add方法的返回值
    		System.out.println("numC="+numC);
    	}
    
    	public static int add(int num1, int num2) { // 第一个int代表返回值的类型是int,当返回值类型是void时,表示没有返回值
    		return num1 + num2;
    	}
    }
    

    方法重载

    上面使用的add方法仅仅适用于int型数据。但如果你想得到两个浮点类型数据的和呢?解决方法是创建另一个有相同名字但参数不同的方法,如下面代码所示:

    public class Run {
    	public static void main(String[] args) {
    		int numA = 6, numB = 8, numC;
    		double numD = 3.14, numE = 6.78, numF;
    		numC = add(numA, numB); // 用int型的numC来接受add方法的返回值
    		System.out.println("numC="+numC);
    		numF = add(numD, numE); // 用double型的numF来接受add方法的返回值
    		System.out.println("numF="+numF);
    	}
    
    	public static int add(int num1, int num2) {
    		return num1 + num2;
    	}
    	public static double add(double num1, double num2) {
    		return num1 + num2;
    	}
    }
    

    如果调用add方法时传递的是int型参数,则int型参数的addd方法就会被调用;如果传递的是double型参数,则double类型的add方法体会被调用,这叫做方法重载;就是说一个类的两个方法拥有相同的名字,但是有不同的参数列表。Java编译器根据方法签名判断哪个方法应该被调用。方法重载可以让程序更清晰易读。执行密切相关任务的方法应该使用相同的名字。重载的方法必须拥有不同的参数列表。不能仅仅依据修饰符或者返回类型的不同来重载方法。

    数组

    Java 提供的数组是用来存储固定大小的同类型元素。声明一个数组变量,如 arr[5] 来代替直接声明 5 个独立变量 arr0,arr1,....,arr4。想要获取数组中的元素值,可以通过元素的下标来获取,数组的下标是从0开始的。

    arr[5] 33 21 18 42 86
    下标 0 1 2 3 4

    创建数组

    一般分为动态初始化和静态初始化。

    // 动态初始化,新建int数组,长度为5,int类型默认值为0
    int[] arr1 = new int[5];
    // 静态初始化1
    int[] arr2 = {1,2,3,4,5};
    // 静态初始化2
    int[] arr3 = new int[]{1,2,3,4,5};
    

    通过下标访问数组元素

    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		char[] ary = new char[5];
    		ary[0]='h'; // 通过下标访问数组元素
    		ary[1]='e';
    		ary[2]='l';
    		ary[3]='l';
    		ary[4]='o';
    		// 遍历数组
    		for (int i = 0; i < 5; i++) {
    			System.out.println("字符数组ary的第"+(i+1)+"个元素是"+ary[i]);
    		}
    		System.out.println(Arrays.toString(ary));
    	}
    }
    

    遍历数组

    • 数组的length属性是数组的长度
    • 数组一旦创建,长度不可变
    • 允许长度为0的数组
    public class Run {
    	public static void main(String[] args) {
    		int[] ary = {1,2,3,4,5};
    		// 遍历数组
    		for (int i = 0; i < ary.length; i++) {
    			System.out.println(ary[i]);
    		}
    	}
    }
    

    数组工具类Arrays

    Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法。使用时需要导包import java.util.Arrays;

    1. Arrays.toString(Object[] array)
      功能:返回数组的字符串形式
    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {1,3,5,7,9};
    		char[] arr2 = {'h','e','l','l','o'};
    		System.out.println(Arrays.toString(arr));
    		// 结果为:[1, 3, 5, 7, 9]
    		System.out.println(Arrays.toString(arr2));
    		// 结果为:[h, e, l, l, o]
    	}
    }
    
    1. Array.sort(Object[] array)
      功能:对数组按照升序排序
    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {10,3,25,-8,1};
    		System.out.println("排序前:"+Arrays.toString(arr));
    		// 排序前:[10, 3, 25, -8, 1]
    		Arrays.sort(arr);
    		System.out.println("排序后:"+Arrays.toString(arr));
    		// 排序后:[-8, 1, 3, 10, 25]
    	}
    }
    
    1. Arrays.copyOf(Object[] array, int to_index)
      返回一个数组,这个数组就等于数组 array 的前 to_index 个数,也就是 array[0] ~ array[to_index - 1] 。
    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {4,6,8,1,3};
    		int[] arr2 = Arrays.copyOf(arr, 3);
    		System.out.println(Arrays.toString(arr2)); // [4, 6, 8]
    	}
    }
    

    数组常见操作

    1. 生成随机数组(值的范围在[1,100],包含边界)
      Math.random() 方法用于返回一个随机数,随机数范围为 0.0 <= Math.random < 1.0。
    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int arrSize = 10; // 指定数组长度
    		int[] arr = getRandomArray(arrSize); // 用数组arr接收方法返回的数组
    		System.out.println(Arrays.toString(arr));
    	}
    
    	public static int[] getRandomArray(int size) {
    		int[] arr = new int[size]; // 将传入的参数指定为数组的长度
    		for (int i = 0; i < arr.length; i++) {
    			// Math.random()生成的随机数范围是[0.0,1.0),乘100再加1,然后取整数部分,即是[1,100]
    			arr[i] = (int) (Math.random() * 100) + 1;
    		}
    		return arr;
    	}
    }
    
    1. 数组求和
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {4,6,8,1,3};
    		System.out.println(getSum(arr)); // 21
    	}
    
    	public static int getSum(int[] arr) {
    		int res = -1;
    		for (int i = 0; i < arr.length; i++) {
    			res += arr[i];
    		}
    		return res;
    	}
    }
    
    1. 数组求最大、最小值
      方法1:一个个比较,然后取值
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {4,6,8,1,3};
    		System.out.println("数组最大值是"+getMax(arr)); // 8
    		System.out.println("数组最小值是"+getMin(arr)); // 1
    	}
    	
    	public static int getMax(int[] arr) {
    		int max = arr[0]; // 最大值初始化为数组第一个元素
    		for (int i = 0; i < arr.length; i++) {
    			if (arr[i] > max) {
    				// 如果某个元素比max还大,那么该元素就是新的最大值
    				max = arr[i];
    			}
    		}
    		return max;
    	}
    	
    	public static int getMin(int[] arr) {
    		int min = arr[0]; // 最小值初始化为数组第一个元素
    		for (int i = 0; i < arr.length; i++) {
    			if (arr[i] < min) {
    				// 如果某个元素比min还小,那么该元素就是新的最小值
    				min = arr[i];
    			}
    		}
    		return min;
    	}
    }
    

    方法2:先排序,然后取值

    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {4,6,8,1,3};
    		Arrays.sort(arr);
    		System.out.println("数组最大值是"+arr[arr.length-1]); // 8
    		System.out.println("数组最小值是"+arr[0]); // 1
    	}
    }
    
    1. 数组求平均值
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {4,6,8,1,3};
    		double avg = getSum(arr) / arr.length; // 21 ÷ 5 = 4.0
    		double avg1 = getSum(arr) * 1.0 / arr.length; // 21.0 ÷ 5 = 4.2
    		System.out.println("数组平均值是"+avg1); // 4.2
    	}
    	
    	public static int getSum(int[] arr) {
    		int res = -1;
    		for (int i = 0; i < arr.length; i++) {
    			res += arr[i];
    		}
    		return res;
    	}
    }
    
    1. 数组去重
      去除数组中的重复元素,例如:数组 [0,1,1,2,2,3,3,4,4,0] 去重后数组变为 [0,1,2,3,4] 。
    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {0, 1, 1, 2, 2, 3, 3, 4, 4, 0};
    		arr = unique(arr);
    		System.out.println(Arrays.toString(arr));
    	}
    
    	public static int[] unique(int[] arr) {
    		// 最好的情况是,所有的元素都不重复,新数组(要返回的数组)与原数组长度相同
    		int[] temp = new int[arr.length];
    		// 默认第一个元素不重复
    		temp[0] = arr[0];
    		// 记录不重复数据的个数
    		int count = 1;
    		// 遍历原数组中的每一项,在此基础上用遍历的第i项去遍历新数组
    		for (int i = 0; i < arr.length; i++) {
    			// 标记,表示是否在新数组中找到重复的元素
    			boolean flag = false;
    			for (int j = 0; j < temp.length; j++) {
    				if (arr[i] == temp[j]) {
    					// 如果元素重复,则更改标记
    					flag = true;
    					break;
    				}
    			}
    			// 如果没有元素重复,则往新数组中添加
    			if (!flag) {
    				temp[count++] = arr[i];
    			}
    		}
    		// 如果不重复数据的个数与原数组长度不同,即原数组中存在重复元素,则缩短新数组的长度
    		if (count != arr.length) {
    			temp = Arrays.copyOf(temp, count);
    		}
    		return temp;
    	}
    }
    
    1. 删除数组中第n个元素
      例如数组{1,2,3,4,5},删除位置为2的元素后,数组变为{1,2,4,5}
    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {1, 2, 3, 4, 5};
    		arr = remove(arr, 2);
    		System.out.println(Arrays.toString(arr));
    	}
    
    	public static int[] remove(int[] arr, int index) {
    		// 如果index范围非法,则返回原数组
    		if (index < 0 || index > arr.length) {
    			return arr;
    		}
    		// 创建一个数组,长度为原数组长度-1
    		int[] temp = new int[arr.length - 1];
    		// 选择性复制元素到新数组中
    		for (int i = 0; i < arr.length - 1; i++) {
    			if (i < index) {
    				temp[i] = arr[i];
    			} else {
    				temp[i] = arr[i + 1];
    			}
    		}
    		return temp;
    	}
    }
    
    1. 往数组中第n个位置新增元素
      例如数组{1,2,3,4,5},往位置2添加666,数组变为{1,2,666,4,5}
    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {1, 2, 3, 4, 5};
    		arr = add(arr, 2, 666);
    		System.out.println(Arrays.toString(arr));
    	}
    
    	public static int[] add(int[] arr, int index, int element) {
    		// 如果index范围非法,则返回原数组
    		if (index < 0 || index > arr.length) {
    			return arr;
    		}
    		// 创建一个数组,长度为原数组长度+1
    		int[] temp = new int[arr.length + 1];
    		// 选择性复制元素到新数组中
    		for (int i = 0; i < arr.length + 1; i++) {
    			if (i < index) {
    				temp[i] = arr[i];
    			} else if (i == index) {
    				temp[i] = element;
    			} else {
    				temp[i] = arr[i - 1];
    			}
    		}
    		return temp;
    	}
    }
    

    递归

    递归指的是在函数的定义中使用函数自身的方法。

    举个例子:
    从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是:“从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是:‘从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是:……’”
     
    再举个例子:
    假设你在一个电影院,你想知道自己坐在哪一排,但是前面人很多,你懒得去数了。于是你问前一排的人「你坐在哪一排?」,这样前面的人 (代号 A) 回答你以后,你就知道自己在哪一排了,只要把 A 的答案加一,就是自己所在的排了。不料 A 和你一样懒,他也不想数,于是他也问他前面的人 B「你坐在哪一排?」,这样 A 可以用和你一模一样的步骤知道自己所在的排。然后 B 也如法炮制,直到他们这一串人问到了最前面的一排(或者说问到了知道自己是哪一排的人,预示着调用结束),第一排的人告诉问问题的人「我在第一排」,最后大家就都知道自己在哪一排了。

    递归的条件

    可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式(自身调用)。存在一种情况,可以使递归在该情况下退出(递归出口)。

    递归三要素

    • 一定有可以退出程序的情况(不能无限递归)
    • 总是在尝试将一个问题化简到更小的规模
    • 父问题与子问题不能有依赖的部分

    1. 阶乘问题
      计算 n 的阶乘,n < 0时返回-1。
    public class Run {
    	public static void main(String[] args) {
    		int n = 4; // 计算n的阶乘,这里设置为4
    		System.out.println(fx(n)); // 4!=4×3×2×1=24
    	}
    
    	public static int fx(int n) {
    		if (n < 0) {
    			// 递归边界
    			return -1;
    		} else if (n == 0) {
    			// 递归边界
    			return 1;
    		} else {
    			// 递归,函数自己调用自己
    			return n * fx(n-1);
    		}
    	}
    }
    
    1. 斐波那契数列
      计算斐波那契数列第n项的结果。

    斐波那契数列的递推公式为:
    F(0) = F(1) = 1        0<=n<=1
    F(n) = F(n-1) + F(n-2)        n>=2

    public class Run {
    	public static void main(String[] args) {
    		int n = 4;
    		System.out.println(Fibonacci(n)); // 5
    	}
    
    	public static int Fibonacci(int n) {
    		if (n < 0) {
    			// 递归边界
    			return -1;
    		} else if (n == 0 || n == 1) {
    			// 递归边界
    			return 1;
    		} else {
    			// 递推公式
    			return Fibonacci(n-1) + Fibonacci(n-2);
    		}
    	}
    }
    

    排序

    参考十大经典排序算法(动图演示)

    使用Arrays.sort()

    import java.util.Arrays;
    public class Run {
    	public static void main(String[] args) {
    		int[] arr = {34,53,12,232,1,20,10,-6,-8,32};
    		System.out.println("排序前:"+Arrays.toString(arr));
    		// 排序前:[34, 53, 12, 232, 1, 20, 10, -6, -8, 32]
    		Arrays.sort(arr);
    		System.out.println("排序后:"+Arrays.toString(arr));
    		// 排序后:[-8, -6, 1, 10, 12, 20, 32, 34, 53, 232]
    	}
    }
    

    冒泡排序

    冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

    算法描述

    1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
    3. 针对所有的元素重复以上的步骤,除了最后一个;
    4. 重复步骤1~3,直到排序完成。

    动图演示

    代码实现

    public static int[] bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                // 相邻元素两两对比
                if (arr[j] > arr[j+1]) {
                    // 元素交换
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        return arr;
    }
    

    选择排序

    选择排序(Selection Sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

    算法描述
    n 个记录的直接选择排序可经过 n-1 趟直接选择排序得到有序结果。具体算法描述如下:

    1. 初始状态:无序区为 R[1..n] ,有序区为空;
    2. 第 i 趟排序 (i=1,2,3…n-1) 开始时,当前有序区和无序区分别为 R[1..i-1] 和 R(i..n)。该趟排序从当前无序区中,选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使 R[1..i] 和 R[i+1..n) 分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
    3. n-1 趟结束,数组有序化了。

    动图演示

    代码实现

    public static int[] selectionSort(int[] arr) {
        int minIndex, temp;
        for (int i = 0; i < arr.length - 1; i++) {
            minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                // 寻找最小的数
                if (arr[j] < arr[minIndex]) {
                    // 将最小数的索引保存
                    minIndex = j;
                }
            }
            // 元素交换
            temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
        return arr;
    }
    

    算法分析
    表现最稳定的排序算法之一,因为无论什么数据进去都是O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

    插入排序

    插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

    算法描述
    一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:

    1. 从第一个元素开始,该元素可以认为已经被排序;
    2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;
    3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;
    4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
    5. 将新元素插入到该位置后;
    6. 重复步骤2~5。

    动图演示

    代码实现

    public static int[] insertionSort(int[] arr) {
    	// current代表当前(待排序)项的值,preIndex代表在当前项之前的某个下标
    	int current, preIndex;
    	for (int i = 1; i < arr.length; i++) {
    		// 循环开始时,默认第0项是已经排好的,需要排的是第1项,所以i初值为1
    		preIndex = i - 1;
    		current = arr[i];
    		// 当前项的前一项大于当前项时,交换这两项的位置
    		while (preIndex >= 0 && arr[preIndex] > current) {
    			arr[preIndex + 1] = arr[preIndex];
    			preIndex--;
    		}
    		// 交换完毕或者没交换,代表当前项之前都是有序的,即将插入的值不会破坏序列
    		arr[preIndex + 1] = current;
    	}
    	return arr;
    }
    

    算法分析
    插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

    快速排序

    参考快速排序

    查找

    顺序查找

    顺序查找适合于存储结构为顺序存储或链接存储的线性表。顺序查找的时间复杂度为O(n)。

    基本思想
    顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值 key 相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于 key 的结点,表示查找失败。

    代码实现

    public static int sequenceSearch(int[] arr, int key) {
    	for (int i = 0; i < arr.length; i++) {
    		// 如果找到,则返回所在下标
    		if (arr[i] == key) {
    			return i;
    		}
    	}
    	// 如果没找到,则返回-1
    	return -1;
    }
    

    二分查找

    参考算法——二分法查找(binarySearch)
    二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法,时间复杂度O(logn)。

    算法描述
    二分法查找的思路如下:

    1. 首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
    2. 如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤 1 的操作。
    3. 如果某一步数组为空,则表示找不到目标元素。

    代码实现

    public static int binarySearch(int[] arr, int key, int low, int high) {
    	// 中间值
    	int mid = (low + high) / 2;
    	if (key == arr[mid]) {
    		// 如果刚好在中间位置,则返回所在下标
    		return mid;
    	}
    	if (key < arr[mid]) {
    		// 如果大于,则key只可能在后半部分,递归调用
    		return binarySearch(arr, key, low, mid - 1);
    	} 
    	if (key > arr[mid]) {
    		// 如果大于,则key只可能在后半部分,递归调用
    		return binarySearch(arr, key, mid + 1, high);
    	}
    	// 如果没找到,则返回-1
    	return -1;
    }
    

    课后任务

    编码实现一个猜字符的游戏

    要求如下:

    1. 系统预先生成好一组(5个)不重复的小写英文字符,游戏开始,初始分值100分
    2. 用户输入自己猜测的字符数据(不考虑非法输入,如数字、特殊字符等)
    3. 系统根据用户的输入给出提示:位置对的个数以及字符对的个数
    4. 如果第3步中,用户输入完全正确(位置和字符),则游戏结束,系统给出猜测的次数和得分。如果没有完全正确,得分每次-5分,重复第2步

    效果展示

    import java.util.Arrays;
    import java.util.Scanner;
    
    public class GuessingCharacters {
    	public static void main(String[] args) {
    		// 设置大小
    		int i, j, size = 5;
    		char[] characters = new char[size];
    		characters = generateCharacters(size);
    		// 显示生成的字符
    		System.out.println(Arrays.toString(characters));
    		
    		boolean win = false;
    		int score = 100, guessTimes = 0, correctPosition, correctCharacters;
    		// 记录用户输入的数组
    		char[] guess = new char[size];
    		Scanner scan = new Scanner(System.in);
    		
    		while (!win) {
    			correctPosition = 0;
    			correctCharacters = 0;
    			System.out.println("请输入" + size + "个字符(a~z):");
    			// 接收输入并去重
    			guess = scan.nextLine().toCharArray();
    			guess = unique(guess);
    			// 更新猜的次数
    			guessTimes++;
    			
    			// 遍历生成的数组,判断位置和字符是否正确
    			for (i = 0; i < characters.length; i++) {
    				// 如果完全正确,则直接退出循环
    				if (Arrays.toString(characters).equals(Arrays.toString(guess))) {
    					correctPosition = characters.length;
    					correctCharacters = characters.length;
    					win = true;
    					break;
    				}
    				// 遍历输入的数组
    				for (j = 0; j < guess.length; j++) {
    					// 如果字符相同,则字符正确数自增
    					if (characters[i] == guess[j]) {
    						// 字符相同并且位置相同,则位置正确数自增
    						if (i == j) {
    							correctPosition++;
    						}
    						correctCharacters++;
    					}
    				}
    
    			}
    			if (!win) {
    				// 没完全猜对,更新得分并给出相应提示
    				score -= 5;
    				System.out.println("字符对:" + correctCharacters + "个,位置对:" + correctPosition + "个");
    			}
    		}
    		// 关闭流并且显示得分
    		scan.close();
    		System.out.println("猜对了,猜了" + guessTimes + "次,得分:" + score);
    	}
    
    	/**
    	 * 随机生成size大小的不重复小写字符数组,size的合理范围为[1,26]
    	 * @param size
    	 * @return char[] 
    	 */
    	public static char[] generateCharacters(int size) {
    		if (size < 0 || size > 26) {
    			return null;
    		}
    		char[] characters = new char[size];
    		int i, random, counts = 0;
    		char a = 'a', newChar;
    		
    		while (counts != size) {
    			// 生成[0,100)的整数
    			random = (int) (Math.random() * 100);
    			// 小写字母有26个,生成的数大于26就会出错,所以大于26时取余 但是这样会导致生成每个字母的概率不是平等的
    			if (random >= 26) {
    				random %= 26;
    			}
    			newChar = (char) (a + random);
    			// 遍历生成的字符,确保生成的字符不重复
    			for (i = 0; i < counts; i++) {
    				if (characters[i] == newChar) {
    					break;
    				}
    			}
    			// 如果循环顺利结束,即没有重复字符时,i=counts
    			if (i == counts) {
    				characters[counts++] = newChar;
    			}
    		}
    		return characters;
    	}
    
    	/**
    	 * 字符数组去重
    	 * @param arr
    	 * @return char[]
    	 */
    	public static char[] unique(char[] arr) {
    		// 最好的情况是,所有的元素都不重复,新数组(要返回的数组)与原数组长度相同
    		char[] temp = new char[arr.length];
    		// 默认第一个元素不重复
    		temp[0] = arr[0];
    		// 记录不重复数据的个数
    		int count = 1;
    		
    		// 遍历原数组中的每一项,在此基础上用遍历的第i项去遍历新数组
    		for (int i = 0; i < arr.length; i++) {
    			// 标记,表示是否在新数组中找到重复的元素
    			boolean flag = false;
    			for (int j = 0; j < temp.length; j++) {
    				if (arr[i] == temp[j]) {
    					// 如果元素重复,则更改标记
    					flag = true;
    					break;
    				}
    			}
    			// 如果没有元素重复,则往新数组中添加
    			if (!flag) {
    				temp[count++] = arr[i];
    			}
    		}
    		// 如果不重复数据的个数与原数组长度不同,即原数组中存在重复元素,则缩短新数组的长度
    		if (count != arr.length) {
    			temp = Arrays.copyOf(temp, count);
    		}
    		return temp;
    	}
    }
    
  • 相关阅读:
    遍历指定目录及其子目录下所有文件
    vim 配置
    解决 Mendeley Linux 中文输入问题
    全角半角字符对照表
    chrome 替换多线程下载管理器
    查看系统日志
    中大东校区iNode For linux 配置笔记
    anaconda 虚拟环境笔记
    linux 网络操作
    deepin 装机
  • 原文地址:https://www.cnblogs.com/ast935478677/p/14859546.html
Copyright © 2011-2022 走看看