見出し画像

マインスイーパーもどきをつくる

また晴れたある日、ミケが堤防を散歩しています。

今日は一人のようです。

ミケ:ん~、何のゲーム作ろっかなぁ~。

ミケ:そういえば、まえクロ(近所に住んでいる猫)から面白いゲームを教えてもらったな。

ミケマインスイーパだっけ?ちょっと調べてみようかな。

ミケ:どれどれ...?

マインスイーパ(Minesweeper)は1980年代に発明された、一人用のコンピュータゲームである。ゲームの目的は地雷原から地雷を取り除くことである。マインスイーパーとも表記される。
wikipediaより
wikipediaより

ミケ:ほえぇ。なるほどなるほど。面白そうじゃん。

ミケ:でも全く同じなのはちょっとやだなぁ。すこしアレンジしちゃお~。

こうして、今日作る物が決まったようです。


とりあえず仕様を決めよう

とりあえずコーティングに入る前にどんなものを作るか決めていこう。

マスに数字が書いてあってそれが周りのボムの数を表してるっていう仕様はそのまま残しておこう。

ただ、マスをクリックしたらあけられていないマスを開けることができるってのは変えようかな。

もともとすべてのマスが見えるようにして、そっから探していくって感じでいいかな。

こんな感じのイメージだねぇ

こんな感じでボムを見つけていって、最終的にすべてのボムを見つけるってわけだね。

上の写真はボムが15個の場合だよ。

ボムの数はとりあえず15個固定でいいかな。

盤は多次元配列で扱ったら分かりやすそうだね。

まぁとりあえず作ってみよう。

実際に作ってみよう!

画面を表示しよう

とりあえずウィンドウを表示しよう。前々回くらいのコードを流用して…と

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Color;

import javax.swing.*;

public class Minesweeper{


    public static void main(String[] args) {
        
        JFrame frame = new JFrame();
        frame.setTitle("マインドスイーパーもどき");
        frame.setSize(500,560);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JPanel canvas = new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                draw(g);
            }
        };

        frame.add(canvas);
        frame.setVisible(true);

        Timer timer = new Timer(10new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                //ループ処理
                
                canvas.repaint();
            } 
        });
        timer.start();

    }
    public static void draw(Graphics g){
        g.setColor(Color.red);
        g.fillOval(10101010);
    }
}

とりあえずこんな感じかな。

でも、これだと後々面倒そうな気がするからJFrameクラスを継承して新たにFrameクラスを作っておこう。

class Frame extends JFrame{
    JPanel canvas;

    Frame(String title){
        canvas = new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                draw(g);
            }
        };
        this.setTitle(title);
        this.setSize(500+15,500+100);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.add(canvas);
        this.setVisible(true);
    }
}

となると、こういうことになるね。

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Color;

import javax.swing.*;

public class Minesweeper{


    public static void main(String[] args) {
        
        Frame Frame = new Frame("マインドスイーパーもどき");

        Timer timer = new Timer(10new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                //ループ処理
                
                Frame.canvas.repaint();
            } 
        });
        timer.start();

    }
}
class Frame extends JFrame{
    JPanel canvas;

    Frame(String title){
        canvas = new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                draw(g);
            }
        };
        this.setTitle(title);
        this.setSize(500+15,500+100);//+15は誤差、+100はメニューバーの分
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.add(canvas);
        this.setVisible(true);
    }
    private void draw(Graphics g){
        g.setColor(Color.red);
        g.fillOval(10101010);
    }
}


こんな感じになったら成功だよ。

画面の構造を考えてみよう

さて、じゃあ次に画面の構造を考えていこう。

どんな感じのUIにするかってのを決めていくよ。

イメージ図

上の図は簡単なイメージ図だね。

まぁ要するに盤面を描画するキャンバス部分リセットボタンなどを配置するメニュー部分に分かれるってことだね。

どういう風にデータを扱うか

よし、じゃあ次に盤のデータ構造について考えてみよう。

まぁ見た目的にも多次元配列が一番合っているのかな。

今回は5x5マスだから配列の要素数も5x5にしようかな。

