めちゃくちゃ簡易のビンゴゲームを作る　＃２

# 初めに
まず[前回やったこと](https://qiita.com/snow_saboten/items/1a3a8c77e22b75c9173b)の確認。
+ ランダムな数字を並べてビンゴカードを作る機能を作成。
+ 「ゲーム開始」ボタンでゲーム画面に移動するようにした。

の2つ。
前回の記事のコメントでビンゴカードはただランダムな数字を並べているのではなく、列ごとに並ぶ数字の範囲が決まっている、ということを教えていただいたので、この機能を追加する。
よって、今回作った機能は以下の2つ。
+ ビンゴカード作成機能の改良版（列ごとに範囲限定）
+ 抽選ボタンで出た数字がカード上にあれば、そのマスの背景色を変える。

ひとつずつ紹介する。
# ビンゴカード作成機能改良版
## コード（レイアウト）
```Java
    JPanel BingoCardPanel;
	JPanel p1;
	JPanel p2;
	JPanel p3;
	JPanel p4;
	JPanel p5;
	JLabel bingoNumLabel1[] = new JLabel[5];
	JLabel bingoNumLabel2[] = new JLabel[5];
	JLabel bingoNumLabel3[] = new JLabel[5];
	JLabel bingoNumLabel4[] = new JLabel[5];
	JLabel bingoNumLabel5[] = new JLabel[5];
	LineBorder border = new LineBorder(Color.LIGHT_GRAY,2,true);
	GridLayout gl = new GridLayout(5,1);

    public BingoGame() {
		setBounds(10,10,600,400);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		mkCardBtn = new JButton("ビンゴカード作成");
		mkCardBtn.addActionListener(this);
		
		BingoCardPanel = new JPanel();
		BingoCardPanel.setLayout(new GridLayout(1,5));
		
		mkCard(p1,bingoNumLabel1,1);
		mkCard(p2,bingoNumLabel2,6);
		mkCard(p3,bingoNumLabel3,11);
		mkCard(p4,bingoNumLabel4,16);
		mkCard(p5,bingoNumLabel5,21);
		
		
		JPanel p1_1 = new JPanel();
		p1_1.setLayout(new GridLayout(1,2));
		p1_1.add(mkCardBtn);
		p1_1.add(BingoCardPanel);
		
		startBtn  =new JButton("ゲーム開始");
		startBtn.addActionListener(this);
		
		c = getContentPane();
		c.add(p1_1, BorderLayout.CENTER);
		c.add(startBtn, BorderLayout.SOUTH); 
	}

    public void mkCard(JPanel p, JLabel[] la, int i){ //カードのレイアウト
		p = new JPanel();
		p.setLayout(gl);
		for(int j=0;j<la.length; j++) {
			String testNum = Integer.toString(j + i);
			la[j] = new JLabel(testNum);
			la[j].setBorder(border);
			p.add(la[j]);
		}
		BingoCardPanel.add(p);
	}
```
### ちょっと説明
前回まではBingoCardPanelにGridLayout(5,5)を設定して、JLabelを並べていたが、今回は列ごとのJPanelを作り、それぞれ5枚ずつJLabelを載せるようにした。
載せる操作は前回同様for文でまとめてみた。

## コード（「カード作成」ボタンの処理）
```Java
public void actionPerformed(ActionEvent e) {
		if(e.getSource() == mkCardBtn) {
			numList1.clear();
			numList2.clear();
			numList3.clear();
			numList4.clear();
			numList5.clear();
			mkRandomNum(numList1, 1, bingoNumLabel1);
			mkRandomNum(numList2, 16, bingoNumLabel2);
			mkRandomNum(numList3, 31, bingoNumLabel3);
			mkRandomNum(numList4, 46, bingoNumLabel4);
			mkRandomNum(numList5, 61, bingoNumLabel5);
        }
}

public void mkRandomNum(ArrayList<Integer> al, int i,JLabel[] la) {
		while(al.size() < 5) {
			int num = random.nextInt(15) + i;
			if(al.indexOf(num) == -1) {
				al.add(num);
			}
		}
		
		for(int j=0; j<al.size(); j++) {
			String number = Integer.toString(al.get(j));
			la[j].setText(number);
    	}
}
```
### ちょっと説明
1列目を例にすると、1列目に並べる用の数を入れるためのArrayList(変数名numList1)を作った。while文で、１～１５の数字を出して、indexOfメソッドで数字の被りがないか確認し、なければArrayListに追加という作業。
次のfor文ではintをStringに変えて、JLabelに乗せている。

・このmkRandomNumの第二引数を変えることで、2列目以降の数字の範囲を変えられるようになっている。

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586452/e7eade7c-e616-0efd-428b-75e1046a8076.png)
左の作成ボタンをおすことで、カードの数字がランダムに変わる。
何度押しても作成し直せるし、列ごとの数字の範囲限定も上手くいっている。いい感じ。
# 抽選ボタンの処理など
抽選ボタンを押すことで、
・被りのない１～７５までの数字をランダムにひとつ生成
・その数字を画面に表示
・その数字がカードにあれば、そのマスを赤くする
の３つが処理されるようにする。
## コード
```Java
public void actionPerformed(ActionEvent e) {
		if(e.getSource() == spinBtn) {
			do {
				spinNum = random.nextInt(75) + 1;
			}while(spinNumbersList.indexOf(spinNum) != -1); {
				spinNum = random.nextInt(75) + 1;
			}
			spinNumbersList.add(spinNum);
			String spinNumber = Integer.toString(spinNum);
			numLog.append(spinNumber + ",");
		}
		
		punchHole();
	}

public void punchHole() { //カードに穴あける。
		if(spinNum <= 15) {
			changeBackgroundColor(numList1, bingoNumLabel1);
		}else if(spinNum <= 30) {
			changeBackgroundColor(numList2, bingoNumLabel2);
		}else if(spinNum <= 45) {
			changeBackgroundColor(numList3, bingoNumLabel3);
		}else if(spinNum <= 60) {
			changeBackgroundColor(numList4, bingoNumLabel4);
		}else if(spinNum <= 75) {
			changeBackgroundColor(numList5, bingoNumLabel5);
		}
	}
	
	public void changeBackgroundColor(ArrayList<Integer> al, JLabel[] la) { //背景色を変える
		if(al.indexOf(spinNum) != -1) {
			la[al.indexOf(spinNum)].setOpaque(true);
			la[al.indexOf(spinNum)].setBackground(Color.red);
		}
	}
```

