方法

方法的定义

方法是程序中最小的执行单元。

main() 方法也叫主方法。

方法必须先定义,然后才能调用。

方法的定义要写在 main() 的外面,类的里面。main() 也是方法,方法不能嵌套定义。

方法的编写顺序和执行顺序无关,执行顺序要根据调用顺序来看。

方法名遵循小驼峰法。

方法与方法之间是平级关系,不能嵌套定义,谁在前谁在后无所谓,但是为了程序的可读性一般都是将 main() 方法写在第一个,表示程序的主入口。

不带返回值的方法返回值类型为 void,此时不要写 return 语句,如果写也行,但是只能是单独的一条 return 语句,后面不能跟别的内容,即 return;

定义方法的格式:

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

方法可以被一些东西修饰,比如访问权限修饰符,final,static 等。

最简单的方法的定义和调用:

public class Test {
    public static void main(String[] args) {
        greet();  // 调用自定义的方法
        greet();  // 再次调用自定义的方法
    }

    // 自定义一个方法
    public static void greet() {
        System.out.println("Hello");
        System.out.println("Good morning");
        System.out.println("Good day");
    }
}

执行结果:

Hello
Good morning
Good day
Hello
Good morning
Good day

程序示例:

public class Method {
    public static void main(String[] args) {
        System.out.println("m");
        method1();
        System.out.println("n");
        method2();
        System.out.println("k");
    }

    public static void method1() {
        System.out.println("a");
        System.out.println("b");
        method2();
        System.out.println("u");
    }

    public static void method2() {
        System.out.println("d");
        System.out.println("c");
    }
}

执行结果:

m
a
b
d
c
u
n
d
c
k

程序示例:

public class Method {
    public static void main(String[] args) {
        getSum();
    }

    public static void getSum() {
        int a = 10;
        int b = 20;
        System.out.println(a + b);
    }
}

执行结果:

30

带参数的方法:

形参:形式参数,是方法定义中所用参数。

实参:实际参数,是方法调用中所用参数。

实参的个数必须和形参保持一致。

程序示例:

public class Method {
    public static void main(String[] args) {
        getSum(10, 20);
    }

    public static void getSum(int a, int b) {
        System.out.println(a + b);
    }
}

执行结果:

30

如果实参能通过自动类型转换为形参类型,也是可以传递参数的。例如下面的程序将 float 和 int 类型的实参转换为 double 类型的形参。

public class Method {
    public static void main(String[] args) {
        System.out.println(getSum(10.0F, 20));
    }

    public static double getSum(double a, double b) {
        return a + b;
    }
}

执行结果:

30.0

程序示例:

// 计算长方形的面积
import java.util.Scanner;

public class Method {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("输入长方形的长: ");
        int length = sc.nextInt();
        System.out.print("输入长方形的宽: ");
        int weight = sc.nextInt();
        System.out.println("长方形的面积为" + getArea(length, weight));
    }

    public static int getArea(int a, int b) {
        return a * b;
    }
}

执行结果:

输入长方形的长: 3
输入长方形的宽: 4
长方形的面积为12

带返回值的方法:

直接调用,不对返回值做任何处理:

方法名(实参);

赋值调用:

数据类型 变量 = 方法名(实参);

输出调用:

System.out.println(方法名(实参));

程序示例:

public class Method {
    public static void main(String[] args) {
        System.out.println(getSum(10, 20));
    }

    public static int getSum(int a, int b) {
        return a + b;
    }
}

执行结果:

30

方法定义中的返回类型和实际 return 的计算结果的类型不同时,允许自动类型转换,即 return 的结果自动类型转换到方法定义中的指定返回值类型,最终的返回值的类型以方法定义中指定的类型为准。

例如,下面的程序中 return 语句的结果为 int 类型,但是方法定义指定了返回类型为 double 类型,最终方法返回的类型为 double,因为将 int 自动转换为 double 了。

// 计算长方形的面积

import java.util.Scanner;