いや、でもボムが周りに何個あるかを判定するときに、外側の要素がめんどいことになりそうだね。

じゃあ、配列の要素数を一回り大きな7x7にしてみたらいいのか。

そうすれば、(配列の中の)ボムの探索の処理がすべて同じように実装できる!

ん~、次はボムの位置をどう扱おうか。

別に配列用意してそこでボムの位置を格納するっていうのも一つの手な気がするけど…。

それか盤配列の要素が負の値ならその位置にボムがあるっていう風にすればいいか。

となると、こういう風になるのかな。

こういう風にすればよさそうだね。

マウスがどのマスをクリックしたのかを判定する

よし、じゃあ次にマウスでクリックされたのがどのマスかを判定する方法を考えてみよう。

とりあえず、簡単な例から考えてみようか。

この場合はマウスの座標は$${(0.5,1.5)}$$でマスの位置は$${[1,0]}$$だよね。

この座標を使ってマウスのマスの位置を求めてみよう。

この場合のマスの位置はそれぞれの値を$${mx,my}$$とすると次の式で求められるよ。

$${mx=\lfloor x \rfloor}$$

$${my=\lfloor y \rfloor}$$

つまり上の例の場合だと、

$${\lfloor 0.5 \rfloor=0}$$

$${\lfloor 1.5 \rfloor=1}$$

となって例図と同じ位置になってるね。

じゃあこれをいまからつくるマインスイーパもどきに適応してみよう。

今回は5x5マスだから一マスの大きさが100pt x 100ptだね。

つまり、マスの位置は

$${(\lfloor \frac{x}{100} \rfloor,\lfloor \frac{y}{100} \rfloor)}$$

で表せるね。

もしかしたら気づいたかもしれないけど、

$${\lfloor\frac{座標}{1マスの大きさ}\rfloor}$$でマスの位置を求めることができるんだ。

コーティングしていく(ゲームの中身の処理)

ということで、実際にかいていこうか。

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.awt.Color;

import javax.swing.*;

public class Minesweeper{

    static final int BOM_NUM=15;

    static int[][] board ={
        {9,9,9,9,9,9,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,9,9,9,9,9,9},
    };
    private static void setBoard(){
        boolean[][] bomBoard=setBom();
        for (int i = 1; i < bomBoard.length-1; i++) {
            for (int j = 1; j < bomBoard[0].length-1; j++) {
                board[i][j]=countSurroundBomNum(j, i, bomBoard);
            }
        }
    }
    private static boolean[][] setBom(){
        int x = 0;
        int y = 0;
        int bomNum = 0;
        boolean[][] bomBoard = new boolean[7][7];
        while(bomNum<BOM_NUM){
            x = new java.util.Random().nextInt(5)+1;
            y = new java.util.Random().nextInt(5)+1;
            if(!bomBoard[y][x]){
                bomBoard[y][x] = true;
                bomNum ++;
            }
        }
        return bomBoard;
    }
    private static int countSurroundBomNum(int x,int y,boolean[][] bomBoard){
        int surroundBomNum=0;
        for(int k=-1;k<2;k++){
            for(int p=-1;p<2;p++){
                if(k==0&&p==0)continue;
                if(checkIsBom(x+k, y+p,bomBoard)){
                    surroundBomNum++;
                }
            }
        }
        if(checkIsBom(x, y, bomBoard)){
            if(surroundBomNum==0)return -9;
            surroundBomNum*=-1;
        }
        return surroundBomNum;
    }

    private static boolean checkIsBom(int x,int y,boolean[][] bomBoard){
        return bomBoard[y][x];
    }

    public static void main(String[] args) {
        
        Frame Frame = new Frame("マインドスイーパーもどき");
        
        setBoard();
        for (int i = 0; i < board.length; i++) {
            System.out.println(Arrays.toString(board[i]));
        }
        System.out.println();
        ...

    }
}
class Frame extends JFrame{
    ...

重複しているところは省略してるけど、こんな感じかな。

僕の英語力のなさがメゾットの名前に表れているね(笑)

まぁこれでターミナルに各マスの周りのボム数が表示されるはずだよ。

これで一応このマインスイーパーもどきの中枢部分はできたかな。

あとは描画処理とメニュー部分の処理を考えていくだけだね。

描画処理を実装する

じゃあ次は描画処理を実装していこうか。

とはいっても、全然簡単だよ。

