18-循环和判断的总结
0. 目录
- Java 中的单行注释
- 从标准输出读取字符串和整数
- 生成指定范围内的随机数
- 猜数字的游戏
1. Java 中的单行注释
- 以 // 为开始,到这一行结束都是注释内容
- 注释可以是任何内容
- 可以在一行的开始注释,也可以在程序内容后面添加注释
- 注释不会对程序有任何影响
2. 生成指定范围内的随机数
2.1 新功能
Math.random()
生成随机数,随机数在 0 到 1 之间,类型是 double
2.2 生成一个在指定范围内的随机正整数程序关键点
- 得到随机数,Java 支持得到的 0 到 1 的 double 类型的随机数
- 确定基本的数学方法
- 运用取模运算符
- 使用强制类型转换
- 确保生成的数字在指定的范围内。极限思维,假设随机数是 0 或者 1,结果是多少?假设取模后是 0 或者
mod-1
,结果会是多少? - 公式:
- link:https://www.yuque.com/aiyuechuang/el8tia/ggzcpx#IDwEC
Math.random()*(max-min+1)+min
public class RandomNumber {
public static void main(String[] args) {
double randNum = 0;
// 要生成一个大于 0.5 的随机数,只有随机数大于了 0.5,循环才会退出
while (randNum < 0.5) {
// 使用 Java 中的 Math.random(),生成一个随机数
randNum = Math.random();
System.out.println(randNum);
}
System.out.println("生成大于 0.5 的随机数是" + randNum);
}
}
输出:
0.0929249734521792
0.6482227349714997
生成大于 0.5 的随机数是0.6482227349714997
生成指定范围的随机数据:
public class Example {
public static void main(String[] args) {
double randNum = 0;
// 要生成一个大于 0.5 的随机数,只有随机数大于了 0.5,循环才会退出
while (randNum < 0.5) {
// 使用 Java 中的 Math.random(),生成一个随机数
randNum = Math.random();
System.out.println(randNum);
}
System.out.println("生成大于 0.5 的随机数是" + randNum);
int rangeStart = 30;
int rangeEnd = 90;
/*我们如何确保,生成的随机数是在我们的范围之内呢?
* 1、先把我们 Math.random() 生成的 0~1 之间的随机数,乘以一个足够大的值,比如:Math.random() * rangeEnd * 10
* 这样,这个值就不是从 0~1 了。就已经足够大,超出我们大范围
* 2、然后我们再取一个模,取一个什么模呢?——取 ranegStart、rangeEnd 差的模,
* 这个数再加上 rangeStart 那它肯定是从 rangeStart 到 rangeEnd 之间的,而且它也是随机数*/
// 取模
int mod = rangeEnd - rangeStart;
for (int i = 0; i < 50; i++) {
int bigRandom = (int) (Math.random() * rangeEnd * 100);
int numberToGuess = (bigRandom % mod) + rangeStart;
System.out.println("mod=" + mod + ", bigRandom=" + bigRandom);
System.out.println("mod=" + mod + ", numberToGuess=" + numberToGuess);
}
}
}
添加一个便捷判断:
public class Example {
public static void main(String[] args) {
double randNum = 0;
// 要生成一个大于 0.5 的随机数,只有随机数大于了 0.5,循环才会退出
while (randNum < 0.5) {
// 使用 Java 中的 Math.random(),生成一个随机数
randNum = Math.random();
System.out.println(randNum);
}
System.out.println("生成大于 0.5 的随机数是" + randNum);
int rangeStart = 30;
int rangeEnd = 90;
/*我们如何确保,生成的随机数是在我们的范围之内呢?
* 1、先把我们 Math.random() 生成的 0~1 之间的随机数,乘以一个足够大的值,比如:Math.random() * rangeEnd * 10
* 这样,这个值就不是从 0~1 了。就已经足够大,超出我们大范围
* 2、然后我们再取一个模,取一个什么模呢?——取 ranegStart、rangeEnd 差的模,
* 这个数再加上 rangeStart 那它肯定是从 rangeStart 到 rangeEnd 之间的,而且它也是随机数*/
// 取模
int mod = rangeEnd - rangeStart;
for (int i = 0; i < 50; i++) {
int bigRandom = (int) (Math.random() * rangeEnd * 100);
int numberToGuess = (bigRandom % mod) + rangeStart;
if (numberToGuess <= rangeStart) {
numberToGuess = rangeStart + 1;
} else if (numberToGuess > rangeEnd) {
numberToGuess = rangeEnd - 1;
}
System.out.println("mod=" + mod + ", bigRandom=" + bigRandom);
System.out.println("mod=" + mod + ", numberToGuess=" + numberToGuess);
}
}
}
很完善了?还没!
public class Example {
public static void main(String[] args) {
double randNum = 0;
// 要生成一个大于 0.5 的随机数,只有随机数大于了 0.5,循环才会退出
while (randNum < 0.5) {
// 使用 Java 中的 Math.random(),生成一个随机数
randNum = Math.random();
System.out.println(randNum);
}
System.out.println("生成大于 0.5 的随机数是" + randNum);
int rangeStart = 30;
int rangeEnd = 90;
/*我们如何确保,生成的随机数是在我们的范围之内呢?
* 1、先把我们 Math.random() 生成的 0~1 之间的随机数,乘以一个足够大的值,比如:Math.random() * rangeEnd * 10
* 这样,这个值就不是从 0~1 了。就已经足够大,超出我们大范围
* 2、然后我们再取一个模,取一个什么模呢?——取 ranegStart、rangeEnd 差的模,
* 这个数再加上 rangeStart 那它肯定是从 rangeStart 到 rangeEnd 之间的,而且它也是随机数*/
// 取模
int mod = rangeEnd - rangeStart;
if (mod <= 1) {
System.out.println("非法的数字范围:(" + rangeStart + "," + rangeEnd + ")");
// 对于非法的,我们并没有做什么事情,我们以后再说;
}
for (int i = 0; i < 50; i++) {
// if (rangeEnd-rangeStart>1){
//
// }
int bigRandom = (int) (Math.random() * rangeEnd * 100);
int numberToGuess = (bigRandom % mod) + rangeStart;
if (numberToGuess <= rangeStart) {
numberToGuess = rangeStart + 1;
} else if (numberToGuess > rangeEnd) {
numberToGuess = rangeEnd - 1;
}
System.out.println("mod=" + mod + ", bigRandom=" + bigRandom);
System.out.println("mod=" + mod + ", numberToGuess=" + numberToGuess);
}
}
}
因为,我们的是判断📄,所以需要添加大于 0 才是正常的:
public class Example {
public static void main(String[] args) {
double randNum = 0;
// 要生成一个大于 0.5 的随机数,只有随机数大于了 0.5,循环才会退出
while (randNum < 0.5) {
// 使用 Java 中的 Math.random(),生成一个随机数
randNum = Math.random();
System.out.println(randNum);
}
System.out.println("生成大于 0.5 的随机数是" + randNum);
int rangeStart = 30;
int rangeEnd = 90;
// int rangeEnd = 31;
/*我们如何确保,生成的随机数是在我们的范围之内呢?
* 1、先把我们 Math.random() 生成的 0~1 之间的随机数,乘以一个足够大的值,比如:Math.random() * rangeEnd * 10
* 这样,这个值就不是从 0~1 了。就已经足够大,超出我们大范围
* 2、然后我们再取一个模,取一个什么模呢?——取 ranegStart、rangeEnd 差的模,
* 这个数再加上 rangeStart 那它肯定是从 rangeStart 到 rangeEnd 之间的,而且它也是随机数*/
// 取模
int mod = rangeEnd - rangeStart;
if (rangeStart <0 || rangeEnd <0){
System.out.println("开始和结束必须是整数或者 0");
}
if (mod <= 1) {
System.out.println("非法的数字范围:(" + rangeStart + "," + rangeEnd + ")");
}
for (int i = 0; i < 50; i++) {
// if (rangeEnd-rangeStart>1){
//
// }
int bigRandom = (int) (Math.random() * rangeEnd * 100);
int numberToGuess = (bigRandom % mod) + rangeStart;
if (numberToGuess <= rangeStart) {
numberToGuess = rangeStart + 1;
} else if (numberToGuess > rangeEnd) {
numberToGuess = rangeEnd - 1;
}
System.out.println("mod=" + mod + ", bigRandom=" + bigRandom);
System.out.println("mod=" + mod + ", numberToGuess=" + numberToGuess);
}
}
}
public class RandomNumber {
public static void main(String[] args) {
double randNum = 0;
// 要生成一个大于 0.5 的随机数,只有随机数大于了 0.5,循环才会退出
while (randNum < 0.5) {
// 使用 Java 中的 Math.random(),生成一个随机数
randNum = Math.random();
System.out.println(randNum);
}
System.out.println("生成大于 0.5 的随机数是" + randNum);
int rangeStart = 99;
int rangeEnd = 180;
for (int i = 0; i < 100; i++) {
// 确定模
int mod = rangeEnd - rangeStart;
//生成随机数
randNum = Math.random();
// num 的值会在 0 到 mod-1,也就是 0 到 rangeEnd - rangeStart -1
int num = ((int) (randNum * rangeEnd * 100)) % mod;
// num 加 rangeStart 之后,值域是 0 到 rangeEnd - 1
num += rangeStart;
if (num <= rangeStart) {
num = rangeStart + 1;
}
// 根据数据分析,这个条件不会满足,只是为了做最后的防护
if (num >= rangeEnd) {
num = rangeEnd - 1;
}
System.out.println("这次的随机数是:" + num);
}
}
}
输出:
/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=54033:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/huangjiabao/GitHub/Java_Coder/Coder18/out/production/Coder18 RandomNumber
0.6599429274808525
生成大于 0.5 的随机数是0.6599429274808525
这次的随机数是:146
这次的随机数是:142
这次的随机数是:107
这次的随机数是:168
这次的随机数是:163
这次的随机数是:159
这次的随机数是:109
这次的随机数是:103
这次的随机数是:137
这次的随机数是:113
这次的随机数是:175
这次的随机数是:120
这次的随机数是:123
这次的随机数是:116
这次的随机数是:121
这次的随机数是:150
这次的随机数是:162
这次的随机数是:143
这次的随机数是:124
这次的随机数是:139
这次的随机数是:124
这次的随机数是:154
这次的随机数是:143
这次的随机数是:142
这次的随机数是:172
这次的随机数是:169
这次的随机数是:131
这次的随机数是:120
这次的随机数是:140
这次的随机数是:116
这次的随机数是:131
这次的随机数是:120
这次的随机数是:100
这次的随机数是:167
这次的随机数是:166
这次的随机数是:173
这次的随机数是:137
这次的随机数是:155
这次的随机数是:155
这次的随机数是:117
这次的随机数是:143
这次的随机数是:128
这次的随机数是:115
这次的随机数是:100
这次的随机数是:155
这次的随机数是:144
这次的随机数是:101
这次的随机数是:122
这次的随机数是:102
这次的随机数是:108
这次的随机数是:159
这次的随机数是:173
这次的随机数是:119
这次的随机数是:158
这次的随机数是:139
这次的随机数是:142
这次的随机数是:136
这次的随机数是:109
这次的随机数是:111
这次的随机数是:113
这次的随机数是:128
这次的随机数是:119
这次的随机数是:134
这次的随机数是:163
这次的随机数是:120
这次的随机数是:100
这次的随机数是:131
这次的随机数是:177
这次的随机数是:115
这次的随机数是:126
这次的随机数是:150
这次的随机数是:130
这次的随机数是:110
这次的随机数是:152
这次的随机数是:136
这次的随机数是:170
这次的随机数是:147
这次的随机数是:169
这次的随机数是:131
这次的随机数是:152
这次的随机数是:143
这次的随机数是:131
这次的随机数是:111
这次的随机数是:128
这次的随机数是:105
这次的随机数是:144
这次的随机数是:160
这次的随机数是:111
这次的随机数是:136
这次的随机数是:112
这次的随机数是:102
这次的随机数是:141
这次的随机数是:158
这次的随机数是:115
这次的随机数是:159
这次的随机数是:169
这次的随机数是:147
这次的随机数是:119
这次的随机数是:135
这次的随机数是:156
Process finished with exit code 0
写程序是一个比较复杂的过程,一般来说你写到某个阶段或者某个可以具体运行的代码的时候,这个时候就可以进行运行测试一下代码是否可以正常运行且达到预期效果。
3. 从标准输出读取字符串和整数
3.1 新功能
Scanner in = new Scanner(System.in)
连接标准输入,在我们例子里也就是命令行。in 也是变量,只是不是基本类型。in.nextLine()
可以从命令行读取一行字符串in.nextInt()
可以从命令行读取一个正整数「必须输入的是整数,不然是会报错的」- 点操作符也是 Java 中的操作符,和
System.out.println()
以及Math.random()
中的点是一样的操作符。是对点前面的“变量”进行点后面的“操作”。这里所谓的操作,就是指方法,也就是我们一直写的 main 方法的那个方法。这些操作都是使用一个个的的方法。使用方法我们叫做调用方法(invoke a method)。方法是 Java 中的重中之重,我们后面会用大篇幅讲解。 import java.util.Scanner;
是告诉程序,Scaner 这个类型在哪里。- 创建 Scanner 类型的“变量”,它就是我们提过的工具,可以帮我们从标准收入读取数据
nextLine()
和nextInt()
两个方法可以从命令行读取一行字符串或者一行字符串代表的整数
import java.util.Scanner; // 现阶段就直接使用即可。为什么要导入呢?——
// 因为,Scanner 的全名就叫 java.util.Scanner;
// 这样我们就不用每次都去写这么长,直接写 Scanner 就等价于 java.util.Scanner;
public class ReadStringAndIntFromConsole {
public static void main(String[] args) {
Scanner in = new Scanner(System.in); // 类似创建变量,后面会讲 new xxx,我们先不从语法层面去理解它。
// 从字面意思理解:System 是系统,系统的输入是什么呢?——系统输入我们就可以认为是键盘,
// 相当于我们用 Scanner 来处理用户输入键盘的数据。
System.out.println("请问你的名字是?");
String str = in.nextLine();
System.out.println(str + ",你好。");
System.out.println("请问你几岁了?");
int age = in.nextInt();
System.out.println("好的," + str + age + "岁了。");
}
}
4. 猜数字的游戏
4.1 善假于物也
- Random 方法和 readInt 方法是两个工具,可以完成一个明确具体的功能。「一个是生产随机数,一个是从命令行读取一个数」
4.2 游戏功能
- 猜数字:生成一个指定范围内的随机正整数,从命令行读取一个整数,如果和随机数相同,就算猜中。
- 固定随机数的范围
- 支持每次猜数字游戏的猜测次数,在指定次数内没猜对,则猜数字失败,否则就是成功。
- 可以支持退出游戏
- 输出剩余的猜测次数
- 每次猜测后,如果未猜中,则提示本次猜测的数字比目标数字大还是小
- 游戏结束后,输出猜数字游戏的统计
- 没有猜中,要输出这次的目标数字
- 可以设置随机数的范围,可以设置最大猜测次数。
import java.util.Scanner;
public class GuessNumber {
public static void main(String[] args) {
// 创建Scanner从控制台读取输入
Scanner in = new Scanner(System.in);
// 游戏设置
int rangeStart = 1; // 开始的范围
int rangeEnd = 8; // 结束的范围
int guessTotal = 5; // 一共能猜几次
// 游戏统计
int totalGameCount = 0; // 玩了多少次
int totalCorrectCount = 0; // 正确了多少次
// 是否结束游戏
boolean stopGame = false;
while (!stopGame) {
// 初始化本次游戏的变量
int guessLeft = guessTotal; // 允许的猜测次数
// -------生成随机数-------
int mod = rangeEnd - rangeStart;
double randNum = Math.random();
int num = ((int) (randNum * rangeEnd * 100)) % mod;
num += rangeStart;
if (num <= rangeStart) {
num = rangeStart + 1;
}
if (num >= rangeEnd) {
num = rangeEnd - 1;
}
// -------生成随机数-------
System.out.println("=================== 猜 数 字 ===================");
System.out.println("目标数已经生成,数字在" + rangeStart + "到" + rangeEnd + "之间," +
"不包括这两个数。共有" + guessTotal + "次猜测的机会。输入-1随时结束游戏。");
// 本次游戏是否开始了
boolean gameStart = true;
// 本次是否猜中数字
boolean guessCorrect = false;
while (guessLeft > 0) {
System.out.println("还有" + guessLeft + "次机会,请输入猜测的数字,回车确认");
int guessNum = in.nextInt();
// 输入-1,结束游戏
if (guessNum == -1) {
stopGame = true; // 修改主循环条件
break; // 用户跳出当前 while 循环
}
if (guessNum <= rangeStart || guessNum >= rangeEnd) {
System.out.println("请输入在" + rangeStart + "到" + rangeEnd + "之间,的数字,不包括这两个数。");
continue;
}
// 只要至少猜过一次,就算玩过了。
if (gameStart) {
totalGameCount++; // 直接 +1 也是可以的
gameStart = false; // 在多次循环中,玩了一次就足够了
}
// 可以用的猜测次数减1
guessLeft--;
if (guessNum == num) {
totalCorrectCount++;
guessCorrect = true;
System.out.println("恭喜你猜对了!这次的数字就是" + num +
"。本次你共猜了" + (guessTotal - guessLeft) + "次。");
break;
} else if (guessNum > num) {
System.out.println("猜测的数字比目标数字大。");
} else {
System.out.println("猜测的数字比目标数字小。");
}
}
if (!guessCorrect) {
System.out.println("本次的目标数字是" + num + "。这次没有猜中。");
}
}
System.out.println("共进行了" + totalGameCount + "次游戏,其中正确的为" + totalCorrectCount + "次");
}
}
学员提问
老师,为何
Math.random()*(rangeEnd - rangeStart) + rangeStart
的值阈是[rangeStart, rangeEnd)
呢?你说的那个公式我还是不太理解
讲师回复:Math.random()
是[0, 1)
所以Math.random()*(rangeEnd - rangeStart) + rangeStart
就是rangeStart + [0, 1) * (rangeEnd - rangeStart)
所以最小值就是 0 的时候,是rangeStart
,最大值不包含为 1 的时候,就是rangeEnd
所以是[rangeStart, rangeEnd)
Math.random 的注释:
- Returns a {@code double} value with a positive sign, greater
- than or equal to {@code 0.0} and less than {@code 1.0}.
在计算有余数的除法时,余数必须小于除数,如果余数大于等于除数,则商就应进一。直至余数小于除数。(小学数学)
余数一定小于除数(除数为 60)就是一定小于 60.
讲师回复:🉑️
其实也可以这样
int zuiXiao =20;
int zuiDa =40;
double suiJi= Math.random();
int Zhi =(int)(suiJi*(zuiDa-zuiXiao+1)+zuiXiao);
System.out.println(Zhi);
老师, 我想问一个问题, 就是比如说取一个80分以上的分数 可以
(int)(Math.random()*21)+80
朋友是这样的,因为 Math.random 是 0 到 1 随机 左闭又开,所以乘 21 是 0 到 21 左闭右开,强制转化成 int 类型就是0-20闭区间,所以是在80到100之间随机
感觉这个随机数的写法不是很好理解
作者回复: 这里为了使用更多的操作符,确实搞得有点复杂。可以参考这节课里别的同学的提问和我的回答。有些别的写法更简单。
老师好,我不太理解为什么在生成 rangeStart 到 rangeEnd 之间的随机数时,为什么不用
Math.random()*(rangeEnd - rangeStart) + rangeStart
这个公式呀?
这个公式看上去很简洁直接,也好理解。 在您的讲课视频里,您先用 Math.random() 产生的随机数乘以一个很大的数字,然后再用这个成倍放大过的随机数和(rangeEnd - rangeStart) 的结果做取模运算,然后再把结果加上 rangeStart。
我不太理解,在这里为什么要用到取模运算呢?取模运算的意义在哪里呢?为什么不直接用Math.random()*(rangeEnd - rangeStart) + rangeStart
生成想要区间内的随机数呢? 谢谢老师的解答,辛苦老师啦_
**作者回复: **
可以,稍微简单点可以这样写(int)(Math.random(rangeEnd - rangeStart) + 0.5) + rangeStart
,这个结果范围会是[rangeStart, rangeEnd)
我遇到的问题 错误: 找不到或无法加载主类 java.util.scanner 原因: java.lang.ClassNotFoundException: java.util.scanner 我的问题背景 Macos IDEA 2022.2.1 运行代码的时候提示无法加载主类,其他的代码都能正常运行 import java.util.Scanner; public class scanner { public static void main(String[] args) { Scanner in = new scanner(System.in); System.out.println("请问你的名字是?"); String str = in.nextLine(); System.out.println(str+ ",你好"); } }
作者回复:
- 建议把类名改一下比如改成MyScanner,如果你的代码完全如你贴出来的这样,应该会有问题,“Scanner in = new scanner(System.in);”,new scanner其实是创建了一个你自己的类的实例,这个是不能够赋值给Scanner的。
- 可以按照这篇FAQ配置一下JDK https://xie.infoq.cn/article/d76e5262dfde072780d414ff7
欢迎关注我公众号:AI悦创,有更多更好玩的等你发现!
公众号:AI悦创【二维码】
AI悦创·编程一对一
AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh
C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh
方法一:QQ
方法二:微信:Jiabcdefh
- 0
- 0
- 0
- 0
- 0
- 0