public class Method {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("输入长方形的长: ");
        int length = sc.nextInt();
        System.out.print("输入长方形的宽: ");
        int weight = sc.nextInt();
        System.out.println("长方形的面积为" + getArea(length, weight));
    }

    public static double getArea(int a, int b) {
        return a * b;
    }
}

执行结果:

输入长方形的长: 3
输入长方形的宽: 4
长方形的面积为12.0

方法的重载

方法的重载:在同一个类中定义了多个同名的方法,功能都相同或类似,但是形参列表不同,可以是类型不同或者是个数不同或者顺序不同,只要有一个不同就可以。

方法的重载与返回值无关。

构成重载的方法必须是同一个类中的,不同的类中的同名方法不构成重载。

不建议书写仅有形参顺序不同的重载函数。

程序示例:

public class Test {
    public static void main(String[] args) {
        fun(1.0, 2, 3);
        // fun(1, 2, 3);  // 报错: Ambiguous method call
    }

    public static void fun(int a, int b, double c) {
        System.out.println("第一个重载方法");
    }

    public static void fun(double a, int b, int c) {
        System.out.println("第二个重载方法");
    }
}

执行结果:

第二个重载方法

这里是构成重载关系的,但是不建议这样写。

程序示例:

// 需求: 使用方法重载的思想, 设计比较两个整数是否相同的方法. 
// 要求: 兼容全整数类型 (byte, short, int, long)

public class Method {
    public static void main(String[] args) {
        byte m1 = 1, n1 = 2;
        System.out.println(compare(m1, n1));
        short m2 = 1, n2 = 2;
        System.out.println(compare(m2, n2));
        int m3 = 1, n3 = 2;
        System.out.println(compare(m3, n3));
        long m4 = 1, n4 = 2;
        System.out.println(compare(m4, n4));
    }

    public static boolean compare(byte a, byte b) {
        System.out.println("调用byte类型方法");
        return a == b;
    }

    public static boolean compare(short a, short b) {
        System.out.println("调用short类型方法");
        return a == b;
    }

    public static boolean compare(int a, int b) {
        System.out.println("调用int类型方法");
        return a == b;
    }

    public static boolean compare(long a, long b) {
        System.out.println("调用long类型方法");
        return a == b;
    }
}

执行结果:

调用byte类型方法
false
调用short类型方法
false
调用int类型方法
false
调用long类型方法
false

程序示例:

// 需求: 设计一个方法用于数组遍历, 要求遍历的结果是在一行上的. 例如: [11, 22, 33, 44, 55]

public class Exercise1 {
    public static void main(String[] args) {
        int[] nums = {11, 22, 33, 44, 55};
        traverse(nums);
    }

    public static void traverse(int[] strings) {
        System.out.print("[");
        for (int i = 0; i < strings.length; i++) {
            if (i == strings.length - 1)
                System.out.print(strings[i]);
            else System.out.print(strings[i] + ", ");
        }
        System.out.println("]");
    }
}

执行结果:

[11, 22, 33, 44, 55]

或者:

// 需求: 设计一个方法用于数组遍历, 要求遍历的结果是在一行上的. 例如: [11, 22, 33, 44, 55]

public class Test {
    public static void main(String[] args) {
        int[] nums = {11, 22, 33, 44, 55};
        traverse(nums);
    }

    public static void traverse(int[] nums) {
        System.out.print("[");
        for (int i = 0; i < nums.length; i++) {
            if (i == nums.length - 1) {
                System.out.print(nums[i] + "]");
            } else {
                System.out.print(nums[i] + ", ");
            }
        }
    }
}

或者:

// 需求: 设计一个方法用于数组遍历, 要求遍历的结果是在一行上的. 例如: [11, 22, 33, 44, 55]
import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] nums = { 11, 22, 33, 44, 55 };
        System.out.println(Arrays.toString(nums));
    }
}

程序示例:

// 需求: 设计一个方法求数组的最大值, 并将最大值返回