    private void draw(Graphics g){
        g.setColor(Color.BLACK);
        g.setFont(new Font("メイリオ",Font.BOLD,15));
        for(int i=1;i<Minesweeper.board.length-1;i++){
            for(int j=1;j<Minesweeper.board.length-1;j++){
                g.drawLine(j*1000, j*100500);
                g.drawLine(0, i*100500, i*100);

                String num = ""+(Minesweeper.board[i][j]!=-9?Minesweeper.board[i][j]:0);
                g.drawString(num,100*(j-1)+45100*(i-1)+45);
            }
        }
    }

ね、簡単でしょ?

縦横に線を引いて表の形を作って、マスの真ん中に数字を表示させる…。

board[i][j]の値が-9のときのみ0を表示させるってことにさえ気を付ければそこまで簡単だね。

あ、ファイルの先頭に次の一文を加えておくことも忘れずに。

import java.awt.Font;

…何か忘れてると思わない?

そう、マルとバツを描画していないんだよ!完全に忘れてたね。

ということでマルとバツの描画もしていこう。

とりあえず、マルバツの区別をどうつけるかなんだけど…。

これについてはboardの値にマルならx13バツならx11すればよさそうだね。

あと、答え合わせのときのマルも必要だね。これはx17すればいいかな。

ん?ちょっとまてよ…。x13したりx11したりするってことは、0はつかっちゃいけないのでは…!

なら、0の部分を10に変えるとしよう。

と、なると次のように書けばいいかな。

    private void draw(Graphics g){
        
        g.setColor(Color.BLACK);
        g.setFont(new Font("メイリオ",Font.BOLD,15));

        for(int i=1;i<Minesweeper.board.length-1;i++){
            for(int j=1;j<Minesweeper.board.length-1;j++){
                g.drawLine(j*1000, j*100500);
                g.drawLine(0, i*100500, i*100);

                String num = Minesweeper.format(j, i);

                g.drawString(num,100*(j-1)+45100*(i-1)+45);

                if(Math.abs(Math.abs(Minesweeper.board[i][j]))%17==0){
                    //答え合わせ用
                    g.setColor(Color.green);
                    g.drawString("〇",100*(j-1)+35100*(i-1)+50);
                }else if(Math.abs(Minesweeper.board[i][j])%13==0){
                    //ボムがある場所を指す
                    g.setColor(Color.blue);
                    g.drawString("〇",100*(j-1)+35100*(i-1)+50);
                }else if(Math.abs(Minesweeper.board[i][j])%11==0){
                    //メモ用 ボムがない場所をさしたりするのに用いる
                    g.setColor(Color.red);
                    g.drawString("×",100*(j-1)+35100*(i-1)+50);
                }
                g.setColor(Color.black);
            }
        }
    }

真ん中あたりで、Minsweeper.format()というメゾットを使っているけどこれは新たに定義したものだね。

中身はこんな感じ。

    public static String format(int x,int y){

        boolean isZero = board[y][x]==-9||board[y][x]==-99||board[y][x]==-117||board[y][x]==10||board[y][x]==110||board[y][x]==130?true:false;

        if(isZero){
            return "0";
        }
        if(Math.abs(board[y][x])%11==0){
            return Math.abs(board[y][x]/11)+"";
        }
        if(Math.abs(board[y][x])%13==0){
            return Math.abs(board[y][x]/13)+"";
        }
        if(Math.abs(board[y][x])%17==0){
            return Math.abs(board[y][x]/17)+"";
        }
        return Math.abs(board[y][x])+"";
    }

おっと、countSurroundBomNum()の修正も忘れずにね。

