SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Javaで学ぶグラフィックス処理

数字パズルを半自動的に解くプログラムの作成

入力可能な場所をガイドするアシストプログラム

  • X ポスト
  • このエントリーをはてなブックマークに追加

プログラム

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class Numbers extends Applet implements ItemListener,
   MouseListener,ActionListener{

   int X0=50,Y0=50;
   int SIZE=50;

   int[][] prob={{1,0,0,0,4,0,0,0,3}, //アプレット起動時のサンプル問題
                 {0,3,0,7,0,1,0,2,0},
                 {0,0,6,0,8,0,7,0,0},
                 {0,0,8,1,0,0,6,0,0},
                 {0,1,0,0,0,0,0,3,0},
                 {0,0,2,0,0,9,8,0,0},
                 {0,0,5,0,2,0,1,0,0},
                 {0,7,0,9,0,6,0,5,0},
                 {9,0,0,0,5,0,0,0,7}};

   int[][] solu=new int[9][9];
   int[][] trial=new int[9][9];
   int[][] gray=new int[9][9];
   int[] number=new int[10];

   Button button_solu_reset,button_trial_reset,button_all_reset;

   CheckboxGroup group1=new CheckboxGroup();
   CheckboxGroup group2=new CheckboxGroup();

   Checkbox[] radio1=new Checkbox[10];
   Checkbox[] radio2=new Checkbox[3];

   Font font0=new Font("",Font.PLAIN,SIZE/2);   //モード表示用フォント
   Font font1=new Font("",Font.PLAIN,SIZE);     //問題用フォント
   Font font2=new Font("",Font.ITALIC,SIZE);    //解答、試行用フォント
   Font font3=new Font("",Font.PLAIN,SIZE/3);   //候補表示用フォント

   int selected_number;   //ラジオボタンで選ばれた数字

   public void init(){

      //数字入力用ラジオボタン
      add(radio1[0]=new Checkbox("取消",group1,true));
      for(int i=1;i<10;i++)
         add(radio1[i]=new Checkbox(String.valueOf(i),group1,false));
      for(int i=0;i<10;i++)
         radio1[i].addItemListener(this);

      //モード選択用ラジオボタン
      add(radio2[0]=new Checkbox("出題",group2,false));
      //起動時には解答モードにしておく
      add(radio2[1]=new Checkbox("解答",group2,true));
      add(radio2[2]=new Checkbox("試行",group2,false));
      for(int i=0;i<3;i++)
         radio2[i].addItemListener(this);

      //ボタンの設定
      add(button_all_reset=new Button("全クリヤ"));
      add(button_solu_reset=new Button("解答クリヤ"));
      add(button_trial_reset=new Button("試行クリヤ"));
      button_all_reset.addActionListener(this);
      button_solu_reset.addActionListener(this);
      button_trial_reset.addActionListener(this);

      addMouseListener(this);

   }

   //ボタンがクリックされた際のメソッド
   public void actionPerformed(ActionEvent ae){

      if(ae.getSource()==button_all_reset){   //[全クリヤ]
         radio1[0].setState(true);   //[取消]に設定
         radio2[0].setState(true);   //[出題]に設定
         for(int j=0;j<9;j++)
            for(int i=0;i<9;i++){    //問題、解答、試行をクリヤ
               prob[j][i]=0;
               solu[j][i]=0;
               trial[j][i]=0;
            }
      }

      if(ae.getSource()==button_solu_reset){  //[解答クリヤ]
         for(int j=0;j<9;j++)
            for(int i=0;i<9;i++){    //解答、試行をクリヤ
               solu[j][i]=0;
               trial[j][i]=0;
            }
      }

      if(ae.getSource()==button_trial_reset){  //[試行クリヤ]
         for(int j=0;j<9;j++)
            for(int i=0;i<9;i++){    //試行をクリヤ
               trial[j][i]=0;
            }
      }

      repaint();

   }

   //ラジオボタンが変更になったときのメソッド
   public void itemStateChanged(ItemEvent ie){

      for(int i=0;i<10;i++){   //選択された数字でselected_numberを設定
         if(radio1[i].getState()){
            selected_number=i;
            break;
         }
      }

      repaint();

   }

   //マウスがクリックされたときのメソッド
   public void mouseClicked(MouseEvent me){

      int i,j;

      int x=me.getX();
      int y=me.getY();

      if(x>=X0 && x<=X0+SIZE*9 && y>=Y0 && y<=Y0+SIZE*9){ //枠の範囲内
         i=(x-X0)/SIZE;
         j=(y-Y0)/SIZE;
         //出題モード --- グレイ以外で設定できる
         if(radio2[0].getState()){
            if(gray[j][i]==0)
               prob[j][i]=selected_number;
            else
               Toolkit.getDefaultToolkit().beep(); //ビープ音を鳴らす
         }
         //解答モード --- 問題、グレイ以外で設定できる
         if(radio2[1].getState()){
            if(prob[j][i]==0 && gray[j][i]==0)
               solu[j][i]=selected_number;
            else
               Toolkit.getDefaultToolkit().beep(); //ビープ音を鳴らす
         }
         //試行モード --- 問題、グレイ、解答以外で設定できる
         if(radio2[2].getState()){
            if(prob[j][i]==0 && gray[j][i]==0 && solu[j][i]==0)
               trial[j][i]=selected_number;
            else
               Toolkit.getDefaultToolkit().beep(); //ビープ音を鳴らす
         }
         repaint();
      }
   }

   public void mousePressed(MouseEvent me){}
   public void mouseReleased(MouseEvent me){}
   public void mouseEntered(MouseEvent me){}
   public void mouseExited(MouseEvent me){}

   public void paint(Graphics g){

      int i,j,ii,jj,k;
      int x,y;
      int single_number=0;

      //モードを表示する
      g.setFont(font0);
      if(radio2[0].getState()){
         g.setColor(Color.black);
         g.drawString("出題モード",X0+SIZE*10,Y0+50);
      }
      else if(radio2[1].getState()){
         g.setColor(Color.blue);
         g.drawString("解答モード",X0+SIZE*10,Y0+50);
      }
      else if(radio2[2].getState()){
         g.setColor(Color.red);
         g.drawString("試行モード",X0+SIZE*10,Y0+50);
      }

      //枠を描く
      g.setColor(Color.black);
      for(j=0;j<10;j++){
         g.drawLine(X0+j*SIZE,Y0,X0+j*SIZE,Y0+SIZE*9);
         if(j % 3 ==0)  //線を太くする
            g.drawLine(X0+1+j*SIZE,Y0,X0+1+j*SIZE,Y0+SIZE*9);
      }
      for(i=0;i<10;i++){
         g.drawLine(X0,Y0+i*SIZE,X0+SIZE*9,Y0+i*SIZE);
         if(i % 3 ==0)  //線を太くする
            g.drawLine(X0,Y0+1+i*SIZE,X0+SIZE*9,Y0+1+i*SIZE);
      }

      //グレイ領域をクリヤ
      for(j=0;j<9;j++)
         for(i=0;i<9;i++)
            gray[j][i]=0;

      //[取消]ボタン以外の場合にグレイ領域を設定する
      if(selected_number!=0){

         //グレイ領域を設定
         for(j=0;j<9;j++)
            for(i=0;i<9;i++){
               if(prob[j][i]==selected_number ||
                  solu[j][i]==selected_number ||
                  trial[j][i]==selected_number){

                  //横方向をグレイ表示
                  jj=j;
                  for(ii=0;ii<9;ii++)
                     gray[jj][ii]=1;

                  //縦方向をグレイ表示
                  ii=i;
                  for(jj=0;jj<9;jj++)
                     gray[jj][ii]=1;

                  //サブグリッドをグレイ表示
                  for(jj=j-(j % 3);jj<j-(j % 3)+3;jj++)
                     for(ii=i-(i % 3);ii<i-(i % 3)+3;ii++)
                        gray[jj][ii]=1;

               }
            }

         //グレイ領域を色付けする
         g.setColor(new Color(208,208,208));
          for(j=0;j<9;j++)
            for(i=0;i<9;i++){
               if(gray[j][i]==1)
                  g.fillRect(X0+2+i*SIZE,Y0+2+j*SIZE,SIZE-3,SIZE-3);
            }
      }

      //入力可能な数字を表示する
      for(j=0;j<9;j++)
         for(i=0;i<9;i++){
            //数字が入っていない
            if(prob[j][i]==0 && solu[j][i]==0 && trial[j][i]==0){

               for(k=0;k<10;k++)
                  number[k]=0;

               //横方向を調べる
               jj=j;
               for(ii=0;ii<9;ii++){
                  number[prob[jj][ii]]=1;
                  number[solu[jj][ii]]=1;
                  number[trial[jj][ii]]=1;
               }

               //縦方向を調べる
               ii=i;
               for(jj=0;jj<9;jj++){
                  number[prob[jj][ii]]=1;
                  number[solu[jj][ii]]=1;
                  number[trial[jj][ii]]=1;
               }

               //サブグリッドを調べる
               for(jj=j-(j % 3);jj<j-(j % 3)+3;jj++)
                  for(ii=i-(i % 3);ii<i-(i % 3)+3;ii++){
                     number[prob[jj][ii]]=1;
                     number[solu[jj][ii]]=1;
                     number[trial[jj][ii]]=1;
                  }

               //入力可能な数字(無かった数字)をマスの中に表示する
               g.setFont(font3);
               g.setColor(Color.black);
               int n=0;
               for(k=1;k<10;k++){
                  if(number[k]!=1){
                     x=X0+i*SIZE+5+((k-1) % 3)*SIZE/3;
                     y=Y0+j*SIZE+SIZE/3+((k-1)/3)*SIZE/3;
                     g.drawString(String.valueOf(k),x,y);
                     single_number=k;
                     n++;
                  }
               }

               //入力可能な数字が一個の場合は、
               //解答または試行として確定する
               if(n==1){
                  if(radio2[1].getState()){
                     solu[j][i]=single_number;
                     repaint();
                  }
                  if(radio2[2].getState()){
                     trial[j][i]=single_number;
                     repaint();
                  }
               }

            }

         }

      //グリッドに数字を描画する
      for(j=0;j<9;j++)
         for(i=0;i<9;i++){

            x=X0+(int)(0.2*SIZE)+i*SIZE;
            y=Y0+(int)(0.9*SIZE)+j*SIZE;

            //問題を描画する
            g.setFont(font1);
            if(prob[j][i]!=0){
               g.setColor(Color.black);
               g.drawString(String.valueOf(prob[j][i]),x,y);
            }

            g.setFont(font2);

            //解答を描画する
            if(solu[j][i]!=0){
               g.setColor(Color.blue);
               g.drawString(String.valueOf(solu[j][i]),x,y);
            }

            //試行を描画する
            if(trial[j][i]!=0){
               g.setColor(Color.red);
               g.drawString(String.valueOf(trial[j][i]),x,y);
            }

         }

   }

}

次のページ
プログラムの使い方

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Javaで学ぶグラフィックス処理連載記事一覧

もっと読む

この記事の著者

石立 喬(イシダテ タカシ)

1955年東京工大卒。同年、NECへ入社し、NEC初のコンピュータの開発に参画。磁気メモリ、半導体メモリの開発、LSI設計などを経て、1989年帝京大学理工学部教授。情報、通信、電子関係の教育を担当。2002年定年により退職し現在に至る。2000年より、Webサイト「Visual C++の勉強部屋」を公開。...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/539 2006/10/05 00:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング