2014年5月5日 星期一

App Inventor 2 的範例程式 -24 points

 24 points是一個運用快速心算將四個數字進行四則運算結果為24的數學遊戲。

遊戲內容:
玩家運算四個數字(四個數字都要用到)使得運算結果為24,共十題,每答對一題得10分,總分100分。

程式功能分析:
設計一個遊戲,運算四個數字始結果為24,答對一題加10分,並進入下一題,直到完成10道題目則結束遊戲。按Retry此題目重新開始。按Skip跳過此題進入下一題。按Done結束遊戲。結束遊戲後出現得分,按再來一次的按鈕回到主頁且可繼續遊戲。


開發步驟:  
步驟一請先新增一個名稱為「points24」的專案,按下 OK 後,即可進入 App Inventor  Designer 視窗。(註:專案名稱開頭不能是數字;專案名稱中可用底線但不能有空格或其它特殊字元)

步驟二: 將排版編制如下圖,此頁面會出現遊戲名稱、遊戲說明以及開始按鈕(重新命名為StartB),最後將此頁重新命名為index,並且隱藏(hidden)。

步驟三將排版編制如下圖,此頁面會出現遊戲名稱、四個數字按鈕(重新命名為n1、n2、n3、n4)、四個運算按鈕(重新命名為 add (加)、subtract (減)、multiply (乘)、divide (除) )、記分板(包含時間、完成題數、分數、未完成題數)、Skip按鈕(重新命名為 skip)、Done按鈕(重新命名為 done)、Retry按鈕(重新命名為 retry),最後將此頁重新命名為p1,並且隱藏(hidden)。
(註:記分板重新命名 timeLable、timeNumber、downLable、downNumber、scoreLable、scoreNumber、unsolovedLable、unsolovedNmber)



步驟四 將排版編制如下圖,此頁面會出現遊戲名稱、遊戲分數(重新命名為score)、時間(重新命名為time)、已完成數(重新命名為finish)、未完成數(重新命名為unfinish)、答對率(重新命名為rate)、回饋(重新命名為ans)及再來一次按鈕(重新命名為restart),最後將此頁重新命名為p2,並且隱藏(hidden)。
(註:回饋是指如果玩家分數100分回饋呈現「你超強的!」,如果玩家分數10分呈現「你超弱!」等等)

步驟五:將主頁(index)顯示(showing),到視窗左側的元件面板(Palette)中,點選使用者介面(User Interface)中的時鐘(Clockl)元件,按住滑鼠不放將其拖曳至預覽(Viewer)中,完成後預覽(Viewer)下會出現一個時鐘(Clock1)。


可加入背景及其他圖片使此遊戲更加精美。
完成頁面排版


由於程式較多因此提供版面aia檔下載

接下來我們就可以開始編寫程式囉!請點擊右上方的Blocks切換到程式頁面。

步驟六:請在左側Blocks選單中點選Built-in下的Variables,在彈出的拼圖式程式區塊中選取 initialize global name to,置於預覽視窗中,並將"name "改為" time1 "嵌入數字"0"。


解釋:在步驟六中,設變數time1(表示紀錄一開始讀取時間),初始值為0。

步驟七:請依照步驟六的動作執行,加入變數record1、record2、method、question、ckN1、ckN2、ckN3、ckN4、gain,完成所有需要的變數。
解釋:
變數record1(表示紀錄點擊的第一個算術運算值,初始值為-1是避免第一個算術運算值為0),變數record2(表示紀錄點擊的第二個算術運算值,初始值為0)
變數method(表示運算紀錄,如加=1,減=2,乘=3,除=4,初始值為0)
變數question(表示題目第幾題,初始值為1,從第一題開始)
變數ckN1(表示n1按鈕有無被點擊,如ckN1=0表示沒有被點擊,ckN1=1表示被點擊了,初始值為0),變數ckN2(表示n2按鈕有無被點擊,初始值為0),變數ckN3(表示n3按鈕有無被點擊,初始值為0)變數ckN4(表示n4按鈕有無被點擊,初始值為0)
變數gain(表示獲得多少分,初始值為0)

