ゲーム開発ラボ

視覚的に楽しいアプリやゲーム開発をしながら,Javaやjavascriptを楽しく学んでいきます

iPhoneの計算機アプリをつくる-3

前回の記事では0~9の数字を押せるアプリを作りました
processing-p5.hateblo.jp

今回は四則演算のボタンを追加し,計算ができるようにします
下図が今回作るアプリです

f:id:filopodia:20201114003704g:plain


現時点では小数点ボタンやACボタンはなく,整数(int型)の四則演算しかできません
コードは以下となります

String dispVal = "0"; // 画面表示用文字列
String currOpr = "="; // 押された演算子の種類
float val = 0; // 計算結果
boolean afterOpr = false; // 直前に演算子を押したか

// ボタン設定
Button[] buttons = new Button[15]; // ボタン型配列
String[] opr = {"÷", "×", "-", "+", "="}; // 演算子
int[] co_x = {50, 120, 190, 280}; // ボタンのx座標
int[] co_y = {240, 310, 380, 450, 520}; // ボタンのy座標

void setup(){
  size(350, 600);
  background(220);
  textAlign(CENTER, BASELINE);
  buttons[0] = new NumButton(0, co_x[0], co_y[4]); // 0のボタンのインスタンス
  // 1~9のボタンのインスタンス
  for(int i=1; i<10; i++){
    buttons[i] = new NumButton(i, co_x[(i-1)%3], co_y[3-(i-1)/3]);
  }
  // 演算子ボタンのインスタンス
  for(int i=10; i<buttons.length; i++){
    buttons[i] = new OprButton(opr[i-10], co_x[3], co_y[i-10]);
  }
}

void draw(){
  background(220);
  fill(0);
  textSize(40);
  text(dispVal, width/2, 160);
  
  for(int i=0; i<buttons.length; i++){
    buttons[i].display();
  }
}

void mouseClicked(){
  for(int i=0; i<buttons.length; i++){
      buttons[i].update();
  }
}

// 抽象クラス
abstract class Button{
  boolean MouseHover = false;
  int col = 255; // ボタンの色
  int bx; // ボタンのx座標
  int by; // ボタンのy座標
  int br = 30; // ボタンの半径
  int num;
  String str;
  
  abstract void update(); // 抽象メソッド
  
  void display(){
    if(isMouseHover()) col=180;
    else               col=255;
    fill(col);
    noStroke();
    circle(bx, by, 2*br);
    fill(0);
    textSize(30);
    text(str, bx, by+10);
  }
  
  boolean isMouseHover(){
    if(dist(mouseX, mouseY, bx, by)<30) MouseHover = true;   
    else                                MouseHover = false;
    return MouseHover;
  }  
}

class NumButton extends Button{  
  // constructor
  NumButton(int _num, int _bx, int _by){
    bx = _bx;
    by = _by;
    num = _num;
    str = Integer.toString(num);
  }  
  // function
  @Override void update(){
    if(isMouseHover()){
      if(afterOpr)
        {
          dispVal = "";
        }
      if(dispVal.length()>0 && dispVal.charAt(0) == '0') dispVal = str;
      else dispVal += str;
    }
  }  
}

class OprButton extends Button{  
  // constructor
  OprButton(String _str, int _bx, int _by){
    bx = _bx;
    by = _by;
    str = _str;
  }  
  // function
  @Override void update(){
    if(isMouseHover()){
      switch(currOpr){
        case "÷" :
          val /= Integer.parseInt(dispVal);
          break;
        case "×" :
          val *= Integer.parseInt(dispVal);
          break;
        case "-" :
          val -= Integer.parseInt(dispVal);
          break;
        case "+" :
          val += Integer.parseInt(dispVal);
          break;  
        default :
          val = Float.parseFloat(dispVal);
          break;
      }
      afterOpr = true;
      currOpr = str;
      dispVal = Float.toString(val);
      println(val);
    }
  }  
}


上のコードを詳しくみてみましょう

ボタンには数字入力ボタンと演算子入力ボタンの2種類があります
これらのボタンは表示方法は同じですが,マウスクリック時の挙動が少し異なります
そこで,抽象クラスButtonを用意し,同じ挙動を示す部分は抽象クラス内で定義を行い,挙動が異なる部分は抽象メソッドとします
抽象メソッドは,抽象クラスを継承した子クラスNumButton, OprButton内でそれぞれ定義するようにします

// 抽象クラス
abstract class Button{
  
  abstract void update(); // 抽象メソッド
  
  void display(){ // ボタンを表示する関数
  }
  
  boolean isMouseHover(){ // マウスがボタン上にあることをチェックする関数
  }  
}

class NumButton extends Button{  // 数字入力ボタンクラス

  NumButton(int _num, int _bx, int _by){ // コンストラクタ
  }  

  @Override void update(){ // マウスクリック時に数字を入力する
  }  
}

class OprButton extends Button{  // 演算子入力ボタンクラス

  OprButton(String _str, int _bx, int _by){ //コンストラクタ
  }  

  @Override void update(){ // マウスクリック時に演算子の処理を行う
  }
}


このように抽象クラスと子クラスを用意することで, NumButtonとOprButtonという異なる挙動を示すクラスを一緒に扱うことができるようになります
次回は少数点やACボタンを実装し, デザイン全体の見た目を整える作業を行います