第十二章:第四個(gè)版本的選擇題
第三個(gè)版本的時(shí)候我們已經(jīng)設(shè)想好,新版本中題目將是動(dòng)態(tài)生成的,不用我們?cè)贔LASH的場(chǎng)景里面一題一題輸入了,我們要做的只是輸入題目和題目答案的數(shù)據(jù)就夠了。 很明顯,每一條題目都將是一個(gè)對(duì)象(不然我們學(xué)這么多對(duì)象的知識(shí)干嘛?),而這些所有的題目,會(huì)用一個(gè)數(shù)組來(lái)存放
再重提一下,可配合源程序?qū)W習(xí) http://www.moock.org/webdesign/lectures/ff2001sfWorkshop/moockQuizzes.zip
好,開(kāi)始設(shè)計(jì)題目的模版
模版就是一個(gè)MC,包含兩個(gè)TEXT FIELD,里面不用填東西,分別起變量名為:(FOR小鳥(niǎo):TEXT FIELD就是按工具條里T按鈕拉出來(lái)的文本框,同時(shí)還要在文本面板(ctrl+t)里將其改為Dynamic Text,變量名則在面板的Variable處改) * qNum (以后將顯示題目的編號(hào)) * qText (以后將顯示題目的正文) 我們還要在庫(kù)里面做標(biāo)識(shí),點(diǎn)一庫(kù)面板(ctrl+l)右上的Options>> Linkage ,選第二個(gè)Expert this symbol,identifier填上questionTemplate,至此,題目模版完成
再制作選項(xiàng)的模版
選項(xiàng)模版應(yīng)包括一個(gè)選擇用的按鈕 還有該選項(xiàng)的內(nèi)容,一個(gè)起名為answerText的TEXT FIELD 在本例的后面,將為每一個(gè)動(dòng)態(tài)生成的選項(xiàng)一個(gè)唯一的名字,譬如: "answer0", "answer1",..."answern". 答題者所選定的答案將由這個(gè)名字來(lái)決定,調(diào)用一個(gè)MC的名字,用的是_name這個(gè)屬性 所以答題的按鈕上面的AS為: on (release) { // Trim the prefix "answer" off this clip's name // 下面使用了String.slice()方法,例如_name為answer0,它將被處理成0,slice的具體語(yǔ)法請(qǐng)查閱AS字典 // 按鈕提交什么由該MC的名字決定的,我作個(gè)標(biāo)記 @@ ,記得一會(huì)看回來(lái) choice = _name.slice(6, _name.length); // 與前面的例子一樣,最后將答案提交給answer函數(shù)處理,不過(guò)現(xiàn)在我們是在某一MC里面用外面主時(shí)間線的函數(shù)了,所以得加上_root _root.answer(choice); } 最后,Options>> Linkage,標(biāo)識(shí)名:answerTemplate,制作模版的工作就完成了
下面將是放在第一幀的程序主體,可要打起精神來(lái)了:
// Stop the movie stop(); // Init main timeline variables var displayTotal; // Text field for user's final score var totalCorrect = 0; // Number of questions answered correctly
// Array containing the user's guesses 記錄作答答案的數(shù)組 var userAnswers = new Array();
// Number of the question the user is on 記錄正在作答中題目的編號(hào) // 要注意的是,它是由0開(kāi)始的,第一題的編號(hào)是0,因?yàn)槲覀円玫綌?shù)組,數(shù)組的第一個(gè)編號(hào)是0,所以這里我們也用0 var currentQuestion = 0;
// The Question constructor // 以下是新類(lèi)型對(duì)象question的構(gòu)造函數(shù),包含三個(gè)屬性:正確答案,題目正文,各個(gè)選項(xiàng) function Question (correctAnswer, questionText, answers) { this.correctAnswer = correctAnswer; this.questionText = questionText; this.answers = answers; }
// Import the source file containing our array of question objects // 咦?應(yīng)該是輸入各條題目的數(shù)據(jù)先啊,放哪去了?因?yàn)槁,?shù)據(jù)輸入是個(gè)與編程無(wú)關(guān)的過(guò)程,為了讓代碼更優(yōu)雅,這些繁瑣的東西扔別地方去了,AS太長(zhǎng),會(huì)使查閱相當(dāng)麻煩,分開(kāi)存放也是好習(xí)慣! // #include是引用外部AS命令,可以將AS分開(kāi)儲(chǔ)存于各個(gè)后綴名為AS的文件中,輸入題目的代碼就是放到了questionsArray.as中(記得和FLA放在同一目錄下喔) #include "questionsArray.as"
//// 我改變了一下教程的結(jié)構(gòu),把questionsArray.as的內(nèi)容也插入進(jìn)來(lái)了,因?yàn)樘^(guò)這段的話,看起來(lái)會(huì)有疑問(wèn) //// 以下內(nèi)容系存放questionsArray.as中的
// 輸入數(shù)據(jù)其實(shí)是建立對(duì)象 // MOOCK用一個(gè)數(shù)組還存放這些對(duì)象,這樣對(duì)象才更易于管理 // 不要被括號(hào)給弄昏了,輸入對(duì)象參數(shù)的中間還有中括號(hào),是因?yàn)檩斎腩}目的參數(shù)“各個(gè)選項(xiàng)”是一個(gè)數(shù)組 // 因?yàn)槭谴娣庞跀?shù)組中,每個(gè)對(duì)象之間記得應(yīng)有逗號(hào)分隔 // Remember to place a comma after each object // in the array except the last
questionsArray = [new Question (2, "Which version of Flash first introduced movie clips?", ["version 1", "version 2", "version 3", "version 4", "version 5", "version 6"]),
new Question (2, "When was ActionScript formally declared a scripting language?", ["version 3", "version 4", "version 5"]),
new Question (1, "Are regular expressions supported by Flash 5 ActionScript?", ["yes", "no"]),
new Question (0, "Which sound format offers the best compression?", ["mp3","aiff", "wav"]),
new Question (1, "True or False: The post-increment operator (++) returns the value of its operand + 1.", ["true", "false"]),
new Question (3, "Actionscript is based on...", ["Java", "JavaScript", "C++", "ECMA-262", "Perl"])];
//// 離開(kāi)questionsArray.as部分,我們繼續(xù)
// Begin the quiz 出題目!調(diào)用makeQuestion函數(shù)來(lái)完成,我們只需要給這個(gè)函數(shù)一個(gè)參數(shù):題目的編號(hào),函數(shù)就會(huì)按編號(hào)提取數(shù)據(jù),結(jié)合我們剛才做的模版生成題目。 makeQuestion(currentQuestion);
// Function to render each question to the screen // 下面就是makeQuestion函數(shù) function makeQuestion (currentQuestion) {
// Clear the Stage of the last question //這句是清理上一題生成的MC,這句從第二題開(kāi)始生效,questionClip就是題目的MC名,MC從哪來(lái)的?看下面就知道了 questionClip.removeMovieClip();
// Create and place the main question clip // 利用模版questionTemplate生成一個(gè)叫questionClip的MC,這個(gè)MC就是我們的問(wèn)題 attachMovie("questionTemplate", "questionClip", 0);
// 設(shè)定MC的位置 questionClip._x = 277; questionClip._y = 205;
// 把題目編號(hào)輸入MC的qNum文本框中 questionClip.qNum = currentQuestion + 1;
// questionsArray[currentQuestion]就是數(shù)組questionsArray里的第currentQuestion個(gè)對(duì)象,例如currentQuestion是0,那么就是我們的第一條題目 // questionsArray[0].questionText就是第一條題目對(duì)象的問(wèn)題屬性 // 然后問(wèn)題輸入MC的qText文本框中 questionClip.qText = questionsArray[currentQuestion].questionText;
// Create the individual answer clips in the question clip // 以下循環(huán)將結(jié)合選項(xiàng)模版生成這一條題目的各個(gè)選項(xiàng)的MC
// questionsArray[currentQuestion].answers記得嗎?選項(xiàng)這個(gè)屬性可是個(gè)數(shù)組,所以我們把它的長(zhǎng)度作為循環(huán)的次數(shù),這個(gè)數(shù)組有多大,我們就生成多少個(gè)選項(xiàng) for (var j = 0; j < questionsArray[currentQuestion].answers.length; j++) {
// Attach our linked answerTemplate clip from the Library. // It contains a generalized button and a text field for the question. // 用answerTemplate做模版生成MC,MC名為"answer" + j ,即第一個(gè)選項(xiàng)MC名為answer0,第二個(gè)為answer1,選項(xiàng)的名字可是關(guān)系到按鈕選什么的,如果你忘了,看看上面有 @@ 標(biāo)記的地方 // 同時(shí)它們的深度為j,每次不同
// 但和上面不同的是,我們要把選項(xiàng)MC生成到題目MC里,這樣我們清除題目MC的同時(shí)也清除了選項(xiàng) // 所以寫(xiě)成questionClip.attachMovie questionClip.attachMovie("answerTemplate", "answer" + j, j);
// Place this answer clip in line below the question. // 設(shè)定MC的位置,第一個(gè)高度為70,之后順序加15 questionClip["answer" + j]._y += 70 + (j * 15); questionClip["answer" + j]._x -= 100;
// Set the text field in the answer clip to the appropriate // element of this question's answer array. // 下面語(yǔ)句的:questionClip["answer" + j]可不是指數(shù)組,j=0的時(shí)候,它代表questionClip.answer0,具體解釋可見(jiàn)上一章。 // 這句語(yǔ)句的作用是把questionsArray[currentQuestion]這個(gè)對(duì)象數(shù)組里面的answers[j]數(shù)組,輸入到對(duì)應(yīng)的選項(xiàng)MC的answerText文本框中,就是該選項(xiàng)的內(nèi)容 questionClip["answer" + j].answerText = questionsArray[currentQuestion].answers[j]; } //生成選項(xiàng)的循環(huán)結(jié)束
}
// Function to register the user's answers // 以下是記錄答題者答案的函數(shù),記錄在數(shù)組userAnswers中,和上一例同 // 每一個(gè)選項(xiàng)如果被選都會(huì)調(diào)用此函數(shù),并用參數(shù)choice傳來(lái)作答的答案 function answer (choice) { userAnswers.push(choice);
// 判斷是否題目全部完成,是的話清楚掉題目MC,并跳轉(zhuǎn)到quizEnd幀 if (currentQuestion + 1 == questionsArray.length) { questionClip.removeMovieClip(); gotoAndStop ("quizEnd"); } else { // 在這里改變題目的編號(hào),然后調(diào)用makeQuestion函數(shù)再次生成新的題目 currentQuestion++; makeQuestion(currentQuestion); } }
// Function to tally the user's score // 改題的函數(shù) function gradeUser() { // Count how many questions the user answered correctly for (var j = 0; j < questionsArray.length; j++) { // 將答題數(shù)組userAnswers[j]與問(wèn)題數(shù)組questionsArray[j]的屬性correctAnswer逐個(gè)比較 if (userAnswers[j] == questionsArray[j].correctAnswer) { totalCorrect++; } } // Show the user's score in an onscreen text field // 顯示答對(duì)與題目數(shù)比 displayTotal = totalCorrect + "/" + questionsArray.length; }
好了,我們來(lái)總結(jié)一下這個(gè)例子吧
我們已經(jīng)完成了第三個(gè)版本結(jié)束時(shí)候定下來(lái)目標(biāo),更快捷的建設(shè),更便易的擴(kuò)展 我們的題目跟選項(xiàng)都是動(dòng)態(tài)生成的,也就是說(shuō)生成10、100題或更多題目也只需要修改questionsArray.as這個(gè)文件就可以了 如果說(shuō)生成兩題這個(gè)例子用時(shí)要長(zhǎng)于上面的例子,那么生成100題,你會(huì)發(fā)現(xiàn)用這個(gè)例子將是最快的。還有,在100題里面修改其中一題,也是最快的。
看完了例子,希望大家不是只明白了代碼的含義,最重要是理解運(yùn)用對(duì)象來(lái)編程的方法。同樣的例子,其實(shí)還可以用其他的對(duì)象結(jié)構(gòu)來(lái)完成的,更有效地組織數(shù)據(jù)也是編程藝術(shù)的一部分。
為了更進(jìn)一步改進(jìn)我們的例子,最后一個(gè),就是第五個(gè)版本,將用XML代替那個(gè)存放對(duì)象的數(shù)組(也就是在questionsArray.as里那個(gè)),它實(shí)在太難懂了,是不是啊?呵呵
出處:藍(lán)色理想
責(zé)任編輯:qhwa
上一頁(yè) 一點(diǎn)面向?qū)ο缶幊讨R(shí) 下一頁(yè) XML
◎進(jìn)入論壇Flash專欄版塊參加討論
|