今回はJavaで宝くじゲームを作成してみよう!
実行例
まずは実行例から
1.宝くじを買う枚数を入力
2.0000~9999の重複のない番号から購入枚数選ばれる(昇順表示)
3. 当選番号が千の位から順番に1秒ごとに表示される
4. 結果が表示される(1等は 完全一致,2等は下3桁,3等は…)
詳しくは以下の実行例を参照のこと
宝くじを何枚買いますか?>>5
['0406', '4131', '8321', '8708', '9871']
抽選開始...
5
1
3
1
1等賞(5131) []
2等賞(*131) ['4131']
3等賞(**31) []
4等賞(***1) ['8321', '9871']
作成
ではこのお題を順に作成していこう。任意の場所にMain.javaを作成し以下のように記述する
import java.util.*;
public class Main{
public static void main(String[] args) throws Exception{
Scanner sc=new Scanner(System.in);
Random rand=new Random();
String[] fortunes=new String[10000];
for(int i=0;i<fortunes.length;i++){
fortunes[i]=String.format("%04d",i);
}
System.out.println(Arrays.toString(fortunes));
}
}
実行してみよう。以下のように1万個表示されれば成功だ
解説
○今回はRandomクラスとScannerクラスを使うのでjava.util.*をimportする。
○途中1秒ごとにという処理の際にThread.sleepを使うがこれはチェック例外だ。
例外処理は不要なのでthrows Exceptionとしておく
○あとは要素が10000個のString配列を用意し、書式を使うことで0~9999を0000~9999にして格納している。
続きを作ろう以下のハイライト部分のように修正する(10行目はコメントアウト)
import java.util.*;
public class Main{
public static void main(String[] args) throws Exception{
Scanner sc=new Scanner(System.in);
Random rand=new Random();
String[] fortunes=new String[10000];
for(int i=0;i<fortunes.length;i++){
fortunes[i]=String.format("%04d",i);
}
//System.out.println(Arrays.toString(fortunes));
for(int i=0;i<fortunes.length-1;i++){
int index=rand.nextInt(fortunes.length-i);
String temp=fortunes[index];
fortunes[index]=fortunes[fortunes.length-1-i];
fortunes[fortunes.length-1-i]=temp;
}
System.out.print("何枚くじを買いますか>>");
int num=sc.nextInt();
String[] myLotts=new String[num];
for(int i=0;i<num;i++){
myLotts[i]=fortunes[i];
}
Arrays.sort(myLotts);
System.out.println(Arrays.toString(myLotts));
}
}
実行してみよう。枚数を聞かれるので適当な枚数を入力してみよう。以下のように表示されれば成功だ。
解説
○配列のシャッフル(11-16行目)
シャッフルのアルゴリズムにて配列をシャッフルしている。
○指定枚数の取り出し
何枚かを聞き。その枚数を元に配列を作成。あとはシャッフル済みの配列の先頭からその枚数取り出せばよい。
○Arrays.sort(myLotts);
配列はArrays.sortを用いることでソートできる。文字列は辞書順にソートされる。
続きを作ろう。以下のハイライト部分を追記する
import java.util.*;
public class Main{
public static void main(String[] args) throws Exception{
Scanner sc=new Scanner(System.in);
Random rand=new Random();
String[] fortunes=new String[10000];
for(int i=0;i<fortunes.length;i++){
fortunes[i]=String.format("%04d",i);
}
//System.out.println(Arrays.toString(fortunes));
for(int i=0;i<fortunes.length-1;i++){
int index=rand.nextInt(fortunes.length-i);
String temp=fortunes[index];
fortunes[index]=fortunes[fortunes.length-1-i];
fortunes[fortunes.length-1-i]=temp;
}
System.out.print("何枚くじを買いますか>>");
int num=sc.nextInt();
String[] myLotts=new String[num];
for(int i=0;i<num;i++){
myLotts[i]=fortunes[i];
}
Arrays.sort(myLotts);
System.out.println(Arrays.toString(myLotts));
System.out.println("抽選開始...");
String lucky=String.format("%04d",rand.nextInt(10000));
for(int i=0;i<4;i++){
Thread.sleep(1000);
System.out.println(lucky.charAt(i));
}
}
}
実行してみよう。当選番号が千の位から1秒毎に表示されれば成功だ。
解説
○Thread.sleep(1000)
1秒止めるにはThread.sleep(1000)を指定する。この引数はミリ秒。
また、これはチェック例外なので例外処理が必要となるが今回は冒頭でthrows Exceptionして省略している。
○文字列.charAt(index)
とすることで文字列を一文字ずつchar型として取り出すことができる。indexは0から始まることに注意
続いて以下のように入力して完成させよう。
import java.util.*;
public class Main{
public static void main(String[] args) throws Exception{
Scanner sc=new Scanner(System.in);
Random rand=new Random();
String[] fortunes=new String[10000];
for(int i=0;i<fortunes.length;i++){
fortunes[i]=String.format("%04d",i);
}
//System.out.println(Arrays.toString(fortunes));
for(int i=0;i<fortunes.length-1;i++){
int index=rand.nextInt(fortunes.length-i);
String temp=fortunes[index];
fortunes[index]=fortunes[fortunes.length-1-i];
fortunes[fortunes.length-1-i]=temp;
}
System.out.print("何枚くじを買いますか>>");
int num=sc.nextInt();
String[] myLotts=new String[num];
for(int i=0;i<num;i++){
myLotts[i]=fortunes[i];
}
Arrays.sort(myLotts);
System.out.println(Arrays.toString(myLotts));
System.out.println("抽選開始...");
String lucky=String.format("%04d",rand.nextInt(10000));
for(int i=0;i<4;i++){
Thread.sleep(1000);
System.out.println(lucky.charAt(i));
}
List<List<String>> list=new ArrayList<>();
for(int i=0;i<4;i++){
list.add(new ArrayList<String>());
}
for(String n:myLotts){
if( n.equals(lucky)){
list.get(0).add(n);
}else if(n.substring(1).equals(lucky.substring(1))){
list.get(1).add(n);
}else if(n.substring(2).equals(lucky.substring(2))){
list.get(2).add(n);
}else if(n.substring(3).equals(lucky.substring(3))){
list.get(3).add(n);
}
}
for(int i=0;i<4;i++){
System.out.printf("%d等賞(%s) %s%n",i+1,
String.format("%4s",lucky.substring(i)).replace(" ","*"),
list.get(i)
);
}
}
}
入力したら実行してみよう。
宝くじを何枚買いますか?>> 5
['0703', '1020', '1480', '3376', '6058']
抽選開始...
8
7
8
4
1等賞(8784) []
2等賞(*784) []
3等賞(**84) []
4等賞(***4) []
5枚くらいだとなかなか当たらない。1000枚くらい大人買いしてみよう。
表示がすごいことになってるがどうやら2等が当たったようだ。
解説
今回この1等が〜、2等が~というのを以下のような2次元リストで管理することにした
list=[
['4142'], # 1等の番号リスト
['0142','8142'], # 2等の番号リスト
['3542','9942'], # 3等の番号リスト
['0002','9992'], # 4等の番号リスト
]
なのでまずはString型の2次元リストを以下のように作成する。
List<List<String>> list=new ArrayList<>();
for(int i=0;i<4;i++){
list.add(new ArrayList<String>());
}
あとは、自分の持っている番号リストから拡張for文で1つずつ取り出しながら判定していくだけだ。
for(String n:myLotts){
if(n.equals(lucky)){
list.get(0).add(n);
}else if(n.substring(1).equals(lucky.substring(1))){
list.get(1).add(n);
}else if(n.substring(2).equals(lucky.substring(2))){
list.get(2).add(n);
}else if(n.substring(3).equals(lucky.substring(3))){
list.get(3).add(n);
}
}
取り出した番号と当選番号が完全一致すれば最初のリストにadd
そうではなくて下三桁が一致すれば2つ目のリストにaddしていっている
文字列.substring(index)
上記のようにsubstringすることでindex以降の文字を切り出せる。(0スタート)
また、今回は当選番号が一つしかないので1等の番号は2等~4等のすべての当選条件を満たす。なのでif文の判定する順序には気を使う必要がある。
さて、最後の出力部分だ
String.format("%4s",lucky.substring(i)).replace(" ","*")
実行例のような***3のような出力を作る手法として今回はsubstringしてからそれを%4sして足りない桁を半角スペースで埋めて、それをreplaceすることで実現した。
完成!
今回のお題を通して、乱数,シャッフル,substring,書式,入れ子のリストなどを演習することができた。
コメント