步驟八:請在左側Blocks選單中點選Screen1下的Clock1,在彈出的拼圖式程式區塊中選取 when Clock1.Timer do,置於預覽視窗中。



步驟九:請在左側Blocks選單中點選Screen1下的Clock1,在彈出的拼圖式程式區塊中選取 call Clock1 .SystemTime(呼叫手機現在時間),置於預覽視窗中。


步驟十:點選Math,選取-,將call Clock1.Now卡入其中。接著點選Variables,選取get,卡入-後,並將選項點開設為" global time1 "。

解釋:call Clock1.Now會一直回傳是變動的,減掉一開始紀錄的時間就會變成計時器(以毫秒為單位)。

步驟十一:請在左側Blocks選單中點選Built-in下的Math,選取modulo of  /  (取餘數)。


步驟十二:點擊下拉按鈕將modulo更改為quotient(取商)。


步驟十三:將call Clock1.Now - get goble time1卡入quotient of 前。接著點選Math,選取0,卡入÷後,並將"0 "改為" 1000 "。
解釋:將時間單位從毫秒變成秒。

步驟十四:將左側Blocks選單中點選p1下的timeNumber,選取timeNumber.Text,卡入when Clock1.Timer do;將quotient of ...嵌入,完成計時器。

步驟十五:將左側Build-in選單中點選Procedures,選取to procedure do,至於預覽畫面,重新命名為testquestion。

解釋:副程式testquestion用於當換題時顯示n1、n2、n3、n4的題目。當要用此副程式 Call於Procedures中。

步驟十六:請在左側Blocks選單中點選Built-in下的Control,在彈出的拼圖式程式區塊中選取if then,拉至 to testquestion do之下,點擊左上的藍色方塊將else if 嵌入if ,嵌入10個else if 




步驟十七:請在左側Blocks選單中點選Control,選取 if then。再點選Math,選取=,卡在if右方。接著點選Variables,選取get,卡入=前,並將選項點開設為"global question "。最後點選Math,選取0,卡入=後,並將"0 "改為"1"。




步驟十八:請在左側Blocks選單中點選p1下的n1,選取set n1.Text to。再點選Built-in下的Math,選取 "0",卡入其中,並將"0 "改為"1"。在下面連接set n2.Text to 加入數字4。在下面連接set n3.Text to 加入數字1。在下面連接set n4.Text to 加入數字6。
解釋:第一題題目是1,4,1,6。

步驟十九:請依照步驟十八的動作執行,將題號跟題目更改嵌入完成至第十題。
題目:第二題(1,2,4,12),第三題(5,5,13,13),第四題(1,2,4,12),第五題(1,2,5,10),第六題(1,4,5,8),第七題(4,7,10,12),第八題(1,5,9,12),第九題(6,10,11,12),第十題(2,6,9,10)。




步驟二十:
點選Math,選取=,卡在else if右方。接著點選Variables,選取get,卡入=前,並將選項點開設為"global question "。點選Math,選取0,卡入=後,並將"0 "改為"11"。
點選Variables,選取set,卡入then後,並將選項點開設為"global question "。點選Math,選取0,卡入=後,並將"0 "改為"10"。
點選Screen1下的Clock1,選取set Clock1.TimerEnabled to 嵌入,點選Logic,選取false,卡入其中。
點選Screen1下的p1,選取set p1.Visible to 嵌入,點選Logic,選取false,卡入其中。複製一次,將名稱更改為set p2.Visible to ,更改true為false。
點選p2下的score,選取set score.Text to 嵌入,點選p1下的scoreNumber.Text,卡入其中。複製三次,將名稱分別更改為set time.Text to、set finish.Text to、set unfinish.Text to ,並將後
面連接分別改為p1的timeNumber.Text、downNumber.Text、unsolovedNumber.Text
點選p2下的rate,選取set rate.Text to 嵌入;點選Text下的join,卡入其中;點選Math下的 × ,卡入其中;點選Math下的 0 ,改為10,卡入 × 後 ;點選Math下的 / ,卡入 × 前;點選p1下的scoreNumber.Text,卡入/前;點選Variables,選取get,卡入/後,並將選項點開設為"global question ";點選Text下的" ",更改為"%",卡入其中
在左側Blocks選單中點選Built-in下的Control,在彈出的拼圖式程式區塊中選取if then,拉至 set rate.Text下,點擊左上的藍色方塊將一個else if及一個else 嵌入if ,if後卡入Math的>=,數字90卡在>=後,點選p1下的scoreNumber,選取scoreNumber.Text 嵌入>=前。複製一次,更改數字為60, 卡入else if。
點選p2下的ans,選取set ans.Text to ;點選Built-in下的Tex,選取" "更改文字為"你超強!!",複製兩次,分別更改文字為"還OK啦!"、"不及格"卡入其中。
完成副程式testquestion。