### ちょっと説明
・ランダム数字の生成に関しては、ほとんどカード作成時と同じ原理。今回はdo-while文を使って、被ってない数字になるまで繰り返すようにした。
・JTextArea(変数名numLog)にappendメソッドで数字の履歴を表示している。
・puchHole()に関して
生成された数字がどの列に入るかによって処理を分けている。
al.indexOf(spinNum)はArrayList alのどこにspinNumと同じ数字が入っているかを返してくれるので、それをビンゴカードのJLabel[]の添え字としている。
また、setOpaqueメソッドでtrueを設定することで、JLabelの背景を非透明にすることができる。デフォルトではfalseに設定されているので、この記述を書かない状態で、背景色を変えても見た目にあらわれない。
### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586452/2d79c9c5-1410-a289-75fe-5d30fc7b7238.png)
こんな感じ。右のボックスに出た数字の履歴が表示されてて、当たった数字は赤ますになってる。
これでだいぶビンゴゲームに近づいたと思う。

# 終わりに
見た目的にはかなりビンゴゲームになってきたが、これは一人で遊ぶものなのでやはり虚しさを感じる笑

もう一つ作りたいのはビンゴやリーチの判定機能なんだが、どうやって作ればいいか見当がついていないので、これはじっくり考えてみようと思う。フラグ用の変数でも作ればいいのかな、とも思ったが、縦横斜めに対応できる方法を思いつけていない。2，3日考えてみて分からなかったら、ネットに頼るか、力技でやってみようと思う。