HyperCard tribute

さんすうのお時間


 お子様向けの筆算型電卓システム、それが「さんすうのお時間」です。四則演算の計算のみで、計算可能な桁数も2桁と2桁の計算しかできませんが、勉強アシスト機能やユーザーインターフェースは十分な機能を持ち合わせていると思います。

お子様向け筆算型電卓「さんすうのお時間」
 ダウンロード(28KB)

さんすうのお時間の使い方


 「さんすうのお時間」には2つの機能を持っています。通常の計算をさせる「けいさん」機能と、ゲーム感覚で問題を解いていける「ゲーム」機能です。
 数字を打ち込むためには、画面下に用意された0から9までのボタンを式にドラッグする事で行います。ドラッグできるフィールドは、上のフィールド(あ)と下のフィールド(い)、そして横棒の下にあるフィールド(う)の3つです。
 画面の右の?マークを見て下さい。このマークは「あ」「い」「う」のフィールドをクリックすることでそのフィールドの横に移動します。実はこの?マークこそが、このスタックのポイントともいえる機能の一つなのです。
 実は、この?マークは答えの出る位置を表しています。すなわち、?マークのついていない2つのフィールドに数字を書き込むと、自動的に答えが?マークのフィールドに現れるということです。(下の例ではわかりやすくするために答えを計算させていませんが、本来ならば2つのフィールドに数字が打ち込まれたと同時に答えが計算されるようになっています)
 左の例の答えは「8」、右の例の答えは「3」となり、その答えが?マークの位置に表示されます。

 四則演算の変更は数字ボタンと同じで、ドラッグする事で行います。数字の打ち込みも、四則演算の変更もドラッグする事で行いますので、とても感覚的な操作方法と言えるでしょう。
 「ゲーム」機能は、自動作成された問題を解いていきます。こちらは通常の計算通り(あ)+(い)を計算します。
 ゲームをするには、まず画面左上のボタンをクリックして「ゲーム」の方を矢印が指している状態にします。次に、どの四則演算の計算ゲームをするかを選びます。選び方は先の「けいさん」機能と同じです。
 ペンギンをクリックするとゲームスタートです。「やさしい」「むずかしい」の2つのレベルの中から、どちらかを選ぶとゲームスタートです。画面上部に現れるペンギンが画面左から画面右へと移動し終わるとゲームは終了です。多くの問題が解けるようにがんばって下さい。



画面構成

(1)ボタン「ペンギン」
(2)ボタン「消しゴム」
(3)ボタン「全て消す」
(4)ボタン(上から順に)「+」「−」「×」「÷」
(5)フィールド「sisoku」
(6)フィールド「hyouji1」
(7)フィールド「hyouji2」
(8)フィールド「sum」
(9)ボタン「?」
(10)ボタン「0」「1」・・・「9」


(11)フィールド「score」
(12)フィールド「問題数」

 この他にフィールド「問題数」のグラフィックを隠すためのフィールド「隠しますよ」と、画面上部のスタートライン・ゴールラインを隠すためのフィールド「隠しますよ2」があります。


変数表
mode
ans_w
check_s
(現在「けいさん」「ゲーム」のどちらを選んでいるか)
(どこに計算結果を表示するか。上から1、2、3となります)
(ゲームを開始した時間)



ハンドラ「openStack」のスクリプト

 ハンドラ「openStack」で、初期の状態を作り上げます。
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
10 
11 
12 
13 
14 
15 
16 
17 
on openStack
  global starttime,mode,ans_w
  lock screen
  put the ticks into starttime
  go to cd "main"
  put 0 into mode
  put 3 into ans_w
  set the loc of cd btn "ペンギン" to 64,30
  hide cd fld "score"
  show cd btn "全て消す"
  showF "隠しますよ,隠しますよ2"
  set the loc of cd fld "?" to 390,241
  put 0 into cd fld "score"
  all_Empty
  put "ペンギンさんの背中を押してね!ゲームが始まるよ" into msg
  unlock screen with dissolve
