写在前面:
每一个不曾起舞的日子,都是对生命的辜负。
希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己。
以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力有限,哪里写的不够清楚、明白,还请各位不吝指正,欢迎交流与讨论。如果有朋友因此了解了一些知识或对Java有了更深层次的理解,从而进行更进一步的学习,那么这篇文章的意义也就达到了。
目录
专题课(编程案例)
涉及到的知识点
⚫ 变量、数组
⚫ 运算符:基本运算符、关系运算符、逻辑运算符…
⚫ 程序流程控制:if、switch;for、while;死循环、循环嵌套
⚫ 跳转关键字:break、continue、return。
⚫ 方法
⚫ …
案例一:买飞机票
需求:机票价格按照淡季旺季、头等舱和经济舱收费、输入机票原价、月份和头等舱或经济舱。
按照如下规则计算机票价格:旺季(5-10月)头等舱9折,经济舱8.5折,淡季(11月到来年4月)头等舱7折,经济舱6.5折。
分析:
①定义一个方法可以进行键盘录入机票原价、月份和机舱类型。
②使用if判断月份是是旺季还是淡季,使用switch分支判断是头等舱还是经济舱。
③选择对应的折扣进行计算并返回计算的结果。
示例代码如下:
public static void main(String[] args) {
// 接收用户输入数据:飞机票原价、仓位类别、月份
Scanner sc = new Scanner(System.in);
System.out.println("请输入月份(1-12):");
int month = sc.nextInt();
System.out.println("请输入舱位类型(头等舱、经济舱):");
String planeType = sc.next();
System.out.println("请输入机票价格:");
double ticketPrice = sc.nextDouble();
// 4.调用方法,统计结果
double ticketMoney = planeTicket(ticketPrice, month, planeType);
System.out.println("机票优惠后的价格是:" + ticketMoney);
}
/**
* create by: 全聚德在逃烤鸭、
* description: 统计优惠后的飞机票价格
* create time: 2022/3/31 0031 10:29
*
* @param ticketPrice
* @param month
* @param planeType
* @return double
*/
// 2.定义方法接收信息,统计优惠后的价格返回
public static double planeTicket(double ticketPrice, int month, String planeType) {
// 3.判断用户选择的信息情况
if (month >= 5 & month <= 10) {
// 旺季
switch (planeType) {
case "头等舱":
ticketPrice *= 0.9; // ticketPrice = ticketPrice * 0.9;
break;
case "经济舱":
ticketPrice *= 0.85;
break;
default:
System.out.println("输入的舱位类型有误!");
ticketPrice = -1; // 表示当前无法计算价格
}
} else if ((month >= 1 & month <= 12) & (month >= 11 | month <= 4)) {
// 淡季
switch (planeType) {
case "头等舱":
ticketPrice *= 0.7; // ticketPrice = ticketPrice * 0.9;
break;
case "经济舱":
ticketPrice *= 0.65;
break;
default:
System.out.println("输入的舱位类型有误!");
ticketPrice = -1; // 表示当前无法计算价格
}
} else {
System.out.println("输入月份有误!");
ticketPrice = -1;
}
return ticketPrice; // 最终价格
案例二:找素数
需求:判断101-200之间有多少个素数,并输出所有素数。
说明:如果除了1和它本身之外,不能被其他正整数整除的数,就叫素数。
分析:
101-200之间的数据可以采用循环依次拿到;每拿到一个数,判断该数是否是素数。
判断规则是:从2开始遍历到该数的一半的数据,看是否有数据可以整除它,有则不是素数,没有则是素数。
示例代码如下:
public static void main(String[] args) {
int startNumber = 101;
int finishNumber = 200;
System.out.println(startNumber + "至" + finishNumber + "中的素数为");
int number = getPrimeNumber(startNumber, finishNumber);
System.out.println("共" + number + "个");
}
/**
* create by: 全聚德在逃烤鸭、
* description: 给定边界值,找出并打印位于两个边界值之间的所有素数
* create time: 2022/3/31 0031 11:30
*
* @param startNumber
* @param FinishNumber
* @return int
*/
public static int getPrimeNumber(int startNumber, int FinishNumber) {
int number = 0; // 记录素数个数
// 1.定义一个循环,找出startNumber至FinishNumber之间的全部数据
for (int i = startNumber; i <= FinishNumber; i++) {
// 信号位:标记当前数据是否为素数
boolean isPrime = true; // 默认是素数
// 3.判断当前遍历的数据是否是素数
for (int j = 2; j <= i / 2; j++) {
if (i % j == 0) {
isPrime = false;
break;
}
}
// 3.根据判断结果选择是否打印该数据,若是素数则打印
if (isPrime) {
System.out.print(i + "\t"); // 打印该素数
number++; // 每找到一个素数,素数总数目+1
}
}
return number;
}
案例三:开发验证码
需求:定义方法实现随机产生一个5位的验证码,每位可能是数字、大写字母、小写字母。
分析:
①定义一个方法,生成验证码返回:方法参数是位数、方法的返回值类型是String。
②在方法内部使用for循环生成指定位数的随机字符,并连接起来。
③把连接好的随机字符作为一组验证码进行返回。
示例代码如下:
public static void main(String[] args) {
int n = 5;
// 4.调用获取验证码的方法,得到一个随机的验证码
String code = creatCode(n);
System.out.println("随机的" + n + "位验证码为:" + code);
}
/**
* create by: 全聚德在逃烤鸭、
* description: 随机产生指定位数的验证码并返回
* create time: 2022/3/31 0031 15:32
*
* @param n
* @return java.lang.String
*/
// 1.定义方法实现随机产生验证码,每位可能是数字、大写字母、小写字母,并将产生的验证码返回
public static String creatCode(int n) {
// 3.定义一个字符串变量用于记录生成的随机字符
String code = ""; // 初始值为空
Random r = new Random();
// 2.定义一个for循环,循环n次,依次生成随机字符
for (int i = 0; i < n; i++) {
// 具体是生成数字、大写字母还是小写字母,是随机的
int type = r.nextInt(3); // 0:生成数字 1:生成大写字母 2:生成小写字母
switch (type) {
// 数字
case 0:
int number = r.nextInt(10); // (0-9)
code += number; // 将数字累加进验证码
break;
// 大写字母
case 1:
char upperCase = (char) (r.nextInt(26) + 65); // 大写字母在ASCⅡ码中对应数字(A:65至Z:90),需要由int型强转为char型
code += upperCase; // 将大写字母累加进验证码
break;
// 小写字母
case 2:
char lowerCase = (char) (r.nextInt(26) + 97); // 大写字母在ASCⅡ码中对应数字(a:97至Z:122),需要由int型强转为char型
code += lowerCase; // 将小写字母累加进验证码
break;
}
}
return code; // 将最终生成的验证码返回
}
案例四:数组元素的复制
需求:把一个数组中的元素复制到另一个新数组中去。
分析:
①需要动态初始化一个数组,长度与原数组一样。
②遍历原数组的每个元素,依次赋值给新数组。
③输出两个数组的内容。
示例代码如下:
public static void main(String[] args) {
int[] arr1 = {10, 20, 30};
// int[] arr2 = arr1; // 只是把arr1中存储的数组对象的地址赋值给arr2存储,本质上还是同一个数组,不是数组复制
int[] arr2 = new int[arr1.length];
copyArray(arr1, arr2); // 调用复制数组的方法,完成数组复制
// 调用打印数组数组内容的方法,查看两个数组内容是否一致
printArray(arr1);
printArray(arr2);
}
/**
* create by: 全聚德在逃烤鸭、
* description: 把一个数组中的元素复制到另一个数组中去
* create time: 2022/3/31 0031 16:04
*
* @param arr1
* @param arr2
* @return void
*/
public static void copyArray(int[] arr1, int[] arr2) {
// 完成数组复制
for (int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
}
/**
* create by: 全聚德在逃烤鸭、
* description: 遍历并打印数组中的每一个元素值
* create time: 2022/3/31 0031 16:07
*
* @param arr
* @return void
*/
public static void printArray(int[] arr) {
System.out.print("[");
// 遍历数组中的每一个元素值,并将其打印出来
for (int i = 0; i < arr.length; i++) {
// 查看是否为最后一位索引,若是,则不打印制表符
System.out.print(i == arr.length - 1 ? arr[i] : arr[i] + "\t");
}
System.out.println("]");
}
注:
int[] arr1 = {10, 20, 30};
int[] arr2 = arr1; // 只是把arr1中存储的数组对象的地址赋值给arr2存储,本质上还是同一个数组,不是数组复制
案例五:评委打分
需求:在唱歌比赛中,有6名评委给选手打分,分数范围是[0-100]之间的整数。选手的最后得分为:去掉最高分、最低分后的4个评委的平均分,请完成上述过程并计算出选手的得分。
分析:
①把6个评委的分数录入到程序中去 --->使用数组
②遍历数组中每个数据,进行累加求和,并找出最高分、最低分。
③按照分数的计算规则算出平均分。
示例代码如下:
public static void main(String[] args) {
// 定义一个动态初始化数组,用于后期录入6个评委的分数
int[] scores = new int[6];
// 录入评委的分数
Scanner sc = new Scanner(System.in);
for (int i = 0; i < scores.length; i++) {
System.out.println("请输入第" + (i + 1) + "评委的成绩");
// 把分数存入数组的对应索引位置
scores[i] = sc.nextInt();
}
System.out.println("平均分为" + getAverageScore(scores)); // 调用求平均分的方法并将结果打印出来
}
/**
* create by: 全聚德在逃烤鸭、
* description: 求一组数据中去掉最高分、最低分后的平均分,分数范围是[0-100]之间的整数
* create time: 2022/3/31 0031 18:33
*
* @param scores
* @return double
*/
public static double getAverageScore(int[] scores) {
// 判断数组内是否有数据,若没有则给出提示,并返回值-1
if (scores == null | scores.length == 0) {
System.out.println("成绩输入有误!");
return -1; // 代表数据有误
}
int totalScore = 0; // 定义变量,存储总分数,初始值为0
int max = scores[0]; // 默认第1个索引的元素值为最大值
int min = scores[0]; // 默认第1个索引的元素值为最小值
// 遍历数组中的每个元素值,找出最大值和最小值,求出总分
for (int i = 0; i < scores.length; i++) { // 涉及到求总分问题,所以必须从第0个索引位置开始
// 判断每个元素的数据值是否在0-100范围内,若超出范围则给出提示,并返回值-1
if (scores[i] < 0 | scores[i] > 100) {
System.out.println("成绩输入超出范围0-100!");
return -1;
}
// 若当前索引位置的元素值大于最大值,则将该元素值设为最大值
if (scores[i] > max) {
max = scores[i];
}
// 若当前索引位置的元素值小于最小值,则将该元素值设为最小值
if (scores[i] < min) {
min = scores[i];
}
totalScore += scores[i]; // 累加各个元素的数据值
}
// 去掉一个最高分,去掉一个最低分,求平均分
double averageScore = (totalScore - max - min) * 1.0 / (scores.length - 2); // 一定要*1.0,使int型自动转换为double型,否则在计算中出现小数时会发生小数丢失
return averageScore; // 将最终求得的平均分返回
}
注:
求解平均分时一定要在计算前*1.0,使int型自动转换为double型,否则在计算中出现小数时会发生小数丢失。
案例六:数字加密
需求:某系统的数字密码,采用加密方式进行传输,规则如下:先得到每位数,然后每位数都加上5,再对10求余,最后将所有数字反转,得到一串新数。
如1983,加密过程如下图所示。
分析:
①将每位数据存入到数组中去,遍历数组每位数据,按照规则进行更改,把更改后的数据从新存入到数组中。
②将数组的前后元素进行交换,数组中的最终元素就是加密后的结果。
示例代码如下:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 1.定义一个数组存储需要加密的数据
System.out.println("请输入需要加密的数字位数:");
int length = sc.nextInt(); // 手动输入加密数字的位数,可以动态加密不同长度的数字
int[] arr = new int[length];
// 2.录入需要加密的数字
for (int i = 0; i < arr.length; i++) {
System.out.println("请输入第" + (i + 1) + "位数字:");
int number = sc.nextInt();
arr[i] = number;
}
// 3.调用打印数组内容的方法,查看原数字
System.out.println("加密前");
printArray(arr);
// 4.调用对数组中的数据进行加密的方法(核心逻辑)
arr = digitalEncryption(arr);
// 5.调用打印数组内容的方法,查看加密后的数字
System.out.println("加密后");
printArray(arr);
}
/**
* create by: 全聚德在逃烤鸭、
* description: 打印数组内容
* create time: 2022/4/1 0001 9:25
*
* @param arr
* @return void
*/
public static void printArray(int[] arr) {
if (arr == null | arr.length == 0) {
System.out.println("数组为空!");
} else {
System.out.print("数组内容为:[");
for (int i = 0; i < arr.length; i++) {
System.out.print(i == arr.length - 1 ? arr[i] : arr[i] + ",");
}
System.out.println("]");
}
}
/**
* create by: 全聚德在逃烤鸭、
* description: 将数组中的数据顺序颠倒
* create time: 2022/4/1 0001 10:15
*
* @param arr
* @return int[]
*/
public static int[] digitalEncryption(int[] arr) {
if (arr == null | arr.length == 0) {
System.out.println("数组为空!");
} else {
// 执行每位数+5,%10
for (int i = 0; i < arr.length; i++) {
arr[i] = (arr[i] + 5) % 10;
}
int temp = 0;
// 执行数组内容顺序翻转
/* 完成数据顺序翻转的原理:①定义2个变量分别占数组的首尾位置
②一个变量往前走,一个变量往后走,同步交换双方位置处的值。*/
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
return arr;
}
完成数据顺序翻转的原理:
①定义2个变量分别占数组的首尾位置。
②一个变量往前走,一个变量往后走,同步交换双方位置处的值。
案例七:模拟双色球
需求:从红色球号码中选择6个号码,从蓝色球号码中选择1个号码,组合为一注投注号码,红色球号码从1—33中选择;蓝色球号码从1—16中选择。
中奖条件与奖金表如下图所示。
业务流程分析:
1.随机一组号码并返回,代表双色球中奖号码
2.用户输入一组号码并返回,代表用户选择的双色球号码
3.比对这两组号码,判断用户的中奖情况。
1.随机一组中奖号码分析:
①中奖号码由6个红球和1个蓝球组成(注意:6个红球要求不能重复)。
②定义方法用于返回一组中奖号码(7个数据),返回的形式是一个整型数组。
核心逻辑:如何去保证随机的6个中奖的红球号码不重复的
①每次随机一个红球号码后去数组中判断是否存在。
②存在需要重新随机一个数字直到不重复为止。
2.用户输入一组号码分析:
①定义一个方法,该方法可以录入用户输入的6个红球和1个篮球号码
②该方法最终需要返回一个数组,数组中就是用户录入的号码(7位)。
核心逻辑:如何去保证7个用户选择的号码不重复且符合范围
①每次选择后,判断该数字是否超出范围以及是否重复
②若超出范围或者数据重复,则要求用户重新输入一个数字直到符合范围且不重复为止。
3.中奖情况判断的分析:
①定义一个方法,可以接收中奖号码的数组,用户选号的数组。
②根据命中红球数和篮球数判断最终的中奖情况并输出详情和中奖金额。
核心逻辑:如何去统计红球的命中数量
①遍历用户的每个选号,然后遍历中奖号码的数组。
②看当前选号是否在中奖号码中存在,存在则命中数量加1。
示例代码如下:
public static void main(String[] args) {
// 1.调用随机生成中奖号码的方法,返回一个数组变量
int[] luckyNumbers = creatLuckyNumber();
// printArray(luckyNumbers);
// 2.调用用户选号的方法让用户输入7个号码,返回一个数组变量
int[] userInputNumbers = userInputNumbers();
// printArray(userInputNumbers);
// 3.调用判断中奖情况的方法,输出中奖情况详情
judgeWinning(luckyNumbers, userInputNumbers);
}
/**
* create by: 全聚德在逃烤鸭、
* description: 打印数组内容
* create time: 2022/4/1 0001 15:48
*
* @param arr
* @return void
*/
public static void printArray(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(i == arr.length - 1 ? arr[i] : arr[i] + ",");
}
System.out.println("]");
}
/**
* create by: 全聚德在逃烤鸭、
* description:生成随机一组中奖号码 随机6个红球号码(1-33,且不能重复),随机1个蓝球号码(1-16),将数据存储到数组中
* create time: 2022/4/1 0001 14:48
*
* @param
* @return int[]
*/
public static int[] creatLuckyNumber() {
Random r = new Random();
// 定义一个动态初始化数组,存储7个数字
int[] numbers = new int[7];
// 遍历数组,为每个位置生成对应号码
for (int i = 0; i < numbers.length - 1; i++) {// 遍历前6个位置,生成不重复的6个随机的红球号码,范围为1-33
OUT:
// OUT标签,标记循环
// 定义死循环,当生成的第i个号码是之前生成过的重复号码时,重新生成
while (true) {
int random = r.nextInt(33) + 1; // 随机生成第i个红球号码
// 遍历第i个红球号码之前的所有号码,判断是否重复,若重复,则重新生成
for (int j = 0; j < i; j++) {
if (random == numbers[j]) {
continue OUT; // 号码重复,跳出当次循环,跳转到被OUT标签标记的while循环处,重新生成随机数,重新判断
}
}
numbers[i] = random; // 遍历完成i之前所有的数字,没有重复,则将该数据赋值给第i个红球
break; // 第i个红球号码赋值完毕,结束当前while循环,进行下一次for循环,为下一个红球号码赋值
}
}
int length = numbers.length;
numbers[length - 1] = r.nextInt(16) + 1; // 生成随机的第7个蓝球号码,范围为1-16
return numbers; // 将得到的随机7个数字的数组返回
}
/**
* create by: 全聚德在逃烤鸭、
* description:用户输入一组号码,6个红球号码(1-33,且不能重复),1个蓝球号码(1-16),将数据存储到数组中
* create time: 2022/4/1 0001 15:32
*
* @param
* @return int[]
*/
public static int[] userInputNumbers() {
Scanner sc = new Scanner(System.in);
// 定义一个动态初始化数组,存储7个数字
int[] numbers = new int[7];
// 要求用户选择6个红球号码,范围1-33
for (int i = 0; i < numbers.length - 1; i++) {
// 依次输入6个红球号码,判断6个红球号码是否均满足范围要求且不重复,若是则将号码存储到数组中,否则重新输入
while (true) {
boolean isDifferent = true; // 默认当前选择的号码是与之前选择的号码是不同的
System.out.println("请选择第" + (i + 1) + "个红球号码:");
int number = sc.nextInt();
// 判断输入的数据是否在1-33范围内,若不在,则给出提示,并跳出本次循环,重新输入
if (number < 1 | number > 33) {
System.out.println("选择号码超出范围1-33,请重新选择!");
continue; // 跳出本次while循环,重新当前输入红球选择的数据
}
// 遍历之前已经选择完毕的号码,判断是否有重复的,若有,则给出提示并重新选择;若没有,则继续
for (int j = 0; j < i; j++) {
// 判断是否重复
if (numbers[j] == number) {
System.out.println("号码" + number + "重复,请重新选择!");
isDifferent = false; // 将是否不同置为false
break; // 无需继续判断,跳出当前for循环
}
}
// 若isDifferent为true,说明遍历完第(i+1)个之前的号码,均没有重复的,本次选择号码有效
if (isDifferent) {
numbers[i] = number; // 将选择的号码添加到数组中
break; // 跳出当前while循环,选择下一个红球号码
}
}
}
// 要求用户录入1个蓝球号码,范围1-16
while (true) {
System.out.println("请选择蓝球号码:");
int number = sc.nextInt();
// 判断输入的数据是否在1-16范围内,若在,则将其添加到数组中,并跳出本次循环,否则给出提示并重新输入
if (number >= 1 & number <= 16) {
int length = numbers.length;
numbers[length - 1] = number; // 将选择的号码添加到数组中
break; // 跳出本次循环
}
System.out.println("选择号码超出范围1-16,请重新选择!");
}
return numbers; // 将输入的7个数字的数组返回
}
/**
* create by: 全聚德在逃烤鸭、
* description: 中奖情况判断 接收中奖号码的数组,用户选号的数组,根据命中红球数和篮球数判断最终的中奖情况并输出详情和中奖金额。
* create time: 2022/4/1 0001 19:40
*
* @param creatLuckyNumber
* @param userInputNumbers
* @return void
*/
public static void judgeWinning(int[] creatLuckyNumber, int[] userInputNumbers) {
int redSame = 0; // 定义变量存储红球猜中个数
// 遍历用户红球的每个选号,然后遍历红球中奖号码的数组,看当前选号是否在中奖号码中存在,存在则红球命中数量加1
for (int i = 0; i < userInputNumbers.length - 1; i++) { // userInputNumbers.length - 1,蓝球不包括在内
// 拿出当前选择的号码,遍历所有的中奖号码,并进行比较,查看是否猜中,若猜中则红球命中数量加1
for (int j = 0; j < creatLuckyNumber.length - 1; j++) { // creatLuckyNumber.length - 1,蓝球不包括在内
// 如果存在中奖号码,则红球猜中个数+1,跳出当前循环
if (userInputNumbers[i] == creatLuckyNumber[j]) { // 当前选择的号码在中奖号码中存在,即代表当前号码猜中了
redSame++;
break;
}
}
}
// 定义变量存储蓝球是否猜中
boolean blueSame = creatLuckyNumber[creatLuckyNumber.length - 1] == userInputNumbers[userInputNumbers.length - 1] ? true : false;
// 打印最终中奖号码、选择号码以及结果情况
System.out.print("您选择的号码是:");
printArray(userInputNumbers);
System.out.print("中奖号码是:");
printArray(creatLuckyNumber);
System.out.println("您猜中了" + redSame + "个红球," + (blueSame ? 1 : 0) + "个蓝球");
// 根据猜中红球与蓝球的数目打印对应的奖励结果
if (blueSame) {
switch (redSame) {
case 6:
System.out.println("恭喜您,中了一等奖,中6+1,奖金最高1000W");
break;
case 5:
System.out.println("恭喜您,中了三等奖,中5+1,奖金3000元");
break;
case 4:
System.out.println("恭喜您,中了四等奖,中4+1,奖金200元");
break;
case 3:
System.out.println("恭喜您,中了五等奖,中3+1,奖金10元");
break;
case 2:
System.out.println("恭喜您,中了六等奖,中2+1,奖金5元");
break;
case 1:
System.out.println("恭喜您,中了六等奖,中1+1,奖金5元");
case 0:
System.out.println("恭喜您,中了六等奖,中0+1,奖金5元");
break;
default:
System.out.println("数据输入错误!");
}
} else {
switch (redSame) {
case 6:
System.out.println("恭喜您,中了二等奖,中6+0,奖金最高500W");
break;
case 5:
System.out.println("恭喜您,中了四等奖,中5+0,奖金200元");
break;
case 4:
System.out.println("恭喜您,中了五等奖,中4+0,奖金10元");
break;
default:
System.out.println("很遗憾您没有中奖!");
}
}
}
写在最后:
感谢读完!
纵然缓慢,驰而不息!加油!