    private static int countSurroundBomNum(int x,int y,boolean[][] bomBoard){
        int surroundBomNum=0;
        for(int k=-1;k<2;k++){
            for(int p=-1;p<2;p++){
                if(k==0&&p==0)continue;
                if(checkIsBom(x+k, y+p,bomBoard)){
                    surroundBomNum++;
                }
            }
        }
        if(checkIsBom(x, y, bomBoard)){
            if(surroundBomNum==0)return -9;
            surroundBomNum*=-1;
        }
        return surroundBomNum==0?10:surroundBomNum;
    }


マウスのクリック処理を実装する

ふぅ、ちょっと疲れてきたね。でもあと少しで完成だよ!

とはいっても、あと3割くらいはあるんだけどね。でもここまで理解できていたら楽勝なはずだよ。

閑話休題話を戻そう

まずはマウスのクリック入力を受け取れるようにしないといけないね。

クリック入力を検知するために、Windowクラスにjava.awt.event.MouseListenerを実装させよう。

そうすると、

public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}

の5つの抽象メゾットをオーバーライドする必要があるね。

でも、今回必要なのはクリック入力の検知のみだからmouseClicked()のみ中身を書いていけばいいね。

右クリックをマル、左クリックをバツにしようかな。

    @Override
    public void mouseClicked(MouseEvent e) {
        switch(e.getButton()){
            case MouseEvent.BUTTON1:
                // 左クリック

                break;
            case MouseEvent.BUTTON3:
                // 右クリック

                break;
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {}
    @Override
    public void mouseReleased(MouseEvent e) {}
    @Override
    public void mouseEntered(MouseEvent e) {}
    @Override
    public void mouseExited(MouseEvent e) {}

つぎはマウスがクリックしたマスがどれかを求めるよ。

ここで思い出してほしいのは、最初のほうで言った「マウスがどのマスをクリックしたのかを判定する」方法だよ。

さっきはガウス記号を使っていたけど、Javaではそんな記号は使えないんだ。

代わりに、Math.floor()メゾットを使うよ。

このメゾットについて簡単に説明しよう。このメゾットは与えられたdouble値以下の最大の整数を返すよ。つまり、ガウス記号と同じだね。

@Override
public void mouseClicked(MouseEvent e) {

    int x=(int)Math.floor(e.getPoint().x/100);
    int y=(int)Math.floor((e.getPoint().y-30)/100);//タイトルバーの分引く

    if(Minesweeper.isAnswered)return;

    switch(e.getButton()){
        case MouseEvent.BUTTON1:
            // 左クリック

            if(Math.abs(Minesweeper.board[y+1][x+1])%11==0){
                Minesweeper.board[y+1][x+1]/=11;
            }else{
                if(Math.abs(Minesweeper.board[y+1][x+1])%13==0)Minesweeper.board[y+1][x+1]/=13;
                Minesweeper.board[y+1][x+1]*=11;
            }

            break;
        case MouseEvent.BUTTON3:
            // 右クリック

            if(Math.abs(Minesweeper.board[y+1][x+1])%13==0){
                Minesweeper.board[y+1][x+1]/=13;
            }else{
                if(Math.abs(Minesweeper.board[y+1][x+1])%11==0)Minesweeper.board[y+1][x+1]/=11;
                Minesweeper.board[y+1][x+1]*=13;
            }
            break;
}

こんな感じかな。

途中でMinesweeper.isAnsweredという変数が出てきているけど、これは後から紹介するよ。

あとはこのマウスリスナーをウィンドウにはめ込もう。

        this.setTitle(title);
        this.setSize(500+15,500+100);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setResizable(false);

        this.addMouseListener(this);//自分自身をはめ込む

        this.setVisible(true);

メニュー部分を実装する。

じゃあ最後にメニュー部分を実装していこう。

イメージ図

上のイメージ図に沿ってメニュー部分を実装していこうか。

とりあえず、メニュー部分にあるボタンとラベル(文字列)を格納するパネルを作ってそこにはめていく感じでいいかな。

class Frame extends JFrame implements MouseListener{
    JPanel canvas;
    JLabel score;

    Frame(String title){
        canvas = new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                draw(g);
            }
        };

        JPanel menu = new JPanel();
        JButton answer = new JButton("Answer");
        JButton reset = new JButton("Reset");
        JLabel bomNum = new JLabel("bomNum:"+Minesweeper.BOM_NUM);
        score = new JLabel("Score:");
    ...
    menu.add(reset);
        menu.add(answer);
        menu.add(bomNum);
        menu.add(score);
       
        this.add(canvas,BorderLayout.CENTER);
        this.add(menu,BorderLayout.SOUTH);

レイアウトはBorderLayoutでいいかな。キャンバスを真ん中に設定しておくことも忘れずに。

じゃあ次にanswer,resetボタンが押された時の処理も書いていこう。

まずはanswerから。

        answer.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                if(Minesweeper.isAnswered)return;

                for(int i =0;i<Minesweeper.board.length;i++){
                    for(int j=0;j<Minesweeper.board[0].length;j++){

                        if(Minesweeper.board[i][j]<0){
                            if(Math.abs(Minesweeper.board[i][j])%13==0){
                                Minesweeper.board[i][j]/=13;
                                Minesweeper.score += 10;
                            }
                            if(Math.abs(Minesweeper.board[i][j])%11==0){
                                Minesweeper.board[i][j]/=11;
                            }
                            Minesweeper.board[i][j]*=17;
                        }
                    }
                }
                score.setText("Score:"+Minesweeper.score);
                Minesweeper.isAnswered=true;

            }
        });