public class Exercise1 {
    public static void main(String[] args) {
        int[] nums = {11, 22, 33, 44, 55};
        System.out.println("数组最大值为 " + getMax(nums));
    }

    public static int getMax(int[] arr) {
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            max = max > arr[i] ? max : arr[i];
        }
        return max;
    }
}

执行结果:

数组最大值为 55

程序示例:

// 定义一个方法判断数组中的某一个数是否存在, 将结果返回

import java.util.Scanner;

public class Exercise1 {
    public static void main(String[] args) {
        int[] nums = {11, 22, 33, 44, 55};
        Scanner sc = new Scanner(System.in);
        System.out.print("输入要寻找的数: ");
        int find = sc.nextInt();
        System.out.println("要寻找的数的索引为: " + getIndex(nums, find));
    }

    public static int getIndex(int[] arr, int n) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == n)
                return i;
        }
        return -1;
    }
}

执行结果:

输入要寻找的数: 22
要寻找的数的索引为: 1

程序示例:

// 需求: 
// 功能: 
// 定义一个方法 copyOfRange(int[] arr, int from, int to)
// 将数组 arr 中从索引 from (包含 from) 开始, 
// 到索引 to 结束 (不包含 to) 的元素复制到新数组中, 
// 将新数组返回. 

import java.util.Scanner;

public class Exercise1 {
    public static void main(String[] args) {
        int[] nums = {0, 11, 22, 33, 44, 55, 66, 77, 88, 99};
        Scanner sc = new Scanner(System.in);
        System.out.print("输入要复制的起始索引: ");
        int start = sc.nextInt();
        System.out.print("输入要复制的终止索引: ");
        int end = sc.nextInt();
        int[] newNums = copyOfRange(nums, start, end);
        System.out.println("复制出来的数组为: ");
        for (int i = 0; i < newNums.length; i++) {
            System.out.print(newNums[i] + "  ");
        }
    }

    public static int[] copyOfRange(int[] arr, int from, int to) {
        int[] newArr = new int[to - from];
        for (int i = 0, j = from; i < newArr.length; i++, j++) {
            newArr[i] = arr[j];
        }
        return newArr;
    }
}

执行结果:

输入要复制的起始索引: 1
输入要复制的终止索引: 6
复制出来的数组为: 
11  22  33  44  55

方法占用的内存分析

方法刚开始执行时要进栈,执行完了后立刻出栈。栈的特点:先进后出。

引用数据类型的变量,存储的是地址值。引用指的是使用了其他空间的数据。

基本数据类型的值是存储在自己的空间当中的。

基本数据类型的变量都是在栈中,引用数据类型的变量的实际内容是在堆中。

传递基本数据类型时传递的是真实的数据,形参的改变不会影响实参,除非用返回值的形式修改原来的值。

  • 基本数据类型:数据值是存储在自己的空间中。
    特点:赋值给其他变量,也是赋的真实的值。

  • 引用数据类型:数据值是存储在其他空间中,自己空间中存储的是地址值。
    特点:赋值给其他变量,赋的地址值。

程序示例:

// 值传递

public class Exercise1 {
    public static void main(String[] args) {
        int number = 100;
        System.out.println(number);    // 100
        change(number);
        System.out.println(number);    // 100
    }

    public static void change(int number) {
        number = 200;
    }
}

传递引用数据类型时传递的是地址值,形参的改变会影响实参的值。

程序示例:

// 引用传递

public class Exercise1 {
    public static void main(String[] args) {
        int[] number = {10, 20, 30};
        System.out.println(number[0]);    // 10
        change(number);
        System.out.println(number[0]);    // 200
    }

    public static void change(int[] number) {
        number[0] = 200;
    }
}

练习题 1

// 需求: 
// 机票价格按照淡季旺季, 头等舱和经济舱收费, 输入机票原价, 月份和头等舱或经济舱. 
// 按照如下规则计算机票价格: 旺季 (5-10 月) 头等舱 9 折, 经济舱 8.5 折, 淡季 (11 月到来年 4 月) 头等舱 7 折, 经济舱 6.5 折. 