end openStack

  • showF "隠しますよ,隠しますよ2"
     11行目では、ハンドラ「showF」を呼び出し、パラメータとして渡されたオブジェクトデータを元にフィールドオブジェクトを表示します。今回は、フィールド「隠しますよ」「隠しますよ2」を表示します。フィールド「隠しますよ」は、「問題数」のグラフィックを隠すため、フィールド「隠しますよ2」は、画面上部のスタートライン・ゴールラインを隠すためのに形式を「不透明」にして置いてあります。


  • all_Empty
     14行目で、ハンドラ「all_Empty」を呼び出します。ハンドラ「all_Empty」はフィールド「hyouji1」「hyouji2」「sum」にemptyを代入します。



    ハンドラ「hideB」のスクリプト

     ハンドラ「hideB」では、パラメータを元にボタンオブジェクトを隠します。パラメータは、コンマで区切って与えます。
     ハンドラ「hideB」の他には、フィールドを隠す「hideF」、ボタンを表示する「showB」、フィールドを表示する「showF」があります。違いは3行目のオブジェクト指定の部分だけです。
     1 
     2 
     3 
     4 
     5 
    
    on hideB data
      repeat with i=1 to the number of items of data
        hide cd btn (item i of data)
      end repeat
    end hideB
    


    ハンドラ「all_Empty」のスクリプト

     ハンドラ「all_Emptyはフィールド「hyouji1」「hyouji2」「sum」を空っぽにします。
     1 
     2 
     3 
     4 
     5 
    
    on all_Empty
      put empty into cd fld "hyouji1"
      put empty into cd fld "hyouji2"
      put empty into cd fld "sum"
    end all_Empty
    

     ハンドラ「all_Empty」は、スタックに書き込んでいます。



    ボタン「0」「1」・・・「9」のスクリプト
     1 
     2 
     3 
    
     4 
     5 
     6 
    
    on mouseUp
      push_b
    end mouseUp
    
    on mouseStillDown
      set the loc of the target to the mouseloc
    end mouseStillDown
    
     ボタン「0」「1」・・・「9」には、全て同じスクリプトが書き込んであります。ドラッグ可能なようにハンドラ「mouseStillDown」と、ドラッグし終わった時にハンドラ「push_b」を呼び出す「mouseUp」を用いました。



    ハンドラ「push_b」のスクリプト
     1 
     2 
     3 
     4 
     5 
    
     6 
     7 
     8 
     9 
    10 
    11 
    12 
    13 
    14 
    15 
    16 
    17 
    18 
    19 
    20 
    21 
    22 
    23 
    24 
    25 
    26 
    27 
    28 
    29 
    30 
    31 
    32 
    33 
    34 
    35 
    36 
    37 
    38 
    39 
    40 
    41 
    42 
    43 
    44 
    45 
    46 
    47 
    48 
    49 
    50 
    51 
    52 
    53 
    54 
    55 
    56 
    57 
    58 
    59 
    60 
    61 
    62 
    63 
    64 
    65 
    66 
    67 
    68 
    69 
    70 
    71 
    72 
    73 
    74 
    75 
    76 
    77 
    78 
    79 
    80 
    81 
    
    82 
    83 
    84 
    85 
    86 
    
    on push_b
      global mode
      set the hilite of target to true
      put the short name of target into n
      put item 1 of (the loc of target) into x
      
      if mode=0 then
        if loc of target is within rect of cd fld "hyouji1" then
          put (the number of chars of cd fld "hyouji1") into keta
          if 330 < x and x <= 370 then
            set the loc of target to 350,110
            put n into char keta of cd fld "hyouji1"
            play "click"
          else if 290 < x and x <= 330 then
            set the loc of target to 310,110
            if keta=2 then
              put n into char 1 of cd fld "hyouji1"
            else
              if cd fld "hyouji1"=empty then put 0 into cd fld "hyouji1"
              put n before cd fld "hyouji1"
            end if
            play "click"
          end if
          if char 1 of cd fld "hyouji1"="0" then
            put empty into char 1 of cd fld "hyouji1"
          end if
        else if loc of target is within rect of cd fld "hyouji2" then
          if mode>0 then exit push_b
          put (the number of chars of cd fld "hyouji2") into keta
          if 330 < x and x <= 370 then
            set the loc of target to 350,170
            put n into char keta of cd fld "hyouji2"
            play "click"
          else if 290 < x and x <= 330 then
            set the loc of target to 310,170
            if keta=2 then
              put n into char 1 of cd fld "hyouji2"
            else
              if cd fld "hyouji2"=empty then put 0 into cd fld "hyouji2"
              put n before cd fld "hyouji2"
            end if
            play "click"
          end if
          if char 1 of cd fld "hyouji2"="0" then
            put empty into char 1 of cd fld "hyouji2"
          end if
        end if
      end if
      if loc of target is within rect of cd fld "sum" then
        put (the number of chars of cd fld "sum") into keta
        if 330 < x and x <= 370 then
          set the loc of target to 350,240
          put n into char keta of cd fld "sum"
          play "click"
        else if 290 < x and x <= 330 then
          set the loc of target to 310,240
          if keta=3 then
            put n into char 2 of cd fld "sum"
          else if keta=2 then
            put n into char 1 of cd fld "sum"
          else
            if cd fld "sum"=empty then put 0 into cd fld "sum"
            put n before cd fld "sum"
          end if
          play "click"
        else if 250 < x and x <= 290 then
          set the loc of target to 270,240
          if keta=3 then
            put n into char 1 of cd fld "sum"
          else if keta=2 then
            put n before cd fld "sum"
          else
            if cd fld "sum"=empty then put 0 into cd fld "sum"
            put 0 before cd fld "sum"
            put n before cd fld "sum"
          end if
          play "click"
        end if
        repeat with i=1 to 2
          if char 1 of cd fld "sum"="0" then put empty into char 1 of cd fld "sum"
        end repeat
      end if
      
      set the hilite of target to false
      put the short name of target into n
      set the loc of target to n*45+50,312
      if mode=0 then sum
    end push_b
    
     このハンドラではドラッグされた数字ボタンの離された位置を調べ、フィールドの状態を調べ適切な位置に数字を代入します。まず、ボタンのy座標を調べ振り分けます。その後、x座標を調べ位置を特定します。
     数字を代入後、ボタンを元の位置に戻し、「けいさん」機能を使用しているときであれば、ハンドラ「sum」を呼び出し、計算結果を求めます。


  • set the hilite of target to true
     3行目でボタンのハイライトをオンにしています。オートハイライトをオンにしてしまうと、ドラッグ中ずっと反転してしまうことになるため、正しい位置にボタンをドラッグした時にも処理が実行されたのかと勘違いさせてしまう恐れがあるからです。正しい動作が行われたときにだけ、ユーザーに反応を返すべきですので、このようにスクリプト中でハイライトをオンにしているわけです。


  • if mode=0 then
     6〜47行目は、「けいさん」機能を使用しているときのみ処理されます。なぜならば、「ゲーム」機能の時に問題が勝手に変更されてしまうのを防ぐためです。


  • if loc of target is within rect of cd fld "hyouji1" then
     7〜25行目では、一番上のフィールドを調べています。どの位置に数字を代入するかを調べ適切な位置に代入します。

    代入された位置が1の位の時
     上の例の通り、1の位に代入された場合は、そのフィールドの桁数番目の文字に代入すればいいことになります。

    代入された位置が10の位の時
     左の例のように、現在の桁数が2桁であれば数字は1文字目に代入されることになります。桁数が1桁であれば、数字は1文字目の前につけ加えられます。もしフィールドが空っぽだったとしたら、「0」を代入しその後、1文字目の前につけ加えます。


  • if char 1 of cd fld "hyouji1"="0" then
     23〜25行目で1文字目の文字を調べ、それが「0」であれば消去します。
     次に、7〜25行目と同じ事を繰り返し、真ん中、下のフィールドにも数字が代入されるようにします。


  • set the loc of target to n*45+55,315
     84行目ではボタンを元の位置に戻しています。ボタンは規則的に並んでいますので、このように計算式を作り上げることが可能なわけです。



    ハンドラ「sum」のスクリプト
     1 
     2 
     3 
     4 
     5 
     6 
     7 
     8 
     9 
    10 
    11 
    12 
    13 
    14 
    15 
    16 
    17 
    18 
    19 
    20 
    21 
    22 
    23 
    24 
    25 
    26 
    27 
    28 
    
    29 
    30 
    31 
    32 
    33 
    34 
    35 
    36 
    37 
    38 
    39 
    40 
    41 
    42 
    43 
    44 
    45 
    46 
    47 
    48 
    49
    
    on sum
      global ans_w,mode,check_s
      if ans_w=1 then
        put cd fld "hyouji2" into n1
        put cd fld "sum" into n2
        put "hyouji1" into name
      else if ans_w=2 then
        put cd fld "hyouji1" into n1
        put cd fld "sum" into n2
        put "hyouji2" into name
      else if ans_w=3 then
        put cd fld "hyouji1" into n1
        put cd fld "hyouji2" into n2
        put "sum" into name
      end if
      if cd fld "sisoku"="+" then
        if ans_w=3 then put -1*n1 into n1
        put n2-n1 into ans
      else if cd fld "sisoku"="−" then
        if ans_w=1 then put -1*n2 into n2
        put n1-n2 into ans
      else if cd fld "sisoku"="×" then
        if ans_w=3 then put 1/n1 into n1
        put n2/n1 into ans
      else if cd fld "sisoku"="÷" then
        if ans_w=1 then put 1/n2 into n2
        put n1/n2 into ans
      end if
      
      if mode<>0 then
        if ans=cd fld "sum" then
          put cd fld "score"+10 into cd fld "score"
          put "正解" into cd fld "info"
          show cd fld "info"
          play "paro" "ee cq"
          wait 1 second
          hide cd fld "info"
          sakusei
        else
          put cd fld "score"-5 into cd fld "score"
          put "間違っているよ" into cd fld "info"
          show cd fld "info"
          play boing
          wait 1 second
          hide cd fld "info"
        end if
      else
        put ans into cd fld name
      end if
    end sum
    

  • if ans_w=1 then
     3〜6行目では、一番上のフィールドに?マークがあるときのデータ代入を行っています。同じように7〜10行目で真ん中のフィールド、11〜14行目で一番下のフィールドの場合の処理をしています。


  • if ans_w=3 then put -1*n1 into n1
     17行目ではちょっとしたテクニックを用いて、どこの位置に?マークがあったとしても同じ計算式で計算できるように変更を加えています。ここでは、このif節を用いて説明します。現在の状況は、四則演算「+」の場合で、計算式はn2-n1です。


     3〜15行目で、ans_wの値によってデータを代入しました。n2-n1を計算してみて下さい。?マークの位置の答えがちゃんと計算されています。
     ans_w=1の答えは8-5=3となり、ans_w=2の答えは8-3=5となります。


     ans_w=3ですので、n1の値を-n1に変更しました。それでは、計算してみます。
     答えは、5-(-3)=8となります。つまり、マイナスを掛けることで、結果的に足し算をさせたというわけです。
     この考え方を用いて、「+」だけでなく、「−」「×」「÷」も1つの式で計算できるように変更を加えてるのが、この行ということになります。


     29〜48行目では、「ゲーム」機能時の答えチェックをしています。正解であれば次の問題を作成するため、ハンドラ「sakusei」を呼び出します。



    フィールド「hyouji1」「hyouji2」「sum」のスクリプト

     フィールド「hyouji1」「hyouji2」「sum」をクリックすると?マークが移動し計算結果を求める位置が変わります。?マーク以外の2つのフィールドから答えを計算するための準備段階のハンドラと言えるでしょう。  
     1 
     2 
     3 
     4 
     5 
     6 
     7 
    
    on mouseup
      global ans_w,mode
      if mode<>0 then exit mouseup
      put 1 into ans_w
      set the loc of cd fld "?" to 390,104
      all_Empty
    end mouseup
    

  • put 1 into ans_w
     ans_wは計算結果を求める位置を表しています。?マークが1番上にあればans_wは1となり、真ん中にあればans_wは2、下にあればans_wは3となります。


  • set the loc of cd fld "?" to 390,104
     ?マークを移動します。
     この4〜5行を少し変えたハンドラがフィールド「hyouji2」「sum」に使っています。
    ・フィールド「hyouji2」
      put 2 into ans_w
      set the loc of cd fld "?" to 390,174
    ・フィールド「sum」
      put 3 into ans_w
      set the loc of cd fld "?" to 390,241


  • all_Empty
     6行目はハンドラall_Emptyを呼び出します。?マークの位置を変更するわけですから、どれとどれの計算をすればいいのかわからなくなってしまいます。そのため一度、フィールド「hyouji1」「hyouji2」「sum」の値をリセットするわけです。



    ハンドラ「sisoku_kirikae」のスクリプト

     四則演算の「+」「−」「×」「÷」をフィールド「sisoku」にドラッグした時、すなわち四則演算を切り替えたときに、このハンドラが呼び出されます。
     1 
     2 
     3 
     4 
     5 
     6 
     7 
     8 
     9 
    10 
    11 
    
    on sisoku_kirikae
      global mode
      put the short name of target into n
      if loc of target is within rect of cd fld "sisoku" then
        set the loc of cd btn n to 180,170
        put n into cd fld "sisoku"
        play "click"
      end if
      set the loc of cd btn n to 90,((cd btn n)*25+55)
      if mode=0 then sum
    end sisoku_kirikae
    

  • put the short name of target into n
     targetは、このハンドラを呼び出したオブジェクトを示しています。そのオブジェクトの名前を変数 n に代入します。つまり、「+」「−」「×」「÷」のいずれかが入ることになります。


  • set the loc of cd btn n to 90,((cd btn n)*25+55)
     この9行目には「cd btn n」が2回出てきますが、1回目のそれと2回目のそれでは意味が違います。
     最初の「cd btn n」はオブジェクトをあらわしており、このオブジェクトをどこにsetするかという意味で使っています。そして次の「cd btn n」はオブジェクトではなく「cd btn n」のコンテナの内容を意味しています。(これについては「小技編」の「ポップアップメニューの追加・削除」を見て下さい)
     ボタン「+」「−」「×」「÷」のコンテナにはそれぞれ「3」「4」「5」「6」が入っています。これにより、それぞれのy座標は130、155、180、205となります。
    「cd btn n(ボタンn)」
      の
    「the loc(中心座標)」
      を
    「90,((cd btn n)*25+55) (90,ボタンnのコンテナ*25+55)」
      に
    「set 〜 to 〜 (設定する)」





    ボタン「ペンギン」のスクリプト

     ゲームをスタートさせるためには、ペンギンをクリックします。本来ならばスタートボタンなどを用意して「スタート」という文字でスタートボタンの存在をアピールした方がわかりやすいのですが、今回は敢えてペンギンをクリックするとゲームが始まるという風にしてみました。
     その理由は、ペンギンが左から右へ動いている間がゲーム中であるからです。つまり、ゲームを始めるにはペンギンに動いてもらわなければならないので、「動いて」とペンギンの背中を押すわけです。
     しかし、このままではペンギンをクリックするとゲームが始まるということがわかりませんので、「ペンギンさんの背中を押してね!ゲームが始まるよ」という説明をハンドラ「openStack」で表示するようにしています。説明書を用意して「ゲームをスタートさせるにはペンギンをクリックする」と書けば簡単なのですが、それはできる限りやめるべきです。使い方がわからなければ説明書を見てくれ、というのは制作者のエゴです。あるソフトや商品を見て、どこをどうすれば自分のしたいことができるのかが、ある程度予測のつく物でなければユーザーインターフェースに問題があると言われても仕方ないのではないでしょうか。このことに気を付けない限り、いつまでたってもコンピュータはコンピュータのままだと思いますので、今回は少しでもコンピュータを感じさせないためにこのような方法を取った次第です。
     1 
     2 
     3 
     4 
     5 
     6 
     7 
     8 
     9 
    10 
    11 
    12 
    13 
    14 
    15 
    16 
    17 
    18 
    19 
    20 
    21 
    22 
    23 
    24 
    25 
    26 
    27 
    28 
    29 
    30 
    31 
    32 
    33 
    34 
    35 
    36 
    37 
    38 
    39 
    40 
    41 
    42 
    
    on mouseUp
      global ans_w,check_s,mode
      if check_s is empty then
        set the loc of cd btn "ペンギン" to 64,30
        answer "どっちのレベルにしますか?" with "やさしい" or "むずかしい" or "キャンセル"
        if it is "キャンセル" then exit mouseUp
        lock screen
        if it is "やさしい" then put 1 into mode
        else put 10 into mode
        put 3 into ans_w
        hideB "+,−,×,÷,全て消す"
        hideF "隠しますよ,隠しますよ2"
        show cd btn "答えあわせ"
        showF "score,問題数"
        set the loc of cd fld "?" to 390,241
        put 0 into cd fld "score"
        put 1 into cd fld "問題数"
        all_Empty
        put "ゲームをやめたいときはペンギンさんを押してね" into msg
        unlock screen with dissolve
        lock screen
        sakusei
        put cd fld "問題数"-1 into cd fld "問題数"
        play "paro" "c c c gs"
        wait until the sound is done
        unlock screen with dissolve
        put the ticks into check_s
      else
        lock screen
        put 0 into mode
        put 3 into ans_w
        hide cd btn "答えあわせ"
        hideF "score,問題数"
        showB "+,−,×,÷,全て消す"
        showF "隠しますよ,隠しますよ2"
        set the loc of cd btn "ペンギン" to 64,30
        all_Empty
        put "ペンギンさんの背中を押してね!ゲームが始まるよ" into msg
        put empty into check_s
        unlock screen with dissolve
      end if
    end mouseUp
    

     ペンギンをクリックしたときゲーム中であればゲームを終了し、そうでなければゲームを開始します。ゲーム中であるかどうかの判断は、変数check_sに値が入っているかで判断しています。



    ハンドラ「sakusei」のスクリプト

     フィールド「問題数」の値を1つ増やし、問題を作成します。
     1 
     2 
     3 
     4 
     5 
     6 
     7 
     8 
     9 
    10 
    11 
    12 
    13 
    14 
    15 
    16 
    17 
    18 
    19 
    20 
    
    on main
      global mode,check_s
      lock screen
      put empty into cd fld "sum"
      put 1+cd fld "問題数" into cd fld "問題数"
      if cd fld "sisoku"="+" then
        put random(mode*10)+mode into cd fld "hyouji1"
        put random(mode*10)+mode into cd fld "hyouji2"
      else if cd fld "sisoku"="−" then
        put random(mode*10)+5 into cd fld "hyouji2"
        put random(mode*10)+cd fld "hyouji2" into cd fld "hyouji1"
      else if cd fld "sisoku"="×" then
        put random((round(mode/2)+1)*9) into cd fld "hyouji1"
        put random((round(mode/2)+1)*9) into cd fld "hyouji2"
      else if cd fld "sisoku"="÷" then
        put random((round(mode/3)+1)*9) into cd fld "hyouji2"
        put random((round(mode/3)+1)*9)*cd fld "hyouji2" into cd fld "hyouji1"
      end if
      unlock screen
    end main
    



    ハンドラ「idle」のスクリプト

     ペンギンを右に移動させ、ゴールラインを超えたらゲームを終了します。
     1 
     2 
     3 
     4 
     5 
     6 
     7 
     8 
     9 
    10 
    11 
    12 
    13 
    14 
    15 
    16 
    17 
    18 
    19 
    20 
    21 
    22 
    23 
    24 
    
    on idle
      global check_s,mode
      if check_s is not empty then
        set the loc of cd btn "ペンギン" to 64+round((the ticks-check_s)/10),30
        if item 1 of (the loc of cd btn "ペンギン")>=424 then
          put "GameOver !!" into cd fld "info"
          show cd fld "info"
          wait 1 second
          hide cd fld "info"
          lock screen
          put 0 into mode
          put 3 into ans_w
          set the loc of cd btn "ペンギン" to 64,30
          hide cd btn "答えあわせ"
          hideF "score,問題数"
          showB "+,−,×,÷,全て消す"
          showF "隠しますよ,隠しますよ2"
          all_Empty
          put "ペンギンさんの背中を押してね!ゲームが始まるよ" into msg
          put empty into check_s
          unlock screen with dissolve
        end if
      end if
    end idle