Java用n种方法编写实现双色球随机摇号案例
之前我用JavaScript编写过一个实现双色球随机摇号的案例,
点击此处查看,今天我再用Java语言来实现这一效果。
规则
那么首先我们要搞清楚规则是什么:
双色球投注区分为红球号码区和蓝球号码区
红球号码范围为01~33,蓝球号码范围为01~16
双色球每期从33个红球中开出6个号码,从16个蓝球中开出1个号码作为中奖号码
双色球玩法即是竞猜开奖号码的6个红球号码和1个蓝球号码,顺序不限
简单来说,就是通过随机,红球就是在1~33中随机出来6个互不相同的数字,蓝球则是产生一个1 ~16之间的数字。那么难点当然在于红球,如何确保不重复呢?
实现方式一
当然是用集合了,因为集合的性质就在于,里面的元素互不重复。接下来我们就用集合来实现:
package day_11_25;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
/**
* 双色球
* 红球1~33 篮球1~16
*
* @author soberw
*/
public class DoubleBall2 {
public static void main(String[] args) {
Random random = new Random();
Set<Integer> red = new HashSet<Integer>();
do {
red.add(random.nextInt(33) + 1);
} while (red.size() != 6);
System.out.print("{ ");
red.forEach((value) -> {
System.out.printf("[%02d] ", value);
});
System.out.print("}");
System.out.printf("{ [%02d] }", random.nextInt(16) + 1);
}
}
运行结果:

实现方式二
那么如果不用集合而用数组呢?我们都知道Java的数组比较死板,就是一旦定义,就不能再更改长度,而且在声明的时候一定要指定长度或者初始化值。那么如果想用数组实现呢,代码如下:
package day_11_25;
import java.util.Random;
/**
* 双色球
* 红球1~33 篮球1~16
*
* @author soberw
*/
public class DoubleBall3 {
public static void main(String[] args) {
Random random = new Random();
//放红球
int[] red = new int[6];
for (int i = 0; i < red.length; i++) {
boolean flag = true;
int redRAn = random.nextInt(33) + 1;
while (flag) {
for (int j = 0; j < red.length; j++) {
if (red[j] == redRAn) {
flag = false;
break;
}
}
if (flag) {
red[i] = redRAn;
break;
}
}
}
System.out.print("{ ");
for (int i : red) {
System.out.printf("[%02d] ", i);
}
System.out.print("}");
System.out.printf("{ [%02d] }", random.nextInt(16) + 1);
}
}
运行结果:

实现方式三
其实用数组的实现方式有很多,上面这种采用了三重循环嵌套,如果逻辑性不强,很难理解为什么这样子写,下面分享另一种写法,相比于上一种写法,这种的思路是创建一个基数数组base存放1~33所有的号码球,每次随机抽取出一个,然后将base 中对应号码球的赋值为0,每次抽取的时候都会先判断是不是为0,如果是0就说明已经被抽走了,那么就继续随机,直到不再重复为止。确保不会重复:
package day_11_25;
import java.util.Random;
/**
* 双色球
* 红球1~33 篮球1~16
*
* @author soberw
*/
public class DoubleBall {
public static void main(String[] args) {
Random ran = new Random();
//基数组,从这里抽数放入red
int[] base = new int[33];
//存放红球
int[] red = new int[6];
int ranIndex;
//给base元素依次赋值1~33
for (int i = 1; i <= base.length; i++) {
base[i - 1] = i;
}
for (int i = 0; i < red.length; i++) {
while (true) {
//随机base的下标
ranIndex = ran.nextInt(33);
//判断是不是被抽走了,被抽走了就继续随机,没有的话就放入red,并将base中对应的赋值为0
if (0 != base[ranIndex]) {
red[i] = base[ranIndex];
base[ranIndex] = 0;
break;
}
}
},
System.out.print("{ ");
for (int i : red) {
System.out.printf("[%02d] ", i);
}
System.out.print("}");
System.out.printf("{ [%02d] }", ran.nextInt(16) + 1);
}
}
运行结果:

实现方式四
当然我们也可以借助数组工具类Arrays中的二分查找方法 binarySearch()来判断是否已经存在,但是前提是必须在查找前先排序,因为二分查找的前提就是要确保数组是有序的:
package day_11_25;
import java.util.Arrays;
import java.util.Random;
/**
* 双色球
* 红球1~33 篮球1~16
*
* @author soberw
*/
public class DoubleBall4 {
public static void main(String[] args) {
Random random = new Random();
//放红球
int[] red = new int[6];
Arrays.fill(red,33);
//存放号码球
int ranRed;
for (int i = 0; i < red.length; i++) {
boolean flag = true;
//确保数组有序
Arrays.sort(red);
while (flag) {
ranRed = random.nextInt(33) + 1;
//判断数组中是否存在此元素
if (Arrays.binarySearch(red, ranRed) < 0) {
flag = false;
red[i] = ranRed;
}
}
}
System.out.print("{ ");
for (int i : red) {
System.out.printf("[%02d] ", i);
}
System.out.print("}");
System.out.printf("{ [%02d] }", random.nextInt(16) + 1);
}
}
运行结果:

这里需要注意一点,Arrays.binarySearch()方法如果找不到元素,返回的不是-1,而是一个小于0的数,这个数是多少呢,查看API手册得知:

我在使用的时候就栽过坑,让其等-1,结果陷入死循环。。。
实现方法五
那么上一个方法存在的问题就是,每次判断之前我还要对数组进行排序,虽然这是内置的算法不用我们自己在写了,但是总感觉还是有待优化一下。于是,就有了第五种方法:)
使用Vector类完成,它的优势在于,它是动态的,可以动态添加数据,最主要的是,它内置了超级多的方法,相比于原始数组的死板,实在是强大许多:
package day_11_25;
import java.util.Random;
import java.util.Vector;
/**
* 双色球
* 红球1~33 篮球1~16
*
* @author soberw
*/
public class DoubleBall5 {
public static void main(String[] args) {
Random random = new Random();
//声明一个空数组用于存放红球
Vector<Integer> red = new Vector<Integer>();
//超出六个退出
while (red.size() < 6) {
int ranRed = random.nextInt(33) + 1;
//如果不存在则添加
if (!red.contains(ranRed)) {
red.add(ranRed);
}
}
System.out.print("{ ");
for (int i : red) {
System.out.printf("[%02d] ", i);
}
System.out.print("}");
System.out.printf("{ [%02d] }", random.nextInt(16) + 1);
}
}
运行结果:

这是我目前想到的五种方式,那么你觉得那种好用呢?
或者你有更好的方法,欢迎评论区补充,大家一起探讨一起学习!
Java用n种方法编写实现双色球随机摇号案例的更多相关文章
- 用JavaScript+HTML实现双色球随机摇号效果
用JavaScript+HTML实现双色球随机摇号效果 首先要知道双色球的规则是什么 双色球投注区分为红球号码区和蓝球号码区 红球号码范围为01-33,蓝球号码范围为01-16 双色球每期从33个红球 ...
- java基础-四种方法引用
实例 直接三角形,通过两边算第三边,目的是为了如何使用这几种方法引用.代码中多有些不合适,尽情原谅. 静态方法引用 接口的参数列表与类中的具体实现方法的参数列表一样,返回值一致. 调用 //静态引用 ...
- Java用四种方法实现阶乘n! (factorial)
1. 引言 实现阶乘的方法很多,这边介绍四种方法,分别是递归,尾递归,循环和BigDecimal. 2. 代码 public class Test { public static void main( ...
- 两个变量交换的四种方法(Java) 七种方法(JS)
两个变量交换的四种方法(Java) 对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) 1 class TestEV 2 ...
- JAVA - 多线程 两种方法的比较
一.继承Thread类 实现方法: (1).首先定义一个类去继承Thread父类,重写父类中的run()方法.在run()方法中加入具体的任务代码或处理逻辑.(2).直接创建一个ThreadDemo2 ...
- JAVA 创建对象4种方法
java创建对象的几种方式 博客分类: java (1) 用new语句创建对象,这是最常见的创建对象的方法.(2) 运用反射手段,调用java.lang.Class或者java.lang.refl ...
- java 中有几种方法可以实现一个线程? 用什么关键字修 饰同步方法? stop()和 suspend()方法为何不推荐使用?
java5 以前, 有如下两种:第一种:new Thread(){}.start();这表示调用 Thread 子类对象的 run 方法, new Thread(){}表示一个Thread 的匿名子类 ...
- 【Java面试题】23 java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
java5 以前, 有如下两种:第一种:new Thread(){}.start();这表示调用 Thread 子类对象的 run 方法, new Thread(){}表示一个Thread 的匿名子类 ...
- JAVA实现两种方法反转单列表
/** * @author luochengcheng * 定义一个单链表 */ class Node { //变量 private int record; //指向下一个对象 private Nod ...
随机推荐
- CS基础 float 浮动的使用方法
html代码: <body> <div class='red'> </div> <div class='green'> </div> < ...
- unittest_TestSuite测试套件(2)
在前面一章中演示了unittest如何执行一个简单的测试,但有两个问题: 我们知道测试用例的执行顺序是根据测试用例名称顺序执行的,在不改变用例名称的情况下,我们怎么来控制用例执行的顺序呢? 一个测试文 ...
- git 不小心把某个文件给 add 了 的解决方法
1.我不小心把这两个文件给add 进来本地仓库 2.解决 进入指令框 ,执行 git rm --cached 文件名 如下图 注意,必须指定文件否则会删除所有
- 查看磁盘I/O命令iostat详解
iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视.它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况.iostat也有一个弱 ...
- Zuul网关 @EnableZuulProxy 和 @EnableZuulServer 的区别
1. @EnableZuulProxy 2. @EnableZuulServer 3.解释 1)@EnableZuulProxy简单理解为@EnableZuulServer的增强版, 当Zuul与Eu ...
- Kubernetes最佳实践之腾讯云TKE 集群组建
作者陈鹏,腾讯工程师,负责腾讯云 TKE 的售中.售后的技术支持,根据客户需求输出合理技术方案与最佳实践,为客户业务保驾护航.使用 TKE 来组建 Kubernetes 集群时,会面对各种配置选项,本 ...
- 读《疯狂Java讲义》笔记总结二
1.变量分类图 2.通过实例访问静态变量(类变量) 3.静态导入 4.构造器 5.创建对象内存过程
- Abp vnext EFCore 实现动态上下文DbSet踩坑记
背景 我们在用EFCore框架操作数据库的时候,我们会遇到在 xxDbContext 中要写大量的上下文 DbSet<>; 那我们表少还可以接受,表多的时候每张表都要写一个DbSet, 大 ...
- 【笔记】golang中使用protocol buffers的底层库直接解码二进制数据
背景 一个简单的代理程序,发现单核QPS达到2万/s左右就上不去了,40%的CPU消耗在pb的decode/encode上面. 于是我想,对于特定的场景,直接从[]byte中取出字段,而不用完全的把整 ...
- 使用Hot Chocolate和.NET 6构建GraphQL应用(1)——GraphQL及示例项目介绍
系列导航 使用Hot Chocolate和.NET 6构建GraphQL应用文章索引 前言 这篇文章是这个系列的第一篇,我们会简单地讨论一下GraphQL,然后介绍一下这个系列将会使用的示例项目. 关 ...