import java.util.Scanner;

public class Exercise2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入机票原价: ");
        int original_Price = sc.nextInt();
        System.out.print("请输入月份: ");
        int month = sc.nextInt();
        System.out.print("请输入是头等舱还是经济舱: ");
        String seat = sc.next();
        double discounted_Price;
        if (month >= 5 && month <= 10) {
            if (seat.equals("头等舱"))
                discounted_Price = 0.9 * original_Price;
            else discounted_Price = 0.85 * original_Price;
        } else {
            if (seat.equals("头等舱"))
                discounted_Price = 0.7 * original_Price;
            else discounted_Price = 0.65 * original_Price;
        }
        System.out.println("机票的折扣价为: " + discounted_Price);
    }
}

执行结果:


请输入机票原价: 100
请输入月份: 5
请输入是头等舱还是经济舱: 头等舱
机票的折扣价为: 90.0

改写代码:

// 需求: 
// 机票价格按照淡季旺季, 头等舱和经济舱收费, 输入机票原价, 月份和头等舱或经济舱. 
// 按照如下规则计算机票价格: 旺季 (5-10 月) 头等舱 9 折, 经济舱 8.5 折, 淡季 (11 月到来年 4 月) 头等舱 7 折, 经济舱 6.5 折. 

import java.util.Scanner;

public class Exercise2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入机票原价: ");
        int original_Price = sc.nextInt();
        System.out.print("请输入月份: ");
        int month = sc.nextInt();
        System.out.print("请输入是头等舱还是经济舱: ");
        String seat = sc.next();
        double discounted_Price;
        if (month >= 5 && month <= 10) {
            discounted_Price = getDiscounted_price(original_Price, seat, 0.9, 0.85);
        } else {
            discounted_Price = getDiscounted_price(original_Price, seat, 0.7, 0.65);
        }
        System.out.println("机票的折扣价为: " + discounted_Price);
    }

    private static double getDiscounted_price(int original_Price, String seat, double v1, double v2) {
        double discounted_Price;
        if (seat.equals("头等舱"))
            discounted_Price = v1 * original_Price;
        else discounted_Price = v2 * original_Price;
        return discounted_Price;
    }
}

练习题 2

// 需求: 判断 101 - 200 之间有多少个素数, 并输出所有的素数

public class Exercise2 {
    public static void main(String[] args) {
        int start = 101;
        int end = 200;
        int count = 0;
        System.out.println("从" + start + "到" + end + "的所有素数为: ");
        for (int i = start; i <= end; i++) {
            if (isPrime(i)) {
                ++count;
                System.out.print(i + "\t");
            }
        }
        System.out.println("\n从" + start + "到" + end + "有" + count + "个素数. ");
    }

    public static boolean isPrime(int num) {
        for (int i = 2; i * i <= num; i++)
            if (num % i == 0)
                return false;
        return true;
    }
}

执行结果:

从101到200的所有素数为: 
101        103        107        109        113        127        131        137        139        149        151        157        163        167        173        179        181        191        193        197        199        
从101到200有21个素数. 

练习题 3

// 需求:
// 定义方法实现随机产生一个 5 位的验证码
// 验证码格式:
// 长度为 5
// 前四位是大写字母或者小写字母
// 最后一位是数字

import java.util.Random;

public class Test {
    public static void main(String[] args) {
        // 如果想要在一堆没有什么规律的数据中随机抽取,
        // 可以先把这些数据放到数组中,
        // 数组的索引是有规律的, 再随机抽取一个索引

        // 将大写字母和小写字母放到数组中
        char[] chs = new char[52];
        for (int i = 0; i < chs.length; i++) {
            if (i < 26) {
                chs[i] = (char) ('a' + i);
            } else {
                chs[i] = (char) ('A' + i - 26);
            }
        }

        // 定义一个字符串类型的变量, 用来记录最终的结果
        String result = "";

        // 随机抽取四次
        // 随机抽取数组的索引
        Random r = new Random();
        for (int i = 0; i < 4; i++) {
            int randomIndex = r.nextInt(chs.length);
            // 利用随机索引, 获取对应的元素
            result += chs[randomIndex];
        }

        // 抽取随机数字 0~9
        int number = r.nextInt(10);

        // 生成最终结果
        result += number;

        System.out.print(result);
    }
}

粗略一点写:

// 需求: 
// 定义方法实现随机产生一个 5 位的验证码
// 验证码格式: 
// 长度为 5
// 前四位是大写字母或者小写字母
// 最后一位是数字

import java.util.Random;

public class Exercise2 {
    public static void main(String[] args) {
        char[] arr = new char[52];
        for (int i = 0; i < 26; i++)
            arr[i] = (char) ('a' + i);
        for (int i = 26; i < 52; i++)
            arr[i] = (char) ('A' + i - 26);
        Random r = new Random();
        String verificationCode = "";                           // 用字符串存储验证码
        for (int i = 0; i <= 3; i++)
            verificationCode += arr[r.nextInt(arr.length)];     // 字符串拼接
        verificationCode += r.nextInt(10);                      // 数字拼接到字符串
        System.out.println(verificationCode);
    }
}

另一种写法:

// 需求: 
// 定义方法实现随机产生一个 5 位的验证码
// 验证码格式: 
// 长度为 5
// 前四位是大写字母或者小写字母
// 最后一位是数字

import java.util.Random;

public class Exercise2 {
    public static void main(String[] args) {
        char[] arr = new char[52];
        for (int i = 0; i < 26; i++)
            arr[i] = (char) ('a' + i);
        for (int i = 26; i < 52; i++)
            arr[i] = (char) ('A' + i - 26);
        char[] nums = new char[10];
        for (int i = 0; i < 10; i++)
            nums[i] = (char) (i + '0');         // 将数字转为字符
        Random r = new Random();
        char[] verificationCode = new char[5];  // 用字符数组存储验证码
        for (int i = 0; i <= 3; i++)
            verificationCode[i] = arr[r.nextInt(arr.length)];
        verificationCode[4] = nums[r.nextInt(nums.length)];
        System.out.println(verificationCode);  // 字符数组用这个方式打印, 结果是数组内容, 而不是地址, 别的类型的数组, 用这个方式打印, 将显示地址
    }
}

执行结果:

OiKA1

练习题 4

// 需求: 把一个数组中的元素复制到另一个新数组中去. 

public class Exercise2 {
    public static void main(String[] args) {
        // 老数组
        int[] nums = {1, 2, 3, 4, 5};
        System.out.println("老数组: ");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + "\t");
        }
        int[] newNums = new int[nums.length];
        for (int i = 0; i < newNums.length; i++) {
            newNums[i] = nums[i];
        }
        System.out.println("\n新数组: ");
        for (int i = 0; i < newNums.length; i++) {
            System.out.print(newNums[i] + "\t");
        }
    }
}

执行结果:

老数组: 
1        2        3        4        5        
新数组: 
1        2        3        4        5

练习题 5

// 需求: 在唱歌比赛中, 有 6 名评委给选手打分, 分数范围是 [0-100] 之间的整数. 选手的最后得分为: 去掉最高分, 最低分后的 4 个评委的平均分, 请完成上述过程并计算出选手的得分. 

import java.util.Scanner;

public class Exercise2 {
    public static void main(String[] args) {
        int[] scores = creatScores();
        int max = getMax(scores);
        int min = getMin(scores);
        int sum = getSum(scores);
        int avg = (sum - max - min) / (scores.length - 2);
        System.out.println("选手的得分为: " + avg);
    }