解釋:當到題目數等於11時,代表結束:將題目數回到10(用來計算答對率),將時鐘停止(使計時器就停止),將p1.Visible隱藏使p2.Visible出現,設置p2頁面的分數,所用時間,完成題數,未完成題數、答對率(得分除以題數乘10等於答對率)、回饋(當分數大於90時出現"你超強!!",分數介於90到60出現"還OK啦!",當分數小於60時出現"不及格")。

步驟二十一:
點選p1下的add,選取when add.Click do置於預覽視窗中,點選Variables,選取set,卡入do後,並將選項點開設為"global method "。點選Math,選取0,卡入to後,並將"0 "改為"1"。
再複製3個,將名稱分別改為subtract、multiply、divide以及將數字分別改為2,3,4。

解釋:使變數method更改,紀錄運算方式。

步驟二十二:
點選index下的startB,選取when startB.Click do置於預覽視窗中。
點選index,選取set index.Visible to ,卡入do後點選Logic,選取false,卡入其中。複製一次將名稱改為set p1.Visible to並將true改為false。
點選Variables,選取set,並將選項點開設為"global time1 "。點選Screen1下的Clock1,選取call Clock1.System嵌入
點選Screen1下的Clock1,選取set Clock1.TimerEnable to嵌入點選Logic,選取true,卡入其中。
點選Variables,選取set,並將選項點開設為"global question"。點選Math,選取0,卡入to後,並將"0 "改為"1"
點選Produces,選取call testquestion。
點選Variables,選取set,並將選項點開設為"global question"。點選Math,選取0,卡入to後
點選p1下的timeNumber.Text,卡入其中。點選Math,選取0,卡入to後。複製三次,將名稱分別改為downNumber.Text、scoreNumber.Text、unsolovedNumber.Text,最後將unsolovedNumber.Text後面的數字改為10

完成startB按鈕。
解釋:當startB被點擊時,index頁面隱藏,p1頁面出現,開始遊戲;time1是紀錄一開始的時間,時鐘Clock1開始運作;設題目數為1,呼叫testquestion使得n1,n2,n3,n4題目為第一題。設獲得分數初始值為0(使如果再玩一次時不會出現上一次玩的得分)。設置p1頁面的時間、完成題數、分數皆為0,未完成題數為10。

步驟二十三:
點選p1下的n1,選取when n1.Click do置於預覽視窗中。
點選Variables,選取set,並將選項點開設為"global ckN1 ",遷入數字1。
請在左側Blocks選單中點選Built-in下的Control,在彈出的拼圖式程式區塊中選取if then,拉至 set goble ckN1 to 1下,點擊藍色框框加入else。
點選Math下的= ,卡入if後點選Variables,選取get,並將選項點開設為"global record1",卡入=前;點選p1下的s點選Math下的 0 ,改為-1,卡入 = 後 
點選Variables,選取set,並將選項點開設為"global record1",卡入then點選p1下的n1,選取 n1.Text,卡入其中。
解釋:ckN1=1代表n1按鈕被點擊。record1=-1代表之前沒有數字被點擊,record1記錄第一個被點擊的數字值(這裡是n1)