またもや出てきたMinesweeper.isAnswered。見ればわかるように、この変数はanswerボタンが押されたかを格納する変数だったんだ。

気づきにくいけどMinesweeper.scoreも新しく出てきているね。この変数はマークした部分にボムがあったら、つまり予想が当たっていたら値が増えるようになっているよ。

普通にゲームのスコアって言っても伝わるかな。

宣言はあとで見せるよ。

お次はresetボタン。

        reset.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                Minesweeper.isReset=true;
            }
        });

こちらは新しくMinesweeper.isResetが使われているね。isAnsweredと同様にresetボタンが押されたかどうかを格納するよ。

リセット処理を実装する

さっきメニュー部分を実装したら終わりって言ったけど、あれ間違いだった。リセット処理を実装するの忘れていたね。

public class Minesweeper{

    static final int BOM_NUM=15;

    static int score = 0;
    static boolean isReset=false;
    static boolean isAnswered=false;

    static int[][] board ={...};
    private static void setBoard(){...}
    private static boolean[][] setBom(){...}
    private static int countSurroundBomNum(int x,int y,boolean[][] bomBoard){...}
    private static boolean checkIsBom(int x,int y,boolean[][] bomBoard){...}

    public static void main(String[] args) {
        
        Frame Frame = new Frame("マインドスイーパーもどき");
        
        ...


        Timer timer = new Timer(10new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                //ループ処理
                if(isReset){
                    isAnswered=false;
                    isReset=false;
                    scre=0;
                    Frame.score.setText("Score:");

                    setBoard();
                }
                
                Frame.canvas.repaint();
            } 
        });
        timer.start();

    }
    ...

完成!!

ということで、正真正銘完成だ!! やったね。

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.util.Arrays;
import java.awt.event.MouseEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;

import javax.swing.*;



public class Minesweeper{

    static final int BOM_NUM=15;
    static int score = 0;
    static boolean isReset=false;
    static boolean isAnswered=false;