    public static int[] creatScores() {
        Scanner sc = new Scanner(System.in);
        int[] scores = new int[6];
        for (int i = 0; i < scores.length; ) {
            System.out.print("请输入评委打分: ");
            int score = sc.nextInt();
            if (score >= 0 && score <= 100) {
                scores[i] = score;
                ++i;
            } else System.out.println("输入的分数不在范围内, 请重新输入. ");
        }
        return scores;
    }

    public static int getMax(int[] arr) {
        int max = arr[0];
        for (int i = 0; i < arr.length; i++)
            max = max > arr[i] ? max : arr[i];
        return max;
    }

    public static int getMin(int[] arr) {
        int min = arr[0];
        for (int i = 0; i < arr.length; i++)
            min = min < arr[i] ? min : arr[i];
        return min;
    }

    public static int getSum(int[] arr) {
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum;
    }
}

执行结果:

请输入评委打分: 100
请输入评委打分: 90
请输入评委打分: 80
请输入评委打分: 70
请输入评委打分: 60
请输入评委打分: 50
选手的得分为: 75

练习题 6

// 需求:
// 某系统的数字密码 (大于 0), 比如 1983, 采用加密方式进行传输.
// 规则如下: 先得到每位数, 然后每位数都加上 5 然后对 10 求余, 最后将所有数字反转, 得到一串新数.

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        System.out.print("输入原始密码: ");
        Scanner sc = new Scanner(System.in);
        int passWd = sc.nextInt();
        int newPassWd = 0;
        while (passWd != 0) {
            int n = passWd % 10;
            n += 5;
            n %= 10;
            passWd = passWd / 10;
            newPassWd = newPassWd * 10 + n;
        }
        System.out.println("新密码为: " + newPassWd);
    }
}

执行结果:

输入原始密码: 1983
新密码为: 8346

将上述加密过程进行解密:


图 1
// 需求: 将上述加密过程进行解密

import java.util.Scanner;

public class Exercise2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("输入新密码: ");
        int newPasswd = sc.nextInt();
        int n;
        int passwd = 0;
        while (newPasswd != 0) {
            n = newPasswd % 10;
            newPasswd /= 10;
            if (n >= 0 & n <= 4)
                n += 10;
            n -= 5;
            passwd = passwd * 10 + n;
        }
        System.out.println("原始密码为: " + passwd);
    }
}

执行结果:

输入新密码: 8346
原始密码为: 1983

练习题 7

需求:一个大 V 直播抽奖,奖品是现金红包,分别有 {2, 588, 888, 1000, 10000} 五个奖金,请使用代码模拟抽奖,打印出每个奖项,奖项的出现顺序要随机且不重复,打印效果如下:(随机顺序,不一定是下面的顺序)


图 2
import java.util.Random;

public class Exercise2 {
    public static void main(String[] args) {
        int[] arr = {2, 588, 888, 1000, 10000};         // 奖池
        int[] exist = new int[arr.length];              // 存储已经被抽走的奖项
        int existIndex = 0;
        Random r = new Random();
        for (int j = 0; j < arr.length; ) {
            int index = r.nextInt(arr.length);          // 生成一个随机索引
            int n = arr[index];                         // 随机抽到的奖项
            boolean in = false;
            for (int i = 0; i < exist.length; i++) {    // 检查该奖项是否已经被抽走
                if (exist[i] == n) {
                    in = true;
                    break;
                }
            }
            if (!in) {                                  // 该奖项仍存在于奖池中
                System.out.println(n + "元的奖金被抽出. ");
                exist[existIndex++] = n;                // 将该奖项标记为已经抽走了
                ++j;                                    // 开始抽下一个奖
            }
        }
    }
}

执行结果:

888元的奖金被抽出. 
1000元的奖金被抽出. 
2元的奖金被抽出. 
588元的奖金被抽出. 
10000元的奖金被抽出. 

优化的写法:

// 需求: 
// 一个大 V 直播抽奖, 奖品是现金红包, 分别有 {2, 588, 888, 1000, 10000} 五个奖金. 请使用代码模拟抽奖, 
// 打印出每个奖项, 奖项的出现顺序要随机且不重复. 打印效果如下: (随机顺序, 不一定是下面的顺序)

import java.util.Random;

public class Exercise2 {
    public static void main(String[] args) {
        int[] arr = {2, 588, 888, 1000, 10000};         // 奖池
        int[] exist = new int[arr.length];              // 存储已经被抽走的奖项
        Random r = new Random();
        for (int i = 0; i < arr.length; ) {
            int index = r.nextInt(arr.length);          // 生成一个随机索引
            int n = arr[index];                         // 随机抽到的奖项
            boolean in = isIn(exist, n);
            if (!in) {                                  // 该奖项仍存在于奖池中
                System.out.println(n + "元的奖金被抽出. ");
                exist[i] = n;                           // 将该奖项标记为已经抽走了, exist 的索引和 arr 相同即可. 
                ++i;                                    // 开始抽下一个奖
            }
        }
    }

    // 判断一个数是否存在于一个数组中
    private static boolean isIn(int[] exist, int n) {
        for (int i = 0; i < exist.length; i++)          // 检查该奖项是否已经被抽走
            if (exist[i] == n)
                return true;
        return false;
    }
}

另一种写法:

import java.util.Random;

public class Test {
    public static void main(String[] args) {
        int[] arr = {2, 588, 888, 1000, 10000};          // 奖池
        int[] newArr = new int[arr.length];              // 存储已经被抽走的奖项
        Random r = new Random();
        for (int i = 0; i < 5; ) {
            int index = r.nextInt(arr.length);
            boolean flag = contains(newArr, arr[index]);
            if (!flag) {
                newArr[i] = arr[index];
                ++i;
            }
        }
        for (int i = 0; i < newArr.length; i++) {
            System.out.println(newArr[i] + "元的奖金被抽出.");
        }
    }

    // 判断一个元素在一个数组中是否存在, 若存在, 则返回 true
    public static boolean contains(int[] arr, int ele) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == ele) {
                return true;
            }
        }
        return false;
    }
}

上面的写法效率太低了,比如最后一次抽取的时候,必须要抽取到前面从来都没有抽取到的那一个元素,这个概率是很低的。

优化:只需要打乱原来的奖池即可。

代码:

import java.util.Random;

public class Exercise2 {
    public static void main(String[] args) {
        int[] prices = {2, 588, 888, 1000, 10000};
        Random r = new Random();
        for (int i = 0; i < prices.length; i++) {
            int index = r.nextInt(prices.length);
            int tmp = prices[i];
            prices[i] = prices[index];
            prices[index] = tmp;
        }
        for (int i = 0; i < prices.length; i++) {
            System.out.println(prices[i] + "元的奖金被抽出. ");
        }
    }
}

练习题 8

投注号码由 6 个红色球号码和 1 个蓝色球号码组成,红色球号码从 1-33 中选择,蓝色球号码从 1-16 中选择,红色球之间不能重复,蓝色的号码可以与红色的号码相同。


图 3
import java.util.Random;
import java.util.Scanner;