步驟二十四:
點選Variables,選取set,並將選項點開設為"global record2",卡入else點選p1下的n1,選取 n1.Text,卡入其中。
請在左側Blocks選單中點選Built-in下的Control,在彈出的拼圖式程式區塊中選取if then,拉至 set goble ckN1 to 1下,點擊藍色框框加入3個 if else。
點選Math下的= ,卡入if後點選Variables,選取get,並將選項點開設為"global method",卡入=前;點選Math下的 0 ,改為1,卡入 = 後 。再複製三次,分別將數字改為2、3、4,並且卡入下方的三個else if。
點選Variables,選取set,並將選項點開設為"global record1",卡在第一個then後,點選Math的 +,選取get,並將選項點開設為"global record1"卡入+前,選取get,並將選項點開設為"global record2"卡入+後;在複製三次,分別將運算更改為 - 、 ×、 /,並且卡入下方的三個then。

解釋:record2記錄第二個被點擊的數字值(這裡是n1),如果method=1(+),record1和record2相加並回傳record1,使record1為相加後的值。method=2是相減,method=3是相乘,method=4是相除。

步驟二十五:
請在左側Blocks選單中點選Built-in下的Control,在彈出的拼圖式程式區塊中選取if then,拉至 then下,點擊藍色框框加入2個 if else。
請在左側Blocks選單中點選Built-in下的Logic,在彈出的拼圖式程式區塊中選取and,拉至 if,點選Math下的 = ,卡入其中;點選Math下的 0 ,改為2,卡入 = 後 ;點選Math下的+ ,卡入=前;點選Variables,選取grt,並將選項點開設為"global ckN1",卡入+前;點選Variables,選取get,卡入+後,並將選項點開設為"global ckN2 ";點選Math下的 = ,卡入and後,更改為≠,點選Math下的 0 ,卡入後,點選Variables,選取get,並將選項點開設為"global 
method",卡入前。複製兩次,更改global ckN2分別為ckN3、ckN4,嵌入兩個else if 中。
點選p1下的n1 ,選set n1.Text,卡入then後;點選Variables,選取get,卡入其中,並將選項點開設為"global  record1 "複製兩次,嵌入兩個then後。
點選p1下的n2 ,選set n2.Text,卡入then後;點選Logic,選取false,卡入to後。複製兩次,分別將名稱更改為n3.Text、n4.Text

解釋:當n1和n2都被點擊且有運算方法時,n1的值會成為先前已運算過的record1值,而n2按鈕消失。當n1和n3被點擊,以及n1和n4被點擊皆是如此。

步驟二十六:
點選Variables,選取set,卡入then下,並將選項點開設為"global recond1 ",嵌入數字1。
點選Variables,選取set,卡入then下,並將選項點開設為"global ckN1 ",嵌入數字0。複製四次,將名稱分別改為ckN2、ckN3、ckN4、method。


解釋:此按鈕為第二個數值,無論是否完成數值運算,record、ckN1、ckN2、ckN3、ckN4、method都要初始化,使下一次運算不會出錯。


步驟二十七:
請在左側Blocks選單中點選Built-in下的Control,在彈出的拼圖式程式區塊中選取if then,拉至 then外。
請在左側Blocks選單中點選Built-in下的Logic,在彈出的拼圖式程式區塊中選取and,拉至 if後
點選Math下的 = ,卡入其中;點選Math下的 0 ,改為24,卡入 = 後 ;點選p1下的n1,選取 n1.Text,卡入= 前;and後,點選Math下的 = ,點選p1下的n2,選取 n2.Visible,卡入 = 前 ;選Logic的false,卡入 = 後重複 n2.Visible = fasle兩次,將名稱改為n3、n4用and連接起來
點選p1下的downNumber,選取set downNumber.Text to,卡入 then後,點選Math下的+ ,卡入其中將數字1卡在+後,點選p1下的downNumber,選取 downNumber.Text 卡在+前。
請在左側Blocks選單中點選p1下的n1,選取set n1.Visible to;點選Logic,選取 true,卡入其中,複製三次,分別將名稱更改為 n2.Visible、 n3.Visible n4.Visible
點選Variables,選取set,並將選項點開設為"global gain ",嵌入Math的+,在卡入數字10在+後;選取get,卡入+前並將選項點開設為"global gain "
點選p1下的scoreNumber,選取set scoreNumber.Text to;點選Variables,選取get,將選項點開設為"global gain ",卡入其中。
點選Variables,選取set,並將選項點開設為"global question",嵌入Math的+,在卡入數字1在+後;選取get,卡入+前並將選項點開設為"global question "
點選p1下的unsolovedNumber,選取set unsolovedNumber.Text to;嵌入Math的-,將數字11卡入-前;點選Variables,選取get,將選項點開設為"global question",卡入-後。
點選Produces,選取call testquestion。
完成n1按鈕。