    static int[][] board ={
        {9,9,9,9,9,9,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,0,0,0,0,0,9},
        {9,9,9,9,9,9,9},
    };
    private static void setBoard(){
        boolean[][] bomBoard=setBom();
        for (int i = 1; i < bomBoard.length-1; i++) {
            for (int j = 1; j < bomBoard[0].length-1; j++) {
                board[i][j]=countSurroundBomNum(j, i, bomBoard);
            }
        }
    }
    private static boolean[][] setBom(){
        int x = 0;
        int y = 0;
        int bomNum = 0;
        boolean[][] bomBoard = new boolean[7][7];
        while(bomNum<BOM_NUM){
            x = new java.util.Random().nextInt(5)+1;
            y = new java.util.Random().nextInt(5)+1;
            if(!bomBoard[y][x]){
                bomBoard[y][x] = true;
                bomNum ++;
            }
        }
        return bomBoard;
    }
    private static int countSurroundBomNum(int x,int y,boolean[][] bomBoard){
        int surroundBomNum=0;
        for(int k=-1;k<2;k++){
            for(int p=-1;p<2;p++){
                if(k==0&&p==0)continue;
                if(checkIsBom(x+k, y+p,bomBoard)){
                    surroundBomNum++;
                }
            }
        }
        if(checkIsBom(x, y, bomBoard)){
            if(surroundBomNum==0)return -9;
            surroundBomNum*=-1;
        }
        return surroundBomNum==0?10:surroundBomNum;
    }

    private static boolean checkIsBom(int x,int y,boolean[][] bomBoard){
        return bomBoard[y][x];
    }

    public static void main(String[] args) {
        
        Frame Frame = new Frame("マインドスイーパーもどき");
        
        setBoard();
        for (int[] a : board) {
            System.out.println(Arrays.toString(a));
        }

        Timer timer = new Timer(10new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                //ループ処理
                if(isReset){
                    isAnswered=false;
                    isReset=false;
                    score=0;
                    Frame.score.setText("Score:");

                    setBoard();
                }
                
                Frame.canvas.repaint();
            } 
        });
        timer.start();

    }
    public static String format(int x,int y){

        boolean isZero = board[y][x]==-9||board[y][x]==-99||board[y][x]==-117||board[y][x]==10||board[y][x]==110||board[y][x]==130?true:false;

        if(isZero){
            return "0";
        }
        if(Math.abs(board[y][x])%11==0){
            return Math.abs(board[y][x]/11)+"";
        }
        if(Math.abs(board[y][x])%13==0){
            return Math.abs(board[y][x]/13)+"";
        }
        if(Math.abs(board[y][x])%17==0){
            return Math.abs(board[y][x]/17)+"";
        }
        return Math.abs(board[y][x])+"";
    }
}
class Frame extends JFrame implements MouseListener{
    JPanel canvas;
    JLabel score;