public class Exercise2 {
    public static void main(String[] args) {
        int[] winningNum = createNumbers();
        System.out.println("中奖号码为: ");
        for (int i = 0; i < winningNum.length; i++) {
            System.out.print(winningNum[i] + "  ");
        }
        System.out.println();
        int[] buyNum = buy();
        System.out.println("顾客买的号码为: ");
        for (int i = 0; i < buyNum.length; i++) {
            System.out.print(buyNum[i] + "  ");
        }
        int redCount = 0, blueCount = 0;
        for (int i = 0; i < winningNum.length - 1; i++) {
            for (int j = 0; j < buyNum.length - 1; j++) { // 这里不能直接调用 isIn 方法, 因为蓝球号码可以和红球相同
                if (winningNum[i] == buyNum[j]) {
                    ++redCount;
                    break;
                }
            }
        }
        if (winningNum[6] == buyNum[6])
            ++blueCount;
        System.out.println("\n红球中了 " + redCount + " 个. ");
        System.out.println("蓝球中了 " + blueCount + " 个. ");

        // 输出中奖情况
        if (redCount == 6 && blueCount == 1)
            System.out.println("恭喜你, 中了一等奖, 奖金1000万. ");
        else if (redCount == 6 && blueCount == 0)
            System.out.println("恭喜你, 中了二等奖, 奖金500万. ");
        else if (redCount == 5 && blueCount == 1)
            System.out.println("恭喜你, 中了三等奖, 奖金3000元. ");
        else if (redCount == 5 && blueCount == 0)
            System.out.println("恭喜你, 中了四等奖, 奖金200元. ");
        else if (redCount == 4 && blueCount == 1)
            System.out.println("恭喜你, 中了四等奖, 奖金200元. ");
        else if (redCount == 4 && blueCount == 0)
            System.out.println("恭喜你, 中了五等奖, 奖金10元. ");
        else if (redCount == 3 && blueCount == 1)
            System.out.println("恭喜你, 中了五等奖, 奖金10元. ");
        else if (redCount == 2 && blueCount == 1)
            System.out.println("恭喜你, 中了六等奖, 奖金5元. ");
        else if (redCount == 1 && blueCount == 1)
            System.out.println("恭喜你, 中了六等奖, 奖金5元. ");
        else if (redCount == 0 && blueCount == 1)
            System.out.println("恭喜你, 中了六等奖, 奖金5元. ");
        else System.out.println("谢谢参与!!!");
    }

    // 中奖号码
    public static int[] createNumbers() {
        int[] arr = new int[7];
        Random r = new Random();
        for (int i = 0; i < 6; ) {
            int redNum = r.nextInt(33) + 1;
            boolean isIn = isIn(arr, redNum);
            if (!isIn) {
                arr[i] = redNum;
                ++i;
            }
        }
        int blueNum = r.nextInt(16) + 1;
        arr[6] = blueNum;
        return arr;
    }

    // 顾客买的号码
    public static int[] buy() {
        Scanner sc = new Scanner(System.in);
        int[] arr = new int[7];
        System.out.println("输入6个红球的号码: ");
        for (int i = 0; i < 6; ) {
            System.out.print("输入第 " + (i + 1) + " 个红球的号码: ");
            int redNum = sc.nextInt();
            if (redNum < 1 || redNum > 33)
                System.out.println("输入的球号错误, 重新输入. ");
            else {
                if (isIn(arr, redNum))
                    System.out.println("这个号码买重复了, 重新输入. ");
                else {
                    arr[i] = redNum;
                    ++i;
                }
            }
        }
        while (true) {
            System.out.print("输入蓝球的号码: ");
            int blueNum = sc.nextInt();
            if (blueNum < 1 || blueNum > 16)
                System.out.println("输入错误, 重新输入. ");
            else {
                arr[6] = blueNum;
                break;
            }
        }
        return arr;
    }


    // 判断一个数是否在一个数组中
    public static boolean isIn(int[] arr, int val) {
        for (int i = 0; i < arr.length; i++)
            if (arr[i] == val)
                return true;
        return false;
    }
}

执行结果:

中奖号码为: 
10  11  33  22  31  15  9  
输入6个红球的号码: 
输入第 1 个红球的号码: 10
输入第 2 个红球的号码: 11
输入第 3 个红球的号码: 22
输入第 4 个红球的号码: 33
输入第 5 个红球的号码: 31
输入第 6 个红球的号码: 15
输入蓝球的号码: 9
顾客买的号码为: 
10  11  22  33  31  15  9  
红球中了 6 个. 
蓝球中了 1 个. 
恭喜你, 中了一等奖, 奖金1000万. 
posted @ 2026-04-06 10:58  YouKong  阅读(0)  评论(0)    收藏  举报