场景故事3 点名与大奖 3.1 场景故事 小明上课的教室里一共有两个班,其中一班有30名同学、二班有33名同学。小明 发现老师每次按学号分别在两个班点名6位不同的同学,并且老师每次都是简单地看一 下她的计算机,就能快速、随意地说出6个不同的学号。老师点名现场如图3.1所示。 图3.1 老师点名现场 课程快结束时,小明好奇地问老师:“老师,我发现您的记忆力非常好。您 可以在一班或二班快速、随意地说出6个学号,而且能保证6个学号互不相同。若是 您想要点名20名学生,即快速、随意地说出20个学号,也能保证这20个学号是不同 的吗?您是怎么做到的呢?” 老师笑着对小明说:“我每次点名时,都是用余光看着计算机显示器的屏 幕,是我用自己编写的一个点名程序,来保证从班级里抽取6个不同的学号 。” 小明向老师要了源代码,决定认真研究一下,准备写一个模拟福利彩票抽奖 的程序。小明发现,这学期有12位给自己上课的老师,决定分别给这些老师编号为 1~12。如果是10号老师上课,就设篮球号码是10;然后用自己编写的Java程序随机 场 景 故 事 点名与大奖 3 10 趣懂Java旋律,击破36个难点 得到1~33中的6个数,作为红球号码,再与福利彩票开奖后的大奖做比对,看看自 己的Java程序能否得大奖。 本故事纯属虚构,如有雷同,纯属巧合。 3.2 场景故事的目的 1. 侧重点 java.util包(Java工具包)中的Arrays类提供了许多static方法,可以用类名 Arrays直接调用这些方法。 通过该场景学习Arrays类提供的复制数组和判断数组相等的方法。 (1)数组的复制。 public static int[] copyOfRange(int[] original, int from, int to) copyOfRange()方法可以把参数original指定的数组中从索引from至to-1的元素复 制到一个新数组中,并返回这个新数组,即新数组的长度为to-from。如果to的值 大于数组original的长度,则新数组的元素从索引original.length-from开始的元素取 默认值。 比如,对于数组a: int [] a = {1,2,3,4,5,6}; ① 复制数组a的部分元素,得到一个新的数组b: int [] b = Arrays.copyOfRange(a,1,4); 那么,数组b的长度即b.length的值是3。b[0]的值是2, b[1]的值是3, b[2]的值是4。 ② 复制数组a的部分元素,得到另一个新的数组: int [] c = Arrays.copyOfRange(a,4,10); 那么,数组c的长度即c.length的值是6。c[0]的值是5,c[1]的值是6,c[2]至c[5]的值 都是0。 (2)数组的相等判断。 有时需要判断两个类型相同的数组的值是否相同,即二者的长度一样且对应 场景故事3 点名与大奖11 的元素值也相同。 public static boolean equals(int[] a,int[] b)方法可以判断int型数组a和数组b是否 相等(类似的方法还有double、char、byte型数组的equals()方法)。当数组a和数 组b相等时,该方法返回true;否则返回false。 比如,在编写标准化考试的程序时,将标准答案(多选题)如ABD存放在一 个数组里,代码如下: char [] answer = {'A','B','D'};(也许某个开发者写成{'B','A','D'};) 考试者即用户提交的答案数组是: char [] user = {'B','D','A'}; 或 char [] user = {'B','A'}; 那么,怎样使用equals()方法给用户判定成绩呢?换言之,在某些应用中,只要两 个数组长度一样,含有的数据也一样,就认为二者相等,而不要求两个数组的元 素按索引顺序依次相同。一个简单的办法就是把二者都排序,代码如下: Arrays.sort(answer); Arrays.sort(user); 然后再使用boolean equals(char []a,char[] b)方法,代码如下: boolean isRight = Arrays.equals(answer,user); 得到一个值isRight,再根据isRight是true或false判断用户提交的数组和标准答案的 数组是否相等,然后决定给多少分。 2. 涉及的其他知识点 java.util包中的Random类以及for循环语句。 3. 进一步的尝试 从不连续的若干个数字中随机抽取若干个数。例如,从1、2、5、8、10、 14、23、30中随机抽取6个数字。 12 趣懂Java旋律,击破36个难点 3.3 程序运行效果与视频讲解 老师分别在一班和二班随机提问6名同学。主类是ExtractNumber。程序运行效 果如图3.2所示。 图3.2 点名与大奖的程序运行效果 3.4 阅读源代码 (1)GetRandomNumber.java的代码如下: import java.util.Random; //负责得到随机数 import java.util.Arrays; public class GetRandomNumber { public static int [] getRandomNumber(int max,int amount) { int [] result = new int[amount<max?amount:max]; //存放得到的amount随机数 int [] a = new int[max]; //存放max个整数 Random random = new Random(); for(int i = 0;i<a.length;i++){ //将1至max个数放入数组a a[i] = i+1; } for(int i =0;i<amount;i++) { //得到amount个随机数 int index = random.nextInt(a.length); //随机得到数组的一个索引值 result[i] = a[index]; int [] b = Arrays.copyOfRange(a,0,index); //数组b存放的是a[0]至a[index-1] int [] c = Arrays.copyOfRange(a,index+1,a.length); //数组复制 a = new int[b.length+c.length]; //新的数组a中去掉了抽到的数字 视频讲解 场景故事3 点名与大奖13 for(int k=0;k<a.length;k++) { if(k<b.length) a[k] = b[k]; else a[k] = c[k-b.length]; } } return result; } } (2)ExtractNumber.java的代码如下: import java.util.Arrays; public class ExtractNumber { public static void main(String args[]) { int [] a =GetRandomNumber.getRandomNumber(30,6); System.out.println("一班被抽到的回答问题的学号:"); System.out.println(Arrays.toString(a)); int [] b =GetRandomNumber.getRandomNumber(33,6); System.out.println("二班被抽到的回答问题的学号:"); System.out.println(Arrays.toString(b)); Arrays.sort(a); Arrays.sort(b); boolean isSame =Arrays.equals(a,b); System.out.println("两个班抽取的学号相同吗?"+isSame); } }