目录
实验1 信用卡号码的校验
- 题目
信用卡号码的编排遵循一定的规则,一般信用卡的号码长度是 13-16 位数字,并且首位数字代表不同的卡类型(比如 4 代表 Visa 卡,5 代表 Master 卡等等),另外它的所有数字使用“Luhn 校验”算法(也称 mod 10 校验)完成检验。
1954 年,在IBM工作的 Hans Luhn 提出了用来验证信用卡号码的算法,该算法对卡片号 码输入是否正确起到了验证作用。随后这个算法被广泛应用于类似于身份识别码的验证。
该算法的具体执行步骤如下:(假如验证号码:4388576018402626)
1.对数字序列从右到左,将所有的偶数位出现的数字翻倍计算,如果计算的结果是一个二 位数,那么就将二位数的每个数位的值进行加和运算。
2.将第1步中计算出的每个数字进行加和:4+4+8+2+3+1+7+8=37。
3.对数字序列从右到左,将所有的奇数位出现的数字进行加和:6+6+0+8+0+7+8+3=38。
4.将第2步和第3步的结果进行相加:37+38=75。
5.如果第4步计算的结果可以被 10 整除,那么这个卡号就是正确的,否则就是错误的。因此上面例子中的卡号是一个非法的卡号。
编写一个程序,要求用户输入卡号(在程序中必须以读入整数代码的形式实现),输出用户输入的卡号是否正确。
备注:
1.信用卡的号码长度是 13-16 位,请注意存储卡号的整数类型;
2.如果不要求用户严格的输入 13-16 位数字,那么就需要在真正执行计算之前对用户输入的数据合法性进行检查,请列举能想到的非法性输入,并将这些检查应用到程序实现中。
- 数据设计
用long长整型储存信用卡号码
用int[]储存信用卡卡号的各个数字
- 算法设计
用户输入一个 13-16 位的银行卡号。
程序首先检查用户输入是否是一个有效的整数,如果不是,则提示用户重输入。
一旦输入被确认为有效的整数,程序检查该整数是否在 1e12 到 1e16 的范围内,如果不在此范围内,会要求用户重新输入。
然后,程序将每个数字从该整数中提取并将它们存储在一个整数数组中。这个数组将用于后续的处理。
接下来,程序遍历数组中的每个数字,对位于奇数索引位置(从0开始计数)的数字执行 Luhn 算法中的“翻倍和减9”操作(即 even 方法),而偶数索引位置的数字将保持不变。
最后,程序将数组中的所有数字相加,然后检查它们的总和是否可以被 10 整除。如果可以整除,程序输出 "卡号合法",否则输出 "卡号非法"。
- 主干代码说明
while (true) {
String userInput = sc.nextLine();
if (isNumber(userInput)) {//第一层循环,判断是否为整数
num = Long.parseLong(userInput);
if (num >= 1e12 && num < 1e16) {//第二层循环,判断是否在范围内
break;
} else
System.out.println("输入错误,您输入的不是13-16位的正整数,请重新输入");
} else
System.out.println("输入错误,您输入的不是整数,请重新输入");
}
一段无限循环的代码,当输入合法的数之后break,第一层循环调用函数,判断是否为整数,第二层循环判断数是否在范围内,分别以不同的提示提醒用户。
//拿出各个位数,存在数组里
int[] digit = new int[16];
int i = 0;
while (num > 0) {
digit[i] = (int) (num % 10);
num /= 10;
i++;
}
很简单,把卡号的各个位数放到数组里。
// 进行运算,把数组中的数重置
for (int j = 0; j < i; j++) {
if (j % 2 == 1) {
digit[j] = (int) even(digit[j]);
}
}
//进行加法,判断最终结果
int sum = 0;
for (int k = 0; k < i; k++) {
sum += digit[k];
}
用题目中给的算法将数组中的数重置并求和。
public static boolean isNumber(String input) {
try {
long number = Long.parseLong(input);
return true;
} catch (NumberFormatException e) {
return false; // 如果无法解析为整数,输入无效
}
}
Integer.parseInt(input) 是一个常用的方法,它会尝试将一个字符串解析成整数。
如果字符串 input 包含一个有效的整数表示,那么它将被转换为整数类型,并赋值给 number 变量。
如果 input 不能解析为整数(例如,它包含非数字字符),则会引发 NumberFormatException 异常。
这里用的是Long.parseLong(input),对long类型进行相同操作
- 运行结果展示
- 总结和收获
通过本题,学到了基础的异常处理,如何保证用户输入一个合法的数而不报错。也锻炼了自己的算法能力。
实验2
- 题目
编写一个 DateUtil 类(其实是 library,只是用类这种语法将相关的函数聚集在一起),其为与日期处理有关的工具类,具体包含的函数如下所列:
• static boolean isLeapYear(int year) o returns true if the given year is a leap year. A year is a leap year if it is divisible by 4 but not by 100, or it is divisible by 400.
• static boolean isValidDate(int year, int month, int day) o returns true if the given year, month and day constitute a given date. Assume that year is between 1 and 9999, month is between 1 (Jan) to 12 (Dec) and day shall be between 1 and 28|29|30|31 depending on the month and whether it is a leap year.
• static int getDayOfWeek(int year, int month, int day): o returns the day of the week, where 0 for SUN, 1 for MON, ..., 6 for SAT, for the given date. Assume that the date is valid.
• static void printCalendar(int year, int month) o The calendar for the specified year/month is output on the screen according to the calendar output format.
• static void printCalendar(int year) o The Calendar for the specified year is output on the screen according to the calendar output format.
• static String formatDate(int year, int month, int day) o prints the given date in the format "xxxday d mmm yyyy", e.g., "Tuesday 14 Feb 2012". Assume that the given date is valid.
- 数据设计
本题对数据要求不高,主要是编写方法,数据储存类型用int和String就行。
- 算法设计
第一个方法用判断闰年的算法即可。
第二个方法,首先对年和月进行判断,不符合条件返回false,对日判断的时候要考虑年和月,首先对1,3-12月进行判断,对于2月,再调用第一个方法判断是否闰年再判断。
第三个方法,首先调用第二个方法对输入的年月日进行判断看是否符合标准,接下来根据题目中给的算法一步步运算即可。
第四个方法有点困难,我们首先需要知道这个月一共有多少天,于是我又重新写了一个方法getLastDay用于根据输入的年和月计算这个月一共多少天,再第四个方法内用lastDay接收,同时调用第三个方法计算这个月的第一天是星期几,同时定义一个计数器counter,当counter为7的倍数时换行。首先打印第一行,从SUN到SAT,中间隔三个空格。第二行开始打印数字,打印之前对每个数字进行判断,如果数字大于9,占两位,那么数字之间间隔为4,否则为5.
第五个方法和第四个方法类似,区别在于:1.我们这次根据平闰年判断这年最后一天是365还是366;2.有可能出现三位数的情况,在出现三位数时,数字间隔为3个空格,保证美观。
第六个方法很简单,主要是调用之前定义的方法。首先调用第二个方法,用户输入的日期进行判断,不合法则循环进行。我们使用StringBuffer的append方法,不断调用先前定义的方法再append到字符串中,最后将StringBuffer转化为String再输出。
- 主干代码说明
第二个方法:
static boolean isValidDate(int year, int month, int day) {
if (year < 1 || year > 9999 || month < 1 || month > 12) {
return false;
} else {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
return day >= 1 && day <= 31;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return day >= 1 && day <= 30;
} else {
if (DateUtil.isLeapYear(year))
return day >= 1 && day <= 29;
else
return day >= 1 && day <= 28;
}
}
}
第二个方法,首先对年和月进行判断,不符合条件返回false,对日判断的时候要考虑年和月,首先对1,3-12月进行判断,对于2月,再调用第一个方法判断是否闰年再判断。
第四个方法:
static void printCalendar(int year, int month) {
int lastDay = DateUtil.getLastDay(year, month);
int date = DateUtil.getDayOfWeek(year, month, 1);
int counter = 0;
System.out.println(" SUN MON TUE WED THU FRI SAT");
for (int i = 0; i < date; i++) {
System.out.print(" ");
counter++;
}
for (int i = 1; i <= lastDay; i++) {
if (i > 9) {
System.out.print(" " + i);
counter++;
if (counter % 7 == 0) {
System.out.println(" ");
counter = 0;
}
} else {
System.out.print(" " + i);
counter++;
if (counter % 7 == 0) {
System.out.println(" ");
counter = 0;
}
}
}
System.out.println("");
}
自定义的方法getLastDay:
static int getLastDay(int year, int month) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
return 31;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
if (DateUtil.isLeapYear(year))
return 29;
else
return 28;
}
}
第四个方法,用自定义的方法getLastDay用于根据输入的年和月计算这个月一共多少天,再第四个方法内用lastDay接收,同时调用第三个方法计算这个月的第一天是星期几,同时定义一个计数器counter,当counter为7的倍数时换行。首先打印第一行,从SUN到SAT,中间隔三个空格。第二行开始打印数字,打印之前对每个数字进行判断,如果数字大于9,占两位,那么数字之间间隔为4,否则为5.
第六个方法:
static String formatDate(int year, int month, int day) {
if (DateUtil.isValidDate(year, month, day)){
String s="";
String years=Integer.toString(year);
String days=Integer.toString(day);
StringBuffer sb = new StringBuffer(s);
int DayOfWeek=DateUtil.getDayOfWeek(year,month,day);
switch (DayOfWeek) {
case 0 -> sb.append("Sunday ");
case 1 -> sb.append("Monday ");
case 2 -> sb.append("Tuesday ");
case 3 -> sb.append("Wednesday ");
case 4 -> sb.append("Thursday ");
case 5 -> sb.append("Friday ");
case 6 -> sb.append("Saturday ");
}
sb.append(days);
sb.append(" ");
switch (month) {
case 1 -> sb.append("Jan ");
case 2 -> sb.append("Feb ");
case 3 -> sb.append("Mar ");
case 4 -> sb.append("Apr ");
case 5 -> sb.append("May ");
case 6 -> sb.append("Jun ");
case 7 -> sb.append("Jul ");
case 8 -> sb.append("Aug ");
case 9 -> sb.append("Sept ");
case 10 -> sb.append("Oct ");
case 11 -> sb.append("Nov ");
case 12 -> sb.append("Dec ");
}
sb.append(years);
String ss=new String(sb);
return ss;
}else{
System.out.println("您输入的日期有误");
return "-1";
}
}
首先定义了String s,years,days,s用于最终被返回,years和days分别接受int类型的year和day。
然后定义了StringBuffer sb,用于拼接,接下来调用方法拼接sb。
最后将sb转化为String类型的ss,输出。
- 运行结构展示
备注:位置有限,2023年的日历仅仅展示一部分。
实验3
- 题目
编写一个程序,通过命令行参数的方式,接收两个参数,参数 1 指定打印的图形模式(分别为 下图中的 a\b\c\d\e),参数 2 指定打印的图形的大小(一个非负整数)。
- 数据设计
String用于接收用户输入,参数2后续再转变成int类型。
- 算法设计
主函数用两层循环,每层循环内分别对用户输入的参数1和2判断是否符合标准,当都符合标准的时候,进行打印,打印用方法output,接收参数1和参数2,在后面单独定义了方法output。
第一个图形,将图形分成三部分,第一行是第一部分,最后一行是第三部分,中间num-2行是第二部分。第一三部分用循环打印即可,第二部分,外循环是对每一行的操作,每一行先打一个#,再打num-2个空格,再打一个#。
第二个图形,同样将其分为三部分,主要是第二部分,外循环依旧是对每行进行操作,先打i+1个空格,打一个#,再打num-i-1个空格。
第三个图形和第二个图形类似,这里不再赘述。
第四个图形,将其分为五个部分,第一行和最后一行不变,第二三四部分根据num是奇数还是偶数进行分类讨论。当num为奇数时,第二四部分各自包含(num-3)/2行,第三部分包括一行;当num为偶数时,第二四部分各自包含(num-4)/2行,第三部分包括两行。
第五个图形和第四个图形类似,只是第二三四部分打印的稍微改变一下。
- 主干代码说明
for (int i = 0; i < number; i++) {
System.out.print("#");
}
System.out.println("");
for (int i = 0; i < number - 2; i++) {//每行的操作
for (int j = 0; j < i + 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - i - 1; j++) {
System.out.print(" ");
}
System.out.println("");
}
if (number != 1) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
}
第二个图形,将图形分成三部分,第一行是第一部分,最后一行是第三部分,中间num-2行是第二部分。第一三部分用循环打印#即可,第二部分,外循环是对每一行的操作,先打i+1个空格,打一个#,再打num-i-1个空格。
if(number==0){
System.out.println("");
}else{
if (number != 1 && number != 2) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
System.out.println("");
}
if (number % 2 == 0) {//分成奇偶进行讨论
for (int i = 0; i < (number - 4) / 2; i++) {//上半
for (int j = 0; j < i + 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 4; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i + 2; j++) {
System.out.print(" ");
}
System.out.println("");
}
//中间两行
if (number != 2) {
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.print("#");
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.println("");
}
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.print("#");
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.println("");
for (int i = (number - 4) / 2; i > 0; i--) {//下半
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 2; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.println("");
}
} else {//奇数的情况
for (int i = 0; i < (number - 3) / 2; i++) {//上半
for (int j = 0; j < i + 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 4; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i + 2; j++) {
System.out.print(" ");
}
System.out.println("");
}
//中间一行
for (int i = 0; i < (number - 1) / 2; i++) {
System.out.print(" ");
}
System.out.print("#");
for (int i = 0; i < (number - 1) / 2; i++) {
System.out.print(" ");
}
System.out.println("");
for (int i = (number - 3) / 2; i > 0; i--) {//下半
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 2; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.println("");
}
}
if (number != 1) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
}
}
第四个图形,将其分为五个部分,第一三部分用循环打印即可,第二三四部分根据num是奇数还是偶数进行分类讨论。当num为奇数时,第二四部分各自包含(num-3)/2行,第三部分包括一行;当num为偶数时,第二四部分各自包含(num-4)/2行,第三部分包括两行。
- 运行结构展示
实验4
- 题目
请编写一个 MorseCodeDecode.java 程序,该程序的输入数据从文件 encode.txt 中读取,最终
给出对该文件所包含的摩斯密码的解密结果。
- 数据设计
一个哈希表用来储存键值对,用BufferedReader读取文件内容,StringBuilder构建解密后的文本,用两个String数组储存每一个单词和每一个字母。
- 算法设计
创建一个String line用于读取文本内容,创建一个StringBuilder对象,名为decodedText,用于构建解密后的文本。
从文件中逐行读取内容直到当读取到的行为空,根据3个空格来分割当前读取到的行line,分割后的每一个结果都存储在一个名为morseWords的字符串数组中,用增强型for循环,用于遍历morseWords数组中的每个元素morseWord,每次循环,都会取出数组中的一个摩尔斯码单词,并将其存储在变量morseWord中。
遍历morseWords数组中的每个元素morseWord,根据1个空格来分割当前读取到的morseWord,分割后的每一个结果都存储在一个名为morseLetters的字符串数组中,用增强型for循环,用于遍历morseLetters数组中的每个元素morseLetter,每次循环,判断这个morseLetter是否存在于创建的map中,如果存在,则添加到decodedText中,不存在则添加原有的内容。
每个单词间隔添上空格。
最后输出:toString()方法是将StringBuilder对象decodedText转换成String类型。.trim(): trim()方法是用来去掉字符串前后的空格。.toLowerCase(): toLowerCase()方法是将字符串中的所有大写字母转换成小写字母。
- 主干代码说明
while ((line = br.readLine()) != null) {
String[] morseWords = line.split(" {3}");
for (String morseWord : morseWords) {
String[] morseLetters = morseWord.split(" ");
for (String morseLetter : morseLetters) {
if (morseCodeMap.containsKey(morseLetter)) {
decodedText.append(morseCodeMap.get(morseLetter));
} else {
// 未知的摩斯码,将原样添加到解密文本中
decodedText.append(morseLetter);
}
}
// 添加单词间的空格
decodedText.append(" ");
}
}
从指定的文件中一行一行地读取内容,直到读取到的行为空为止。对于每一行,根据3个连续的空格来将其分割成多个部分,这些部分称之为摩尔斯码单词,并将它们存储在一个名为morseWords的字符串数组中。
接下来,会逐一处理morseWords数组中的每个摩尔斯码单词。对于每个单词,再根据单个空格将其分割成更小的部分,并将它们存储在一个名为morseLetters的字符串数组中。
然后,会逐一检查morseLetters数组中的每个摩尔斯码字母。如果这个字母在摩尔斯码映射表(即morseCodeMap)中存在,就将映射表中对应的解密文本添加到decodedText中;如果不存在,就直接将摩尔斯码字母本身添加到decodedText中。
在处理完morseLetters数组中的所有摩尔斯码字母后,会在decodedText中添加一个空格,以分隔不同的摩尔斯码单词。
这个过程会一直重复,直到处理完文件中的所有行。
- 运行结构展示
实验5
- 题目
题目要求使用蒙特卡洛方法
求解圆周率Π。具体的过程可以按照下面的方式来模拟:下图为边长为 1 的正方形,随机的向该正方形中投入 n 个点,统计落入 1/4 正切圆中的点的个数为 m,那么可以通过 m/n 的比例间
接求解圆周率。如图所示,当投入的点数为 3000 时,统计出来的Π近似为 3.1133。
编写一个 PIByMonte.java 程序,该程序接收 1 个命令行参数 n(意义如题中描述),运行
结束后,输出在给定的 n 下,求解的近似圆周率值。另外,尝试将 n 的值不断增长,看看程序
输出结果的变化趋势。
- 数据设计
用int接收m和n即可。
- 算法设计
进行n次循环,每一次循环都在0-1中随机一个double类型的数代表长和宽,然后计算距离,当距离小于1时,m++,最后计算(m/n)*4就是圆周率。
- 主干代码说明
for (int i = 0; i < n; i++) { double length = r.nextDouble(); double width = r.nextDouble(); double distance = Math.sqrt((length * length) + (width * width)); if (distance < 1.0) { m++; } } double pai= ((double) m /n)*4; System.out.println("预测圆周率为"+pai);
- 运行结构展示
结果越来与接近真实值。
实验6
- 题目
一只兔子在我校地东操场漫无目的地行走,假设这只兔子每一步都走 1 米(有点夸张,但并不影响模拟地结论),且它地行走方向只能是东、西、南、北四个方向,选择每个方向的概率都是一样的,那么当这只兔子行走 n 步之后,离它出发的点有多远呢?这个过程就是著名的二维随机游走问题。
1.编写一个 RandomWalker.java 程序,该程序接收一个整数类型的命令行参数 n,功能是模拟题干中描述的二维随机游走 n 步的过程。程序要求输出:每一步的坐标(包括起始步的坐标,假设每次起始步的坐标都是(0,0)),除此以外,还需要给出 n 步之后最终位置和起始位置的欧几里得距离。
2.编写一个 RandomWalkers.java 程序,该程序接收两个整数类型的命令行参数 n 和trials。n 的意义如同 1 中描述的含义,trials 表示的是完成实验的次数(一次实验即一只兔子完成 n 步行走)。程序要求输出:完成 trials 次实验之后的欧几里得距离的平均值。
备注:执行多次该程序,调整 n 参数和 trials 参数,观察是否随着 n 的增加,兔子行走的距离会离原点越来越远?如果不是的话,那么距离和 n 的值有关系吗?
- 数据设计
用int储存坐标,用double储存距离和距离的平均值。
- 算法设计
用random随机四个数,分别代表四个方向的移动。
- 主干代码说明
for (int i = 0; i < n; i++) { System.out.println("兔子当前的坐标为(" + length + "," + width + ")"); int chosen = r.nextInt(4) + 1; switch (chosen) { case 1 -> length++; case 2 -> length--; case 3 -> width++; case 4 -> width--; } }
- 运行结构展示
随着 n的增加,兔子行走的距离会离原点越来越远。
附录:
第一题:
package homework01;
import java.util.Scanner;
public class homework01 {
public static void main(String[] args) {
//数据结构准备
Scanner sc = new Scanner(System.in);
long num;
//异常处理和数据输入
System.out.println("请输入13-16位卡号:");
while (true) {
String userInput = sc.nextLine();
if (isNumber(userInput)) {//第一层循环,判断是否为整数
num = Long.parseLong(userInput);
if (num >= 1e12 && num < 1e16) {//第二层循环,判断是否在范围内
break;
} else
System.out.println("输入错误,您输入的不是13-16位的正整数,请重新输入");
} else
System.out.println("输入错误,您输入的不是整数,请重新输入");
}
//拿出各个位数,存在数组里
int[] digit = new int[16];
int i = 0;
while (num > 0) {
digit[i] = (int) (num % 10);
num /= 10;
i++;
}
// 进行运算,把数组中的数重置
for (int j = 0; j < i; j++) {
if (j % 2 == 1) {
digit[j] = (int) even(digit[j]);
}
}
//进行加法,判断最终结果
int sum = 0;
for (int k = 0; k < i; k++) {
sum += digit[k];
}
//判断sum
if (sum % 10 == 0) {
System.out.println("卡号合法");
} else {
System.out.println("卡号非法");
}
}
public static boolean isNumber(String input) {
try {
long number = Long.parseLong(input);
return true;
} catch (NumberFormatException e) {
return false; // 如果无法解析为整数,输入无效
}
//Integer.parseInt(input) 是一个常用的方法,它会尝试将一个字符串解析成整数。
//如果字符串 input 包含一个有效的整数表示,那么它将被转换为整数类型,并赋值给 number 变量。
//如果 input 不能解析为整数(例如,它包含非数字字符),则会引发 NumberFormatException 异常。
//这里用的是Long.parseLong(input),对long类型进行相同操作
}
public static long even(long num) {
long doubled = num * 2;
if (doubled > 9) {
return doubled - 9;
} else {
return doubled;
}
}
}
第二题:
DateUtil.java:
package homework02;
public class DateUtil {
/*1. returns true if the given year is a leap year. A year is a leap year if it
is divisible by 4 but not by 100, or it is divisible by 400.*/
static boolean isLeapYear(int year) {
return year % 400 == 0 || ((year % 4 == 0) && (year % 100 != 0));
}
/*2. returns true if the given year, month and day constitute a given date.
Assume that year is between 1 and 9999, month is between 1 (Jan) to 12
(Dec) and day shall be between 1 and 28|29|30|31 depending on the month
and whether it is a leap year.*/
static boolean isValidDate(int year, int month, int day) {
if (year < 1 || year > 9999 || month < 1 || month > 12) {
return false;
} else {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
return day >= 1 && day <= 31;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return day >= 1 && day <= 30;
} else {
if (DateUtil.isLeapYear(year))
return day >= 1 && day <= 29;
else
return day >= 1 && day <= 28;
}
}
}
/*3. returns the day of the week, where 0 for SUN, 1 for MON, ..., 6 for SAT,
for the given date. Assume that the date is valid.*/
static int getDayOfWeek(int year, int month, int day) {
if (DateUtil.isValidDate(year, month, day)) {
int sum = 0;
if ((year / 100) % 4 == 0)
sum += 6;
else if ((year / 100) % 4 == 1)
sum += 4;
else if ((year / 100) % 4 == 2)
sum += 2;
else
sum += 0;
sum += (year % 100);
sum += ((year % 100) / 4);
if (DateUtil.isLeapYear(year)) {
switch (month) {
case 1, 4, 7 -> sum += 6;
case 2, 8 -> sum += 2;
case 3, 11 -> sum += 3;
case 5 -> sum += 1;
case 6 -> sum += 4;
case 9, 12 -> sum += 5;
}
} else {
switch (month) {
case 2, 3, 11 -> sum += 3;
case 4, 7 -> sum += 6;
case 5 -> sum += 1;
case 6 -> sum += 4;
case 8 -> sum += 2;
case 9, 12 -> sum += 5;
}
}
sum += day;
return sum % 7;
} else {
System.out.println("您输入的日期有误");
return -1;
}
}
/*4. The calendar for the specified year/month is output on the screen
according to the calendar output format.*/
static void printCalendar(int year, int month) {
int lastDay = DateUtil.getLastDay(year, month);
int date = DateUtil.getDayOfWeek(year, month, 1);
int counter = 0;
System.out.println(" SUN MON TUE WED THU FRI SAT");
for (int i = 0; i < date; i++) {
System.out.print(" ");
counter++;
}
for (int i = 1; i <= lastDay; i++) {
if (i > 9) {
System.out.print(" " + i);
counter++;
if (counter % 7 == 0) {
System.out.println(" ");
counter = 0;
}
} else {
System.out.print(" " + i);
counter++;
if (counter % 7 == 0) {
System.out.println(" ");
counter = 0;
}
}
}
System.out.println("");
}
/*5. The Calendar for the specified year is output on the screen according to
the calendar output format.*/
static void printCalendar(int year) {
int lastDay = DateUtil.getLastDay(year);
int date = DateUtil.getDayOfWeek(year, 1, 1);
int counter = 0;
System.out.println(" SUN MON TUE WED THU FRI SAT");
for (int i = 0; i < date; i++) {
System.out.print(" ");
counter++;
}
for (int i = 1; i <= lastDay; i++) {
if (i > 9&&i<100) {
System.out.print(" " + i);
counter++;
if (counter % 7 == 0) {
System.out.println(" ");
counter = 0;
}
} else if(i<10) {
System.out.print(" " + i);
counter++;
if (counter % 7 == 0) {
System.out.println(" ");
counter = 0;
}
}else{
System.out.print(" " + i);
counter++;
if (counter % 7 == 0) {
System.out.println(" ");
counter = 0;
}
}
}
System.out.println("");
}
/*6. prints the given date in the format "xxxday d mmm yyyy", e.g., "Tuesday
14 Feb 2012". Assume that the given date is valid.*/
static String formatDate(int year, int month, int day) {
if (DateUtil.isValidDate(year, month, day)){
String s="";
String years=Integer.toString(year);
String days=Integer.toString(day);
StringBuffer sb = new StringBuffer(s);
int DayOfWeek=DateUtil.getDayOfWeek(year,month,day);
switch (DayOfWeek) {
case 0 -> sb.append("Sunday ");
case 1 -> sb.append("Monday ");
case 2 -> sb.append("Tuesday ");
case 3 -> sb.append("Wednesday ");
case 4 -> sb.append("Thursday ");
case 5 -> sb.append("Friday ");
case 6 -> sb.append("Saturday ");
}
sb.append(days);
sb.append(" ");
switch (month) {
case 1 -> sb.append("Jan ");
case 2 -> sb.append("Feb ");
case 3 -> sb.append("Mar ");
case 4 -> sb.append("Apr ");
case 5 -> sb.append("May ");
case 6 -> sb.append("Jun ");
case 7 -> sb.append("Jul ");
case 8 -> sb.append("Aug ");
case 9 -> sb.append("Sept ");
case 10 -> sb.append("Oct ");
case 11 -> sb.append("Nov ");
case 12 -> sb.append("Dec ");
}
sb.append(years);
String ss=new String(sb);
return ss;
}else{
System.out.println("您输入的日期有误");
return "-1";
}
}
static int getLastDay(int year, int month) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
return 31;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
if (DateUtil.isLeapYear(year))
return 29;
else
return 28;
}
}
static int getLastDay(int year) {
if (DateUtil.isLeapYear(year))
return 365;
else
return 366;
}
}
TestDateUtil.java:
package homework02;
import java.util.Scanner;
public class TestDateUtil {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 输入年、月、日
System.out.print("请输入年份:");
int year = sc.nextInt();
System.out.print("请输入月份:");
int month = sc.nextInt();
System.out.print("请输入日期:");
int day = sc.nextInt();
//验证DateUtil.isLeapYear
if(DateUtil.isLeapYear(year)){
System.out.println(year+"是闰年");
}else {
System.out.println(year+"不是闰年");
}
//验证DateUtil.isValidDate
if(DateUtil.isValidDate(year,month,day)){
System.out.println("该日期有效");
}else {
System.out.println("该日期无效");
}
//验证DateUtil.getDayOfWeek
switch (DateUtil.getDayOfWeek(year,month,day)) {
case 0 -> System.out.println("Sunday");
case 1 -> System.out.println("Monday");
case 2 -> System.out.println("Tuesday");
case 3 -> System.out.println("Wednesday");
case 4 -> System.out.println("Thursday");
case 5 -> System.out.println("Friday");
case 6 -> System.out.println("Saturday");
}
//验证DateUtil.printCalendar
DateUtil.printCalendar(year,month);
System.out.println("");
DateUtil.printCalendar(year);
//验证DateUtil.formatDate
System.out.println(DateUtil.formatDate(year,month,day));
}
}
第三题:
package homework03;
import java.util.Scanner;
public class homework03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num;
String userInput2;
String userInput;
//第一次输入
while (true) {
System.out.print("请输入a\\b\\c\\d\\e指定打印的图形模式:");
userInput = sc.nextLine();
if (isValid(userInput)) {
//第二次输入
while (true) {
System.out.print("请输入正整数指定打印的图形大小:");
userInput2 = sc.nextLine();
if (isValidNumber(userInput2)) {//第一层循环,判断是否为整数
break;
} else
System.out.println("您输入的不正确,请重新输入");
}
output(userInput, userInput2);
break;
} else {
System.out.println("您输入的不正确,请重新输入");
}
}
}
public static boolean isValid(String s) {
return s.equals("a") || s.equals("b") || s.equals("c") || s.equals("d") || s.equals("e");
}
public static boolean isValidNumber(String input) {
try {
int number = Integer.parseInt(input);
return number >= 0;
} catch (NumberFormatException e) {
return false;
}
}
public static void output(String s, String num) {
int number = Integer.parseInt(num);
switch (s) {
case "a" -> {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
System.out.println("");
for (int i = 0; i < number - 2; i++) {
System.out.print("#");
for (int j = 0; j < number - 2; j++) {
System.out.print(" ");
}
System.out.println("#");
}
if (number != 1) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
}
}
case "b" -> {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
System.out.println("");
for (int i = 0; i < number - 2; i++) {//每行的操作
for (int j = 0; j < i + 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - i - 1; j++) {
System.out.print(" ");
}
System.out.println("");
}
if (number != 1) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
}
}
case "c" -> {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
System.out.println("");
for (int i = 0; i < number - 2; i++) {//每行的操作
for (int j = 0; j < number - i - 2; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i + 2; j++) {
System.out.print(" ");
}
System.out.println("");
}
if (number != 1) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
}
}
case "d" -> {
if(number==0){
System.out.println("");
}else{
if (number != 1 && number != 2) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
System.out.println("");
}
if (number % 2 == 0) {//分成奇偶进行讨论
for (int i = 0; i < (number - 4) / 2; i++) {//上半
for (int j = 0; j < i + 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 4; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i + 2; j++) {
System.out.print(" ");
}
System.out.println("");
}
//中间两行
if (number != 2) {
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.print("#");
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.println("");
}
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.print("#");
for (int i = 0; i < (number - 2) / 2; i++) {
System.out.print(" ");
}
System.out.println("");
for (int i = (number - 4) / 2; i > 0; i--) {//下半
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 2; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.println("");
}
} else {//奇数的情况
for (int i = 0; i < (number - 3) / 2; i++) {//上半
for (int j = 0; j < i + 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 4; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i + 2; j++) {
System.out.print(" ");
}
System.out.println("");
}
//中间一行
for (int i = 0; i < (number - 1) / 2; i++) {
System.out.print(" ");
}
System.out.print("#");
for (int i = 0; i < (number - 1) / 2; i++) {
System.out.print(" ");
}
System.out.println("");
for (int i = (number - 3) / 2; i > 0; i--) {//下半
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 2; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.println("");
}
}
if (number != 1) {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
}
}
}
case "e" -> {
if (number == 1) {
System.out.println("#");
} else if (number == 2) {
System.out.println("##");
System.out.print("##");
} else if (number==0) {
System.out.println("");
} else {
for (int i = 0; i < number; i++) {
System.out.print("#");
}
System.out.println("");
if (number % 2 == 0) {//分成奇偶进行讨论
for (int i = 0; i < (number - 4) / 2; i++) {//上半
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 4; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.print("#");
System.out.println("");
}
//中间两行
System.out.print("#");
for (int i = 0; i < ((number - 2) / 2) - 1; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.print("#");
for (int i = 0; i < ((number - 2) / 2) - 1; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.println("");
System.out.print("#");
for (int i = 0; i < ((number - 2) / 2) - 1; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.print("#");
for (int i = 0; i < ((number - 2) / 2) - 1; i++) {
System.out.print(" ");
}
System.out.print("#");
System.out.println("");
for (int i = (number - 4) / 2; i > 0; i--) {//下半
System.out.print("#");
for (int j = 0; j < i - 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 2; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i - 1; j++) {
System.out.print(" ");
}
System.out.print("#");
System.out.println("");
}
} else {//奇数的情况
for (int i = 0; i < (number - 3) / 2; i++) {//上半
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 4; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i; j++) {
System.out.print(" ");
}
System.out.println("#");
}
//中间一行
System.out.print("#");
for (int i = 0; i < ((number - 1) / 2) - 1; i++) {
System.out.print(" ");
}
System.out.print("#");
for (int i = 0; i < ((number - 1) / 2) - 1; i++) {
System.out.print(" ");
}
System.out.println("#");
for (int i = (number - 3) / 2; i > 0; i--) {//下半
System.out.print("#");
for (int j = 0; j < i - 1; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < number - 2 * i - 2; j++) {
System.out.print(" ");
}
System.out.print("#");
for (int j = 0; j < i - 1; j++) {
System.out.print(" ");
}
System.out.println("#");
}
}
for (int i = 0; i < number; i++) {
System.out.print("#");
}
}
}
}
}
}
第四题:
package homework04;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class MorseCodeDecode {
public static void main(String[] args) {
//创建了一个Map对象,名为morseCodeMap。这个Map的键和值都是String类型。
//它用于存储摩尔斯码与其对应的字母或数字的映射关系。
Map<String, String> morseCodeMap = createMorseCodeMap();
//创建了一个BufferedReader对象,名为br。这个对象被用来读取文件内容
try (BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\86196\\Desktop\\encode.txt"))) {
String line;//用于存储从文件中读取的每一行内容。
//创建一个StringBuilder对象,名为decodedText。这个对象用于构建解密后的文本。
StringBuilder decodedText = new StringBuilder();
//从文件中逐行读取内容直到当读取到的行为空
while ((line = br.readLine()) != null) {
//Java的String.split()方法,根据3个空格来分割当前读取到的行line。
//分割后的每一个结果都存储在一个名为morseWords的字符串数组中
String[] morseWords = line.split(" {3}");
//增强型for循环,用于遍历morseWords数组中的每个元素。
//每次循环,都会取出数组中的一个摩尔斯码单词,并将其存储在变量morseWord中
for (String morseWord : morseWords) {
String[] morseLetters = morseWord.split(" ");
for (String morseLetter : morseLetters) {
//判断morseCodeMap中是否包含当前摩尔斯码字母morseLetter
if (morseCodeMap.containsKey(morseLetter)) {
decodedText.append(morseCodeMap.get(morseLetter));
} else {
// 未知的摩斯码,将原样添加到解密文本中
decodedText.append(morseLetter);
}
}
// 添加单词间的空格
decodedText.append(" ");
}
}
//toString()方法是将StringBuilder对象decodedText转换成String类型。
//.trim(): trim()方法是用来去掉字符串前后的空格。
//.toLowerCase(): toLowerCase()方法是将字符串中的所有大写字母转换成小写字母。
System.out.println("解密结果:");
System.out.println(decodedText.toString().trim().toLowerCase());
} catch (IOException e) {
System.err.println("读取文件时出错: " + e.getMessage());
}
}
// 返回类型是Map<String, String>
private static Map<String, String> createMorseCodeMap() {
//创建一个新的HashMap对象,并赋值给变量morseCodeMap。
Map<String, String> morseCodeMap = new HashMap<>();
// 在这里添加摩斯密码映射
morseCodeMap.put(".-", "A");
morseCodeMap.put("-...", "B");
morseCodeMap.put("-.-.", "C");
morseCodeMap.put("-..", "D");
morseCodeMap.put(".", "E");
morseCodeMap.put("..-.", "F");
morseCodeMap.put("--.", "G");
morseCodeMap.put("....", "H");
morseCodeMap.put("..", "I");
morseCodeMap.put(".---", "J");
morseCodeMap.put("-.-", "K");
morseCodeMap.put(".-..", "L");
morseCodeMap.put("--", "M");
morseCodeMap.put("-.", "N");
morseCodeMap.put("---", "O");
morseCodeMap.put(".--.", "P");
morseCodeMap.put("--.-", "Q");
morseCodeMap.put(".-.", "R");
morseCodeMap.put("...", "S");
morseCodeMap.put("-", "T");
morseCodeMap.put("..-", "U");
morseCodeMap.put("...-", "V");
morseCodeMap.put(".--", "W");
morseCodeMap.put("-..-", "X");
morseCodeMap.put("-.--", "Y");
morseCodeMap.put("--..", "Z");
morseCodeMap.put("-----", "0");
morseCodeMap.put(".----", "1");
morseCodeMap.put("..---", "2");
morseCodeMap.put("...--", "3");
morseCodeMap.put("....-", "4");
morseCodeMap.put(".....", "5");
morseCodeMap.put("-....", "6");
morseCodeMap.put("--...", "7");
morseCodeMap.put("---..", "8");
morseCodeMap.put(".-...", "&");
morseCodeMap.put(".----.", "'");
morseCodeMap.put(".--.-.", "@");
morseCodeMap.put("-.--.-", ")");
morseCodeMap.put("-.--.", "(");
morseCodeMap.put("---...", ":");
morseCodeMap.put("--..--", ",");
morseCodeMap.put("-...-", "=");
morseCodeMap.put("-.-.--", "!");
morseCodeMap.put(".-.-.-", ".");
morseCodeMap.put("-....-", "-");
morseCodeMap.put(".-.-.", "+");
morseCodeMap.put(".-..-.", "\"");
morseCodeMap.put("..--..", "?");
morseCodeMap.put("-..-.", "/");
return morseCodeMap;
}
}
第五题:
package homework05;
import java.util.Random;
import java.util.Scanner;
public class PIByMonte {
public static void main(String[] args) {
Random r = new Random();
Scanner sc = new Scanner(System.in);
System.out.print("请输入参数n:");
int n = sc.nextInt();
int m = 0;
for (int i = 0; i < n; i++) {
double length = r.nextDouble();
double width = r.nextDouble();
double distance = Math.sqrt((length * length) + (width * width));
if (distance < 1.0) {
m++;
}
}
double pai = ((double) m / n) * 4;
System.out.println("预测圆周率为" + pai);
}
}
第六题:
RandomWalker:
package homework06;
import java.util.Random;
import java.util.Scanner;
public class RandomWalker {
public static void main(String[] args) {
Random r = new Random();
Scanner sc = new Scanner(System.in);
System.out.print("请输入参数n:");
int length = 0;
int width = 0;
int n = sc.nextInt();
for (int i = 0; i < n; i++) {
System.out.println("兔子当前的坐标为(" + length + "," + width + ")");
int chosen = r.nextInt(4) + 1;
switch (chosen) {
case 1 -> length++;
case 2 -> length--;
case 3 -> width++;
case 4 -> width--;
}
}
System.out.println("兔子当前的坐标为(" + length + "," + width + ")");
double distance = Math.sqrt((length * length) + (width * width));
System.out.println(distance);
}
}
RandomWalkers:
package homework06;
import java.util.Random;
import java.util.Scanner;
public class RandomWalkers {
public static void main(String[] args) {
Random r = new Random();
Scanner sc = new Scanner(System.in);
System.out.print("请输入实验次数:");
int trials = sc.nextInt();
System.out.print("请输入参数n:");
int n = sc.nextInt();
double distances = 0;
for (int i = 0; i < trials; i++) {
int length = 0;
int width = 0;
for (int j = 0; j < n; j++) {
int chosen = r.nextInt(4) + 1;
switch (chosen) {
case 1 -> length++;
case 2 -> length--;
case 3 -> width++;
case 4 -> width--;
}
}
double distance = Math.sqrt((length * length) + (width * width));
distances += distance;
}
double average = (double) distances / trials;
System.out.println("距离的平均值为" + average);
}
}