    Frame(String title){
        canvas = new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                draw(g);
            }
        };

        JPanel menu = new JPanel();
        JButton answer = new JButton("Answer");
        JButton reset = new JButton("Reset");
        JLabel bomNum = new JLabel("bomNum:"+Minesweeper.BOM_NUM);
        score = new JLabel("Score:");

        answer.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                if(Minesweeper.isAnswered)return;

                for(int i =0;i<Minesweeper.board.length;i++){
                    for(int j=0;j<Minesweeper.board[0].length;j++){

                        if(Minesweeper.board[i][j]<0){
                            if(Math.abs(Minesweeper.board[i][j])%13==0){
                                Minesweeper.board[i][j]/=13;
                                Minesweeper.score += 10;
                            }
                            if(Math.abs(Minesweeper.board[i][j])%11==0){
                                Minesweeper.board[i][j]/=11;
                            }
                            Minesweeper.board[i][j]*=17;
                        }
                    }
                }
                score.setText("Score:"+Minesweeper.score);
                Minesweeper.isAnswered=true;

            }
        });
        reset.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                Minesweeper.isReset=true;
            }
        });
        menu.add(reset);
        menu.add(answer);
        menu.add(bomNum);
        menu.add(score);
        this.setTitle(title);
        this.setSize(500+15,500+100);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setResizable(false);
        this.add(canvas,BorderLayout.CENTER);
        this.add(menu,BorderLayout.SOUTH);
        this.addMouseListener(this);
        this.setVisible(true);
    }
    
    private void draw(Graphics g){
        
        g.setColor(Color.BLACK);
        g.setFont(new Font("メイリオ",Font.BOLD,15));

        for(int i=1;i<Minesweeper.board.length-1;i++){
            for(int j=1;j<Minesweeper.board.length-1;j++){
                g.drawLine(j*1000, j*100500);
                g.drawLine(0, i*100500, i*100);

                String num = Minesweeper.format(j, i);

                g.drawString(num,100*(j-1)+45100*(i-1)+45);

                if(Math.abs(Math.abs(Minesweeper.board[i][j]))%17==0){
                    //答え合わせ用
                    g.setColor(Color.green);
                    g.drawString("〇",100*(j-1)+35100*(i-1)+50);
                }else if(Math.abs(Minesweeper.board[i][j])%13==0){
                    //ボムがある場所を指す
                    g.setColor(Color.blue);
                    g.drawString("〇",100*(j-1)+35100*(i-1)+50);
                }else if(Math.abs(Minesweeper.board[i][j])%11==0){
                    //メモ用 ボムがない場所をさしたりするのに用いる
                    g.setColor(Color.red);
                    g.drawString("×",100*(j-1)+35100*(i-1)+50);
                }
                g.setColor(Color.black);
            }
        }
    }


    @Override
    public void mouseClicked(MouseEvent e) {

        int x=(int)Math.floor(e.getPoint().x/100);
        int y=(int)Math.floor((e.getPoint().y-30)/100);//タイトルバーの分引く

        if(Minesweeper.isAnswered)return;

        switch(e.getButton()){
            case MouseEvent.BUTTON1:
                // 左クリック

                if(Math.abs(Minesweeper.board[y+1][x+1])%11==0){
                    Minesweeper.board[y+1][x+1]/=11;
                }else{
                    if(Math.abs(Minesweeper.board[y+1][x+1])%13==0)Minesweeper.board[y+1][x+1]/=13;
                    Minesweeper.board[y+1][x+1]*=11;
                }

                break;
            case MouseEvent.BUTTON3:
                // 右クリック
                if(Math.abs(Minesweeper.board[y+1][x+1])%13==0){
                    Minesweeper.board[y+1][x+1]/=13;
                }else{
                    if(Math.abs(Minesweeper.board[y+1][x+1])%11==0)Minesweeper.board[y+1][x+1]/=11;
                    Minesweeper.board[y+1][x+1]*=13;
                }

                break;
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {}
    @Override
    public void mouseReleased(MouseEvent e) {}
    @Override
    public void mouseEntered(MouseEvent e) {}
    @Override
    public void mouseExited(MouseEvent e) {}
}

ふぅぅ、お疲れ様だねぇ。

でも、これでもまだ不完全な部分はあると思うんだ。

とりあえず全部コピペして、自分のできそうなところから自分なりに改造していくといいかもね。

ボムの数を増やしたり減らしたりして遊ぶだけでも楽しいと思うよ!

終わりに

銅色に染まる空を眺めながら、堤防で寝転がっている猫がいます。

どうやらミケのようです。 疲れて眠ってしまっているようですね。

ミケ:むにゃむにゃむにゃ~ zzZ…。

そこへ一匹の猫が現れました。今度はマロのようです。

マロ:あ!やっと見つけた!ミケ~。

ミケ:むにゃ~? あ、マロ~!おはよう~。

マロ:おはようじゃないよミケ!探したんだから!

ミケ:ごめん~。疲れちゃってさ。

マロ:まぁミケが見つかってよかったよ。早く帰ろう!

ミケ:ちょっとまって、今日何かあるの?

マロ:えぇ?覚えてないの?今日の朝にもいったじゃん!

ミケ:むむ~?覚えてないな~。何かあったっけ?

マロ:今日から2週間飼い主さんが旅行するからそれについていくんだよ!

ミケ:えぇ!!旅行!?

マロ:そう、旅行! しかも海外!

ミケ:海外ぃ!最高じゃん!早く帰ろうよ!!

マロ:だからさっきから言ってるじゃん!

ミケ:すみませんでしたぁ!

マロ:ほら、帰るよ~!

ミケ:うん!

どうやら飼い主さんの二週間旅行についていけることになった二匹。

わくわくが止まらない二匹、なにも起こらないといいけど…。

(※次回は二匹が海外旅行に行く話ではありません)

                       by ミケ


~~誤字や質問、間違いなどがあれば遠慮なくどうぞ~~














この記事が気に入ったらサポートをしてみませんか?