解釋:當n1值為24且已經沒有其他按鈕時,進入下一題,將完成數加1,n1、n2、n3、n4按鈕重新出現,得分數加10,題目數加1,未完成數(11題減已完成數),題目值更新。


步驟二十八:請依照步驟二十三到二十七的動作執行,將紅框中的名稱稍作更改,以完成n2、n3、n4按鈕。(有些部分可能不用修改)




步驟二十九:
點選p1下的retry,選取when retry.Click do置於預覽視窗中。
點選Produces,選取call testquestion。
點選p1下的n1,選取set n1.Visible to,點選Logic,選取true,卡入其中。複製三次,分別將名稱改為n2、n3、n4。
完成retry按鈕。

解釋:當點擊retry按鈕時,n1、n2、n3、n4按鈕要出現並且顯示該題題目。

步驟三十:
retry按鈕複製,將名稱改為skip。
點選p1下的downNumber,選取set downNumber.Text to加入Math的+,將數字1卡入+後,點選p1下的downNumber,選取get downNumber.Text to,卡入前
點選Variables,選取set,並將選項點開設為"global question",嵌入Math的+,在卡入數字1在+後;選取get,卡入+前並將選項點開設為"global question "
點選p1下的unsolovedNumber,選取set unsolovedNumber.Text to加入Math的-,將數字1卡入-後,點選p1下的unsolovedNumber,選取get unsolovedNumber.Text to,卡入+前
(註:set global question to get global question +1一定要在call testquestion上面,否則題目無法更新)

解釋:當點擊skip按鈕時,以完成數加1,題目數加1,未完成數-1,n1、n2、n3、n4按鈕要出現並且顯示下一題題題目。

步驟三十一:
點選p1下的done,選取when retry.Click do置於預覽視窗中。
複製副程式testquestion中else if global question=11 then以下的程式將get global question to10刪除,其餘程式卡入do後。
完成Done程式。

解釋:當點擊done按鈕時,遊戲結束。將get global question to10刪除由於此題之後的題目未完成。

步驟三十二:
點選p2下的restart,選取when start.Click do置於預覽視窗中。
點選index,選取set index.Visible to ,卡入do後點選Logic,選取true,卡入其中。複製一次將名稱改為set p2.Visible to並將true改為false。
完成restart按鈕。
解釋:當點擊restart按鈕時,回到主頁面,p2頁面消失。

恭喜完成此次範例程式!


4 則留言:

  1. 請問做完一頁之後怎麼hidden?

    回覆刪除
  2. 1.先將所有元件放在 HorizontalArrangement,TableArrangement或VerticalArrangement中, 再改變這個Layout的屬性為Hidden或Show就可達到整個頁面元件一起隱藏或一起顯示的換頁效果。
    2.若您仍不知螢幕排列(Layout)如何設定, 可先參考前面的幾個範例。

    回覆刪除
  3. 您好,我想請問有關計時的問題
    我做出來的成果無法顯示計時
    出現了以下訊息:
    The operation - cannot accept the arguments: [java.util.GregorianCalendar[time=1462984490171,areFieldsSet=true,lenient=true,zone=Asia/Taipei,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=4,WEEK_OF_YEAR=20,WEEK_OF_MONTH=2,DAY_OF_MONTH=12,DAY_OF_YEAR=133,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=34,SECOND=50,MILLISECOND=171,ZONE_OFFSET=28800000,DST_OFFSET=0]] [0]
    想請問這是甚麼原因,謝謝

    回覆刪除