第一篇:“24點(diǎn)”游戲說明書
“24點(diǎn)”游戲說明書
名稱:“24點(diǎn)”游戲
基本玩法:給定四個(gè)自然數(shù),通過+,-,×,÷四則運(yùn)算,可以交換數(shù)的位置,可以隨意地添括號(hào),但規(guī)定每個(gè)數(shù)恰好使用一次,連起來組成一個(gè)混合運(yùn)算的算式,使最后得數(shù)是24。
“24點(diǎn)”游戲通常是用撲克牌進(jìn)行的,此時(shí),給定的四個(gè)自然數(shù)就被限定在1~13范圍內(nèi)了。“數(shù)學(xué)24”游戲可以1個(gè)人玩,也可以多個(gè)人玩,比如四個(gè)人玩,把撲克牌中的大、小王拿掉,剩下的52張牌洗好后,每人分13張,然后每人出一張牌,每張牌的點(diǎn)數(shù)代表一個(gè)自然數(shù),其中J,Q,K分別代表11,12和13,四張牌表示四個(gè)自然數(shù)。誰最先按游戲規(guī)則算出24,就把這四張牌贏走。然后繼續(xù)進(jìn)行。最后誰的牌最多誰獲勝。
要想算得又快又準(zhǔn),這就要靠平時(shí)的基本功了。最重要的有兩條:一是熟悉加法口訣和乘法口訣,二是利用括號(hào)。括號(hào)既能改變運(yùn)算順序,也可以改變運(yùn)算符號(hào)。
好處:通過玩“24點(diǎn)”的游戲,能把枯燥的基本數(shù)字計(jì)算變得趣味盎然,能大大提高計(jì)算能力和速度。
第二篇:沙盤游戲說明書
你是否感覺和他人交流有障礙,總是詞不達(dá)意或者被人誤解? 你是否感覺自己做得都很好,可別人就是不領(lǐng)情? 你是否總是莫名其妙落入別人的陷阱? 你是否總是遇到同一類人或事讓我煩惱? 你我是否總是遇到層出不窮的麻煩?
你是否有焦慮、抑郁、悲傷、憤怒、恐懼等情緒需要處理? 你是否有自殺或自傷傾向需要處理? 你是否害怕與人交往? 你是否不愿意一個(gè)人獨(dú)處? 你是否缺乏親密的朋友?
你是否有太多的親戚和朋友需要我費(fèi)心照顧? 你是否害怕考試?又想念書又念不下去? 你是否過份害怕小動(dòng)物? 你是否被人指責(zé)為愛做白日夢(mèng)? 你是否網(wǎng)絡(luò)成癮,欲罷不能?
你是否感覺付出了很多,卻得不到周圍人的認(rèn)可? 你是否自信不足?
你是否對(duì)小時(shí)候的一些人或事仍有抱怨或怨恨? 你是否感覺伴侶特別不可理喻?特別不能理解自己? 你是否感覺家庭成員之間缺乏溫暖和關(guān)愛?
你的孩子是否易怒?稍不如意就大喊大叫,大哭大鬧? 你的孩子是否過于膽怯,不敢主動(dòng)和其他孩子交往? 你的孩子是否做事磨蹭,沒有時(shí)間觀念? 你的孩子是否不愛學(xué)習(xí),注意力不集中?
你是否感覺下級(jí)總是不能圓滿完成自己交給的任務(wù)? 你是否感覺上級(jí)總是下達(dá)一些莫名其妙的指令? 你是否感覺同級(jí)之間有人在不公平競(jìng)爭(zhēng)或者刁難自己? 你是否經(jīng)常有類似的夢(mèng)境出現(xiàn)?
你是否對(duì)未來充滿信心?還是已經(jīng)一眼就望到了盡頭? 你是否有員工需要增進(jìn)團(tuán)隊(duì)凝聚力,提高工作效率?
如果你有上面的這些困擾,這些困擾是否嚴(yán)重到你沒辦法自己處理或克服,困擾是否嚴(yán)重到你愿意花費(fèi)金錢和時(shí)間來找專業(yè)人士幫助你處理。如果是的話,你就可以考慮申請(qǐng)參加沙盤游戲。
沙盤游戲只是呈現(xiàn)參加者的行為和行為模式,并不能看到參加者之前經(jīng)歷了什么具體事件,不涉及個(gè)人隱私。
指導(dǎo)者的主要功能是陪伴,提供安全和信任的環(huán)境,讓參加者有充分的機(jī)會(huì)獲得感悟和自愈。在討論過程中,指導(dǎo)者只就沙盤呈現(xiàn)出來的部分對(duì)參加者有針對(duì)性的提醒,提醒參加者回憶當(dāng)時(shí)操作時(shí)的想法和情緒感受,在參加者的一些情緒關(guān)口予以適當(dāng)?shù)囊龑?dǎo),以幫助參加者順利釋放和更深層看清自己。
沙盤游戲現(xiàn)在越來越多被企業(yè)用作增強(qiáng)團(tuán)隊(duì)協(xié)作的有力工具,以及越來越多的個(gè)人漸漸喜歡使用這種直觀的方式來解決自身的問題,很多企業(yè)管理者和需要心理幫助的人士,無論是親身經(jīng)驗(yàn)過的還是只是聽說過沙盤游戲療效的人,均對(duì)此深感神奇,其中有些人士希望借助沙盤游戲看透別人以滿足自己的好奇心,有些人士則希望被旁觀者看到以獲得幫助,還有些人因?yàn)閾?dān)心泄漏自己的隱私而在內(nèi)心抵制沙盤游戲,但是更有很多人士希望深入了解沙盤游戲。
沙盤游戲的適用人群(我和周圍的人需要做沙盤游戲嗎?):
沙盤游戲適用的人群相當(dāng)廣泛,按照分類方法的不同,羅列如下:
(一)按照心理問題分類,沙盤游戲適用于以下情況:
(1)自閉癥等言語障礙和交流困難者:言語障礙者因?yàn)楦鞣N原因不能很好地用語言表達(dá)自己的觀點(diǎn)或情緒體驗(yàn)、與他人交流。言語面談式的咨詢也不適用于他們。沙盤游戲不需要語言交流,可使參加者的挫敗感和心靈創(chuàng)傷都得到適當(dāng)?shù)谋硎?,并得以減弱甚至治愈。而這些未曾得到表現(xiàn)、宣泄的挫敗感和心靈創(chuàng)傷往往是造成學(xué)業(yè)失敗、心理沮喪、社會(huì)技能缺乏的主要原因。
(2)焦慮等情緒困難者:學(xué)習(xí)和考試焦慮是當(dāng)前學(xué)生面臨的主要情緒困難之一。沙盤是一種集認(rèn)知重構(gòu)、情緒表達(dá)、感覺統(tǒng)合、心理動(dòng)力于一體的心理治療方法。通過玩沙子和沙具,可以宣泄自己的焦慮情緒,放松身心,并在面對(duì)沙盤這一內(nèi)心鏡像時(shí),重構(gòu)自己的意識(shí)和潛意識(shí)。沙盤制作過程能夠充分挖掘參加者的創(chuàng)造潛力,這種成功創(chuàng)造的感覺和經(jīng)歷又能夠進(jìn)一步提升他們的自信和自尊,使他們具備強(qiáng)大的心理抗擊打能力來面對(duì)學(xué)習(xí)和考試以及步入社會(huì)之后的挫折。
(3)注意缺陷、多動(dòng)者:注意缺陷、多動(dòng)主要表現(xiàn)為注意力分散、多動(dòng)、易沖動(dòng)、易激怒以及無法容忍延遲滿足等。對(duì)注意缺陷的干預(yù)一直是臨床工作者感到困惑的難題。運(yùn)用沙盤游戲能幫助注意缺陷者將注意力集中于一種可具體感知到的、自我主導(dǎo)的活動(dòng),沙子和玩具的可觸性、可移動(dòng)性通過觸覺與運(yùn)動(dòng)覺作用于參加者的大腦神經(jīng),從而使他們的注意力集中于具體的物件和活動(dòng)。此外,沙盤的沙箱是一個(gè)有邊界限制的空間,可以將參加者的注意力集中于這一有限的空間內(nèi),有助于訓(xùn)練他們集中注意力。
(4)攻擊性行為者:情感宣泄是矯治攻擊性行為的重要方法。煩惱、攻擊、挫折、憤怒等侵犯性情感是點(diǎn)燃攻擊性行為的導(dǎo)火索,侵犯性情感積聚越多,其表現(xiàn)攻擊性行為的可能性愈大。宣泄可以減弱侵犯 性情感的強(qiáng)度,而過分壓抑侵犯性情感只能使其獲得暫時(shí)的壓制而不會(huì)因此消失,反而深入到潛意識(shí)中,危害其身心健康。過分壓抑的結(jié)果,往往會(huì)爆發(fā)出突然的、猛烈的攻擊性行為。沙盤為此類行為者提供了一個(gè)表達(dá)的機(jī)會(huì),可以讓他們?cè)谔摂M的空間里將其憤怒、攻擊性的行為和情感具體地演示出來,以耗散其攻擊性心理能量,并從沙盤所建構(gòu)的故事情境中學(xué)會(huì)與人相處的適應(yīng)性行為。
(5)人際關(guān)系困難者:人際關(guān)系是影響個(gè)體主觀幸福感的主要因素之一,并可能進(jìn)一步影響個(gè)體的學(xué)習(xí)、生活質(zhì)量,所以如何正確處理與他人的關(guān)系是個(gè)體心理發(fā)展的重要課題。團(tuán)體沙盤游戲在促進(jìn)團(tuán)體成員協(xié)作能力、增進(jìn)團(tuán)體整合、提高人際交往技能、確立自我概念等方面具有非常顯著的效果。在沙盤世界中,成員或個(gè)體以虛擬而又注入真情實(shí)感的角色扮演的方式展開人際關(guān)系互動(dòng),并在沙盤的幫助下調(diào)整社會(huì)認(rèn)知系統(tǒng),從成員人際交往的成功行為中學(xué)會(huì)社交適應(yīng)行為。
(6)網(wǎng)絡(luò)成癮者:沙盤游戲可以使網(wǎng)絡(luò)成癮者獲得充分的內(nèi)在體驗(yàn),以及充分的表現(xiàn)和表達(dá),引發(fā)成癮的焦慮內(nèi)容得以展現(xiàn),焦慮情緒因之緩解。同時(shí)沙盤游戲和網(wǎng)絡(luò)都能創(chuàng)建出變化無窮的三維圖畫,能充分發(fā)揮網(wǎng)絡(luò)成癮者的創(chuàng)造性和動(dòng)手能力,容易引發(fā)他們?nèi)硇耐度胍患虑榈挠鋹傮w驗(yàn),從而把對(duì)網(wǎng)絡(luò)的依賴轉(zhuǎn)移到既能獲得成功愉悅體驗(yàn)又能促進(jìn)心智發(fā)展的行為中。
(二)按照年齡分類,沙盤游戲適用于:
(1)幼兒及中小學(xué)生:沙盤游戲可以對(duì)有需要的幼兒與兒童提供輔導(dǎo)。鑒于幼兒和兒童語言表達(dá)不清晰和喜歡玩具與游戲的特點(diǎn),沙盤游戲特別適用于這樣的年齡階段。沙盤游戲提供了一種自由的情境讓兒童的心靈自己產(chǎn)生自我療愈。
(2)成人:沙盤游戲可使成人提高自信心、完善自我性格、提高人際交往技巧、有效宣泄消極情緒、釋放壓力等。
成人大多數(shù)的創(chuàng)傷或者問題都源于兒童時(shí)代,在那時(shí)他們感覺被拋棄,受到嚴(yán)格限制,過度的批評(píng)和懲罰,或者因失敗而被周圍的人不接納。在沙盤游戲中,指導(dǎo)者沒有批評(píng)和懲罰,而是抱著接納一切的態(tài)度,給予參加者以自由空間,并身臨其境,感同身受,和參加者結(jié)為同盟,從而使參加者感受到極大的支持,更能激發(fā)他的潛力來獲得自愈。
沙盤游戲也允許在沙盤內(nèi)把過去的事件呈現(xiàn)出來。參加者可以現(xiàn)場(chǎng)把事件場(chǎng)景改變,并把這些事件從潛意識(shí)和意識(shí)層面解決掉。參加者借助沙盤把創(chuàng)傷事件具體化,不斷增強(qiáng)自我去面對(duì),并以新的眼光和新的理解方式來看待這些創(chuàng)傷事件,最后達(dá)到自愈。
(三)按照參加人數(shù)和相互關(guān)系分類,沙盤游戲適用于:(1)個(gè)體沙盤:可以深入展示個(gè)人的內(nèi)心世界,讓參加者與自己的潛意識(shí)對(duì)話,疏泄積壓的情緒,了解自己的深層次需要,從而更了解自己,更清晰自己的目標(biāo),更容易達(dá)成自己的目標(biāo)。
(2)伴侶沙盤:可以借助沙盤游戲,清晰雙方的行為模式和行為動(dòng)機(jī),有助于雙方深層溝通,冰釋前嫌并減少以后誤解的產(chǎn)生和情緒的爆發(fā),促進(jìn)雙方更加伉儷情深。
(3)家庭沙盤:可以有效的改善家庭成員關(guān)系,呈現(xiàn)成員的潛意識(shí)反應(yīng),促進(jìn)成員間深層次的心靈溝通,尤其是對(duì)培養(yǎng)孩子的良好性格習(xí)慣有積極作用。
(4)團(tuán)體沙盤:針對(duì)學(xué)生、教師、醫(yī)護(hù)人員、病人、企業(yè)高層管理人員、銷售人員、公務(wù)員等,可以促進(jìn)團(tuán)隊(duì)精神的升華,提升團(tuán)隊(duì)凝聚力,培養(yǎng)協(xié)作性人才,加強(qiáng)成員間的精神交流,改善團(tuán)隊(duì)氣氛,提高工作效率。
(四)按照內(nèi)容分類,沙盤游戲可應(yīng)用于:
(1)解夢(mèng):以沙盤呈現(xiàn)夢(mèng)境以及夢(mèng)境的發(fā)生發(fā)展過程,在清醒狀態(tài)下重現(xiàn)相關(guān)情緒,有助于參加者明白夢(mèng)境在提示自己什么,有助于參加者從旁觀者的立場(chǎng)看清自己,更加了解自己。
(2)未來展望:以沙盤呈現(xiàn)參加者潛意識(shí)層面對(duì)未來的憧憬,使?jié)撘庾R(shí)的模糊影像上升到意識(shí)層面的清晰意象,讓頭腦更清晰地看到自己對(duì)未來的期待,內(nèi)心形成一個(gè)完整的感受,這種完整感受的體驗(yàn)?zāi)苁箙⒓诱卟活櫶弁春徒箲]去繼續(xù)在現(xiàn)實(shí)中尋找這一完整,這強(qiáng)大的動(dòng)力可導(dǎo)致參加者現(xiàn)在就開始制定朝向未來的計(jì)劃,由于意識(shí)層面和潛意識(shí)層面目標(biāo)一致,更有利于現(xiàn)實(shí)生活中計(jì)劃的逐步執(zhí)行和實(shí)現(xiàn)。
(3)EAP(企業(yè)員工心理援助)及人力資源開發(fā):沙盤游戲?qū)τ谌烁癜l(fā)展、想象力、創(chuàng)造力的培養(yǎng)以及心理維護(hù)、個(gè)人成長(zhǎng)等都發(fā)揮著積極的促進(jìn)作用,而且簡(jiǎn)單實(shí)用見效快,是企業(yè)EAP心理咨詢及人力資源開發(fā)的核心技術(shù)。
(4)職業(yè)生涯規(guī)劃:通過沙盤來呈現(xiàn)個(gè)人未來的生活和工作場(chǎng)景,來具象化參加者對(duì)于未來職業(yè)的展望,使參加者更加清晰未來工作的宏觀輪廓和微觀細(xì)節(jié),聯(lián)系目前的現(xiàn)狀,尋找現(xiàn)在和未來的切合點(diǎn),激發(fā)對(duì)于未來工作的向往和對(duì)于現(xiàn)狀的改造熱情,幫助參加者提高現(xiàn)在的學(xué)習(xí)和工作效率,更快達(dá)成一個(gè)又一個(gè)目標(biāo)。
第三篇:delphi24點(diǎn)游戲
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.1 “速算24”撲克游戲效果說明
“速算24”是一個(gè)考察心算能力、有助于開發(fā)智力的撲克游戲。在給出4張撲克牌之后,要求應(yīng)用這些撲克牌數(shù)字做數(shù)學(xué)運(yùn)算,迅速構(gòu)造出一個(gè)數(shù)學(xué)表達(dá)式,得出結(jié)果24。這個(gè)游戲的關(guān)鍵在于迅速判斷用戶輸入的表達(dá)式是否正確,并做出相應(yīng)的反饋,告訴用戶是算對(duì)了還是算錯(cuò)了。游戲的初始界面如圖3.1所示。
圖3.1 游戲的初始界面
當(dāng)用戶單擊“開始”按鈕時(shí),系統(tǒng)開始發(fā)牌,隨機(jī)發(fā)出4張牌,如圖3.2所示為隨機(jī)開始的一局游戲,給出的4張紙牌分別為“9”,“8”,“9”,“2”。在文本框中輸入運(yùn)算表達(dá)式,比如,輸入“8*(2+(9-9))”,單擊“計(jì)算”按鈕,系統(tǒng)會(huì)出現(xiàn)提示框,顯示“您輸入的表達(dá)式的計(jì)算結(jié)果為16!”,告訴你該表達(dá)式的結(jié)果不是“24”,如圖3.3所示。單擊“確定”按鈕,再次在文本框中輸入表達(dá)式,比如“8*(2+(9/9))”,單擊“計(jì)算”按鈕,系統(tǒng)會(huì)出現(xiàn)提示框,顯示“您真行,我服了您!”,表明運(yùn)算正確,如圖3.4所示。
圖3.2 系統(tǒng)隨機(jī)發(fā)4張紙牌
圖3.3 運(yùn)算式不正確
圖3.4 運(yùn)算式正確
這個(gè)游戲具體的規(guī)則如下:
(1)單擊“開始”按鈕,游戲開始,系統(tǒng)將隨機(jī)發(fā)牌。
(2)請(qǐng)迅速在文本框中輸入運(yùn)算表達(dá)式,然后單擊“計(jì)算”按鈕。
(3)這時(shí)系統(tǒng)會(huì)提示您的運(yùn)算是對(duì)了還是錯(cuò)了,在彈出的對(duì)話框中單擊“OK”按鈕,再次輸入新的運(yùn)算表達(dá)式,重復(fù)上一步,直到您的運(yùn)算表達(dá)式結(jié)果正確,這時(shí)系統(tǒng)會(huì)恭喜您!
(4)如果結(jié)果錯(cuò)了還想繼續(xù)或者中途想計(jì)算另一局撲克牌,就單擊“重新開始”按鈕,得到新一局撲克牌進(jìn)行游戲。
下面,我們開始循序漸進(jìn)地創(chuàng)建這個(gè)小游戲。在最開始,游戲的界面和效果都會(huì)非常簡(jiǎn)單,在后面我們會(huì)逐漸地完善它。
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.2 生成和建立程序(1)在程序中用到了Image組件,用于放置圖片。還用到了Timer組件,用于計(jì)算用戶操作時(shí)間。下面我們來生成游戲的基本框架。
3.2.1 Image組件
Image組件在Additional頁上,用來在窗口中顯示一幅圖片。它擁有如下幾個(gè)主要屬性: 1.Picture屬性
可以在picture屬性中調(diào)入圖像文件。Delphi支持多種圖像格式,如位圖(.BMP)、圖標(biāo)(.ICO)、圖元(.WFM)、動(dòng)畫光標(biāo)(.ANI)、JPEG圖片(.JPG、.JPEG)等。
2.AutoSize屬性
當(dāng)AutoSize為True時(shí),Image組件將根據(jù)它所包含的圖像的大小來調(diào)整自身的大?。划?dāng)AutoSize為False時(shí),不論圖像有多大,組件將保持設(shè)計(jì)時(shí)的大小。如果組件比圖像小,那么只有一部分圖像是可見的。
3.Stretch屬性
當(dāng)Stretch為True時(shí),位圖圖像將根據(jù)組件的大小調(diào)整自身的大小,當(dāng)組件大小改變時(shí),上述三種文件也做相應(yīng)變化。Stretch屬性對(duì)圖標(biāo)沒有作用。
上述的AutoSize和Stretch屬性決定了圖像在窗口中的顯示尺寸。
圖3.5演示的3個(gè)Image分別為:AutoSize為True,AutoSize為False,Stretch為True的情形??梢钥吹?,Image的原始尺寸比圖片寬,矮,在上面的屬性設(shè)置下,就會(huì)有不同的顯示效果。
圖3.5 AutoSize和Stretch的設(shè)置 3.2.2 Timer組件
在Delphi中,組件分可視組件和非可視組件??梢暯M件是指那些在運(yùn)行期間仍然能顯示的組件,例如Label,Button,Image組件等。非可視組件是指那些在程序界面設(shè)計(jì)期間可見,而在程序運(yùn)行時(shí)不可見的組件,例如在System頁上的Timer組件。
Timer組件能夠有規(guī)律地觸發(fā)OnTimer事件,發(fā)送信息給應(yīng)用程序,它是編制應(yīng)用程序時(shí)最為重要的組件之一。
1.Timer組件的屬性
Enabled屬性表示Timer是打開還是關(guān)閉。用Interval屬性設(shè)置兩個(gè)OnTimer事件間的間隔,單位是毫秒。將間隔設(shè)置為0相當(dāng)于關(guān)閉計(jì)時(shí)器,Interval是Cardinal類型的,最大值可到4294967295,當(dāng)然程序中一般不會(huì)把Interval設(shè)成很大的值。2.Timer組件的使用
Timer是獨(dú)立的對(duì)象,在啟動(dòng)與Windows無關(guān)的邏輯和應(yīng)用事件時(shí)極其有用??梢阅M時(shí)鐘或計(jì)時(shí)器,可視地顯示經(jīng)過的時(shí)間;可以用作系統(tǒng)延時(shí),Delphi提示信息出現(xiàn)只需在該區(qū)域停頓幾秒,就是Timer組件應(yīng)用的一個(gè)例子;可以檢查系統(tǒng)環(huán)境、事件,根據(jù)結(jié)果進(jìn)行響應(yīng);也可以在窗口中閃爍一段正文或圖像,提示某種操作或處理正在進(jìn)行等等。
盡管Delphi的計(jì)時(shí)器每秒可以產(chǎn)生1000次激發(fā),在編程中還必須注意程序?qū)imer觸發(fā)的響應(yīng)。如果程序處理OnTimer事件的時(shí)間超過Interval的設(shè)定值,就可能錯(cuò)過事件,因?yàn)楫?dāng)下一次觸發(fā)到來時(shí),系統(tǒng)正忙于處理上一事件,則這次觸發(fā)就會(huì)被忽略。同時(shí)要注意其他的Windows應(yīng)用程序是否會(huì)影響Timer的觸發(fā)。如果后臺(tái)正運(yùn)行著一個(gè)占用處理器的程序,就可能會(huì)導(dǎo)致Timer的觸發(fā)不準(zhǔn)確,從而使前臺(tái)程序運(yùn)行出現(xiàn)錯(cuò)誤。
這里要強(qiáng)調(diào)的是Timer組件是一個(gè)非可視組件,可以把它放置到窗體或者其他容器組件上的任何位置。3.實(shí)現(xiàn)游戲計(jì)時(shí)功能
在本章的游戲中,我們加入一個(gè)Timer組件,實(shí)現(xiàn)游戲的計(jì)時(shí)功能。
在窗體中加入一個(gè)Label組件,將此組件的Caption屬性設(shè)置為“使用時(shí)間”,然后從組件面板上選擇System頁中的Timer組件。
在Unit1中加入Form1的一個(gè)私有成員SpendTime,記錄用戶計(jì)算所用的時(shí)間。代碼如下所示:
private { Private declarations } SpendTime:Integer;在Form1的onCreate事件中加入如下代碼。將SpendTime設(shè)置為0,并將Timer1的Enabled屬性設(shè)置為False,使Timer1組件不能響應(yīng)OnTimer事件;并將Timer1的Interval屬性設(shè)置為1000,表示當(dāng)Timer1有效時(shí),每間隔1000ms(即1秒)發(fā)生一次OnTimer事件:
procedure TForm1.FormCreate(Sender: TObject);var i:integer;begin //初始化,設(shè)置數(shù)組RandomData的長(zhǎng)度為4 //并將每個(gè)數(shù)組元素初始化為零
setLength(RandomData,4);for i := 0 to 3 do RandomData[i]:=0;SpendTime:=0;Timer1.Enabled:=False;Timer1.Interval:=1000;end;然后在標(biāo)題為“開始”的“開始”按鈕的OnClick事件中,加入如下所示的代碼,將Timer1的Enabled屬性設(shè)置為True,使Timer1組件有效,即現(xiàn)在Timer1能響應(yīng)OnTimer事件,計(jì)時(shí)開始。并將SpendTime重新設(shè)置為0:
Timer1.Enabled:=True;Timer1.Interval:=1000;SpendTime:=0;//將SpendTime重新設(shè)為0 再在“計(jì)算”按鈕的OnClick事件句柄中,增加下面的語句,使Timer1無效:
Timer1.Enabled:=False;最后雙擊Timer1組件,創(chuàng)建Timer1的OnTimer事件句柄,在其中加入如下所示的代碼,將SpendTime加1,并設(shè)置Label5的Caption屬性:
procedure TForm1.Timer1Timer(Sender: TObject);begin SpendTime:=SpendTime+1;Label5.Caption:='使用時(shí)間:'+IntToStr(SpendTime)+'秒';end;這樣,每隔1秒鐘,程序就刷新一次使用時(shí)間。
3.2.3 設(shè)計(jì)初始界面
按住Shift鍵,然后單擊組件面板中Additional頁中的Image組件,這時(shí)該組件邊緣出現(xiàn)藍(lán)色的邊框,并且凹陷下去,表示可以在窗體上連續(xù)加入幾個(gè)Image組件。選擇好Image組件后,在窗體的左上角單擊,加入1個(gè)Image組件,然后依次向右單擊鼠標(biāo)3次,再加入3個(gè)Image組件。最后再單擊組件面板中最左邊的箭頭。
為了排列這4個(gè)Image組件,先利用Shift鍵將它們同時(shí)選上,然后右擊,選擇Align命令,在隨后出現(xiàn)的Alignment對(duì)話框中的Horizontal選項(xiàng)組中選擇Space equally,在Vertical選項(xiàng)組中選擇Tops,表示這4個(gè)組件頂端對(duì)齊,水平方向上間距相等。
按照同樣的方法加入4個(gè)Label組件、3個(gè)Button組件和1個(gè)Edit組件。按照表3.1所示設(shè)置各個(gè)組件的屬性。
表3.1 各個(gè)組件的屬性
組件名 Form1 Label1 屬性名 Caption Caption AutoSize WordWrap Caption
屬性值 速算24
1.單擊“開始”按鈕,游戲開始,系統(tǒng)將發(fā)出4張撲克牌
False False
2.要求用戶利用撲克牌顯示的數(shù)字,通過加減乘除運(yùn)算,以最快的速度得出24(可以使用括號(hào)),JQKA和“王”算做1。然后在文本框中寫好表達(dá)式,接
著單擊“計(jì)算”按鈕
Label2
Label3 AutoSize WordWrap Caption
False True
3.這時(shí)系統(tǒng)會(huì)計(jì)算輸入表達(dá)式的結(jié)果,告訴用戶是對(duì)還是錯(cuò)了。在彈出的對(duì)話框中單擊“OK”按鈕,如果錯(cuò)了可以再次輸入新的表達(dá)式,重復(fù)上一步。直
到您的表達(dá)式正確,這時(shí)系統(tǒng)會(huì)恭喜算對(duì)了!
Label4 AutoSize WordWrap Caption AutoSize Caption Caption Caption Text
False True 在下面輸入數(shù)學(xué)表達(dá)式
False 開始 計(jì)算 退出游戲 空
Button1 Button2 Button3 Edit1
現(xiàn)在同時(shí)選擇Label1,Label2和Label3,將它們左對(duì)齊,垂直方向等距離排列。將Button1,Button2和Button3左對(duì)齊,垂直方向等距離排列。
下面放置4個(gè)Image組件,用于放置4張紙牌的圖片。
先選擇Image1,然后切換到對(duì)象查看器中的屬性編輯器,選擇屬性選項(xiàng)頁中的Picture屬性,然后在Picture屬性值欄中雙擊,或單擊此屬性值旁邊的帶有省略號(hào)的按鈕,打開Picture Editor對(duì)話框,如圖3.6所示。然后單擊Load按鈕,彈出Load Picture對(duì)話框,在此對(duì)話框中選擇background.bmp文件。最后單擊OK按鈕,退出Picture Editor對(duì)話框。
圖3.6 指定圖片
使用同樣的方法,設(shè)定其他3個(gè)Image組件的Picture屬性。
保存我們的新項(xiàng)目,運(yùn)行之后界面如圖3.7所示,與運(yùn)行時(shí)的界面圖3.1稍有不同。這里是設(shè)計(jì)時(shí)界面,只有界面沒有事件響應(yīng)。是程序創(chuàng)建過程中的一個(gè)步驟的檢驗(yàn)。但是,這個(gè)程序還沒有什么具體的功能,為了讓游戲運(yùn)行起來,必須添加代碼,創(chuàng)建相應(yīng)的事件處理程序。
第3章 “速算24”撲克游戲--單元、異常、邏輯
????生成和建立程序????
???????
3.2.4 事件處理
需要添加?個(gè)事件:第一個(gè)用于響應(yīng)單擊?開始?按鈕,在此事件中完成發(fā)牌,即隨機(jī)顯示圖片;第二個(gè)用于響應(yīng)單擊?計(jì)算?按鈕,解析用戶在文本框中輸入的表達(dá)式,計(jì)算表達(dá)式的結(jié)果,并判斷表達(dá)式的結(jié)果是否等于??;第三個(gè)用于響應(yīng)單擊?退出游戲?按鈕,退出游戲(程
序)。?
1.數(shù)據(jù)初始化
創(chuàng)建窗體的????????事件處理程序,在這里進(jìn)行必要的初始化。?第一步先在Unit1中添加Form1的私有成員數(shù)組:
private
{ Private declarations }
RandomData:array of Integer;然后,在對(duì)象查看器中選中Form1,選中Event選項(xiàng)卡,在OnCreate一欄對(duì)應(yīng)的右邊的空白欄中雙擊,創(chuàng)建OnCreate函數(shù)。添加如下代碼。
procedure TForm1.FormCreate(Sender: TObject);
var
i:integer;
begin //初始化,設(shè)置數(shù)組RandomData的長(zhǎng)度為4
//并將每個(gè)數(shù)組元素初始化為零
setLength(RandomData,4);
for i := 0 to 3 do
RandomData[i]:=0;
end;這里使用一個(gè)for循環(huán)語句,i是循環(huán)變量,格式是:for循環(huán)變量:=初值to末值do循環(huán)體。你也可以借助Delphi的自動(dòng)完成功能,在輸入for之后按下Ctrl+J鍵,生成如下代碼:
procedure TForm1.FormCreate(Sender: TObject);
begin
for := to do
begin end;
end;在上述代碼中,程序首先利用setLength函數(shù)設(shè)定可變數(shù)組RandomData的數(shù)組長(zhǎng)度為4,然后,將數(shù)組的每一個(gè)單元都設(shè)置為0。這樣,就完成了數(shù)組的數(shù)據(jù)初始化工作。
2.“開始”按鈕的Click事件處理
(?)功能?單擊?開始?按鈕時(shí),系統(tǒng)就隨機(jī)地發(fā)出?張紙牌,顯示在?個(gè)?????組件中。?
(?)代碼?首先,我們需要一個(gè)循環(huán)變量?,一個(gè)字符串變量存放隨機(jī)選取的圖片的文件名。?創(chuàng)建“開始”按鈕的OnClick事件處理程序,在begin前頭添加需要的變量,然后在此事件
中加入如下所示的代碼。
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
filename:String;
begin
Randomize;//初始化隨機(jī)數(shù)
for i := 0 to 3 do
begin RandomData[i]:=Random(13)+1;//產(chǎn)生一個(gè)1到13的隨機(jī)數(shù)
filename:=IntToStr(RandomData[i])+'.bmp';//根據(jù)隨機(jī)數(shù),得到文件名
//根據(jù)i的不同為不同的Image組件載入圖像文件
case i of 0 : Image1.Picture.LoadFromFile(filename);1 : Image2.Picture.LoadFromFile(filename);2 : Image3.Picture.LoadFromFile(filename);3 : Image4.Picture.LoadFromFile(filename);
end;
edit1.Text:='';
edit1.SetFocus;
end;
end;在Delphi內(nèi)部,隨機(jī)數(shù)的產(chǎn)生實(shí)際上也是在一套算法的控制之下,Randomize函數(shù)用于初始化產(chǎn)生隨機(jī)數(shù)的種子,保證兩次產(chǎn)生的隨機(jī)數(shù)不同,而Random(i:integer)則利用初始化過后的隨機(jī)數(shù)種子產(chǎn)生一個(gè)1~i之間的隨機(jī)數(shù)。這里i設(shè)定為13,以配合撲克牌的張數(shù)13。
???????????????????用來將一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)字符串,和上一章中的??????????????????的功能恰好相反。?我們已經(jīng)預(yù)先準(zhǔn)備了位圖文件,它們都是???形式,文件名則是利用數(shù)字????命名。??????中特殊的字符串運(yùn)算符???將兩個(gè)字符串串聯(lián)起來,產(chǎn)生一個(gè)新的字符串,我們需要的位圖文件后綴是???,因此,在產(chǎn)生文件名的時(shí)候,在數(shù)字后面加上??????這個(gè)字符串。?????語句在上一章中已經(jīng)講過,單擊?開始?按鈕后,準(zhǔn)備接受用戶的輸入,然后利用????????方法,把焦點(diǎn)設(shè)置到?????上。????????是??????提供的方法之一,用于設(shè)置輸入
焦點(diǎn)到某個(gè)指定的組件。?
3.“計(jì)算”按鈕的OnClick事件
雙擊“計(jì)算”按鈕,創(chuàng)建此組件的OnClick事件響應(yīng)句柄,然后在代碼編輯器中加入如下所
示的代碼,用于計(jì)算用戶輸入的表達(dá)式。
procedure TForm1.Button2Click(Sender: TObject);
var
result:integer;
answer:String;
begin
result:=TotalCompute(Edit1.Text);
if(result=24)then Application.MessageBox('您真行,我服了您!','對(duì)了',MB_OK)
else
begin answer:='您輸入的表達(dá)式的計(jì)算結(jié)果為'+IntToStr(Result)+'!';Application.MessageBox(PChar(answer),'錯(cuò)了',MB_OK);
end;
end;這段程序根據(jù)自定義函數(shù)的計(jì)算結(jié)果判斷用戶的輸入正確與否,并且輸出相應(yīng)的結(jié)果以提示
用戶。
在語句“result:=TotalCompute(Edit1.Text)”中用到了一個(gè)自定義的函數(shù)TotalComp-ute,我們用它來計(jì)算用戶輸入的表達(dá)式?,F(xiàn)在我們還沒編寫這個(gè)函數(shù)的代碼,所以,目前這段代碼是無法運(yùn)行的。沒關(guān)系,可以先把它用“//”注釋掉,然后隨便給 result賦一個(gè)值,測(cè)試這個(gè)事件處理程序的其他部分是否運(yùn)行正常,例如:
//result:=TotalCompute(Edit1.Text);
result:=24;這樣,運(yùn)行后,單擊“計(jì)算”按鈕后的顯示如圖3.8所示。
圖3.8 成功的提示信息
我們用一個(gè)??????類型的??????變量存放出錯(cuò)信息,但是???????函數(shù)的第一個(gè)參數(shù)要求是?????(????????????????字符指針)類型,因此,我們用一個(gè)強(qiáng)制類型轉(zhuǎn)換將??????轉(zhuǎn)換
成?????。?4.“退出游戲”按鈕的OnClick事件
雙擊“退出游戲”按鈕,創(chuàng)建此組件的OnClick事件處理程序,然后在代碼編輯器中加入如
下所示的代碼,用于退出程序。
procedure TForm1.Button3Click(Sender: TObject);
begin
Close;
end;在上一章中我們提到可以用?????????????????????代替?????,但這里使用?????來結(jié)束程序的運(yùn)行。這樣,可以通過????????????事件來指定在什么條件下窗體可以關(guān)閉。
第3章 “速算24”撲克游戲--單元、異常、邏輯
????生成和建立程序???????????5.OnCloseQuery事件
當(dāng)調(diào)用?????方法來關(guān)閉窗體時(shí),????????????事件發(fā)生。利用????????????事件來指定在什么條件下窗體可以關(guān)閉。????????????事件包含一布爾型的????????參量,可以用它來決定窗體是否關(guān)閉。????????的默認(rèn)值為????。?可以利用????????????事件來詢問用戶是否真的希望馬上關(guān)閉窗體。?我們?cè)谶@里彈出一個(gè)對(duì)話框,代碼如下所示:
procedure TForm1.FormCloseQuery(Sender: TObject;var CanClose: Boolean);begin if(MessageDlg('現(xiàn)在要退出游戲嗎?', mtConfirmation, [mbOk, mbCancel], 0)= mrOk)then canClose:=True else canClose:=False;end;MessageDlg是一種提示對(duì)話框,第一個(gè)參數(shù)是對(duì)話框詢問的訊息,是一個(gè)字符串;第二個(gè)參數(shù)則代表對(duì)話框的類型,mtConfirmation是一個(gè)TMsgDlgType的枚舉類型,表示這個(gè)對(duì)話框是個(gè)確認(rèn)對(duì)話框。TMsgDlgType類型如下所示:
type TMsgDlgType =(mtWarning, mtError, mtInformation, mtConfirmation, mtCustom);以上定義的對(duì)話框類型分別表示:警告、錯(cuò)誤、提示、確認(rèn)和自定義類型。
第三個(gè)參數(shù)是TMsgDlgBtn類型的集合,這個(gè)集合包含了類型為TMsgDlgBtn的按鈕,TMsgDlgBtn的定義如下:
type TMsgDlgBtn =(mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mnNoToAll, mbYesToAll, mbHelp);在我們的程序中,利用了一個(gè)集合[mbOK, mbCancle],表示在對(duì)話框中顯示兩個(gè)按鈕:OK和Cancel的組合。
最后一個(gè)參數(shù)是用來描述幫助索引的長(zhǎng)整型變量,用來獲取提示用戶的幫助信息,這里我們沒有任何幫助信息,先不管它。??????????函數(shù)和用戶交互,返回一個(gè)????類型的數(shù)字,??????預(yù)先定義了一套數(shù)字,用來直觀地表示對(duì)話框返回信息。如果用戶單擊了??按鈕,這個(gè)對(duì)話框返回????,效果如圖???所示。?
圖3.9 關(guān)閉窗口時(shí)詢問用戶
現(xiàn)在,我們已經(jīng)完成了程序的主體部分。??第3章 “速算24”撲克游戲--單元、異常、邏輯
????單元間的互相引用????????3.3.1 單元引用的概念
在第?章關(guān)于單元的知識(shí)里,我們已經(jīng)知道??????可以定義不包含窗體的單元,它集中定義了程序中使用的函數(shù),這一節(jié)里,我們就要實(shí)現(xiàn)這樣的一個(gè)單元,用來實(shí)現(xiàn)上面提到的????????????函數(shù)。?我們可以在任何單元中編寫自己的函數(shù),當(dāng)然包括與窗體相連的單元??墒俏覀兂3P枰玫揭恍┏S玫暮瘮?shù),這時(shí)最好是創(chuàng)建一個(gè)不與窗體相連的獨(dú)立單元,用它來容納自己的函數(shù),這稱為獨(dú)立的單元文件。當(dāng)創(chuàng)建了不與窗體相連的獨(dú)立單元文件后,項(xiàng)目中的其他單元就能很容易地共享這些函數(shù),其他項(xiàng)目也可以很容易地調(diào)用這些函數(shù)了。?對(duì)于單元間的引用,要用到????語句。?3.3.2 uses語句
????語句告訴程序在最終的執(zhí)行代碼中需要用到哪些函數(shù)和過程。??????會(huì)自動(dòng)把一些必須的單元包括進(jìn)來,例如???????,????????,????????等。對(duì)于我們自己編寫的單元,如果程序中使用了該單元的函數(shù)或代碼,也需要包括在????部分中。?????語句具有兩種類型:公有引用和私有引用。?在?????????部分包含的????語句代表的是本單元的公有引用,就是說,這部分的引用可以被其他引用本單元的單元繼承性地引用。在?????????部分的????語句應(yīng)包含在?????????部分中的代碼所需要的單元,去掉那些??????可以自動(dòng)加入到程序中的單元。?在?????????部分包含的????語句代表的是本單元的私有引用,就是說,這部分的引用只能被本單元內(nèi)部使用。在??????????????部分的????語句應(yīng)只包含在??????????????部分中的代碼所需的單元的名字。?對(duì)于單元間的引用,要避免交叉引用。假設(shè)有兩個(gè)單元?和?,如果?出現(xiàn)在?的?????????部分的????語句中,那么單元?便不能出現(xiàn)在單元?的?????????的????語句中。因?yàn)檫@樣會(huì)產(chǎn)生對(duì)單元的循環(huán)訪問,編譯時(shí)會(huì)出現(xiàn)錯(cuò)誤信息。?3.3.3 創(chuàng)建另一個(gè)單元
創(chuàng)建一個(gè)不與窗體相連的單元文件的方法是,首先選擇主菜單的????命令,然后選擇???命令,此時(shí)??????彈出一個(gè)?????????對(duì)話框,如圖????所示。在此圖中選擇???選項(xiàng)卡中的????,然后單擊??按鈕。此時(shí)??????自動(dòng)為我們創(chuàng)建一個(gè)名為?????的獨(dú)立單元文件,并顯示在代碼編輯器中,我們只需在此加入函數(shù)即可。?
圖3.10 New Items對(duì)話框
單元?jiǎng)?chuàng)建之后,就需要實(shí)現(xiàn)單元之間的互相引用。這里有兩種方法:?(1)直接在Unit1中寫入uses Unit2,代碼如下所示:
var Form1: TForm1;implementation uses Unit2;(2)選擇主菜單的File | Use Unit命令,此時(shí)Delphi彈出Use Unit對(duì)話框,如圖3.11所示,在此窗口中列出當(dāng)前文件沒有連接的所有文件,只需選擇需要連接的文件即可。當(dāng)選擇了某一文件并單擊OK按鈕后,當(dāng)前文件就包含了對(duì)所選文件的引用。
圖3.11 Use Unit對(duì)話框
如果當(dāng)前文件已經(jīng)連接了當(dāng)前項(xiàng)目中所有其他文件,選擇????????命令后,就會(huì)彈出如圖????所示的信息窗口,告訴程序員當(dāng)前文件已經(jīng)連接了當(dāng)前項(xiàng)目中所有其他文件。?
圖3.12 Information對(duì)話框
此時(shí)再編譯,程序就沒有任何錯(cuò)誤了。?現(xiàn)在我們已經(jīng)創(chuàng)建了?????,它將用作我們的數(shù)學(xué)函數(shù)定義單元。在開始定義這個(gè)單元之前,需要先了解一下關(guān)于??????的異常處理機(jī)制。?第3章 “速算24”撲克游戲--單元、異常、邏輯
3.4 異 常 處 理
3.4.1 異常處理的概念 在應(yīng)用程序開發(fā)中如何檢測(cè)、處理程序的運(yùn)行錯(cuò)誤是一個(gè)很重要的問題。在 Delphi 的IDE(集成開發(fā)環(huán)境)中提供了一個(gè)完善的內(nèi)置調(diào)試器,可以發(fā)現(xiàn)大部分程序錯(cuò)誤。但并不是所有的錯(cuò)誤都可以被發(fā)現(xiàn),而且當(dāng)程序涉及到與外設(shè)的數(shù)據(jù)交換或操作外設(shè),如要求用戶輸入、讀寫磁盤等時(shí),錯(cuò)誤的發(fā)生是程序無法控制的,如輸入非法字符、磁盤不能讀寫等。這些情況不僅會(huì)導(dǎo)致應(yīng)用程序異常中止,而且可能引起系統(tǒng)的崩潰。針對(duì)這些問題,Delphi提供了一套強(qiáng)大的異常處理機(jī)制。巧妙地利用它,可以使程序更為強(qiáng)健,使用更為友好。
Delphi異常處理機(jī)制建立在Protected Blocks(保護(hù)塊)的概念上。所謂保護(hù)塊是指用保留字try和end封裝的一段代碼。保護(hù)塊的作用是當(dāng)應(yīng)用程序發(fā)生錯(cuò)誤時(shí)自動(dòng)創(chuàng)建一個(gè)相應(yīng)的Exception(“異?!鳖悾?。程序可以捕獲并處理這個(gè)“異?!鳖悾源_保程序的正常結(jié)束以及資源的釋放和數(shù)據(jù)不受破壞。如果程序不進(jìn)行處理,則系統(tǒng)會(huì)自動(dòng)提供一個(gè)消息框?!爱惓!鳖愂荄elphi異常處理機(jī)制的核心,也是Delphi異常處理的主要特色。Delphi提供的所有“異?!鳖惗际穷怑xception的子類。用戶也可以從類Exception派生一個(gè)自定義的“異?!鳖?。
3.4.2 資源保護(hù)方式
回收分配的資源是確保程序健壯性的一個(gè)關(guān)鍵。但默認(rèn)情況下異常發(fā)生時(shí)程序會(huì)在出錯(cuò)點(diǎn)自動(dòng)退出當(dāng)前模塊,因此需要一種特殊的機(jī)制來確保即使在異常發(fā)生的情況下,釋放資源的語句仍能被執(zhí)行,而Delphi的異常處理正提供了這種機(jī)制。
Delphi提供了一個(gè)保留字finally,用于實(shí)現(xiàn)資源的保護(hù)。
{分配資源}
try {資源使用情況} finally {釋放資源}
end;try?finally?end就形成了一個(gè)資源保護(hù)塊。finally后面的語句在任何情況下(不論程序是否發(fā)生異常)都會(huì)執(zhí)行。
在異常保護(hù)的情況下,當(dāng)異常發(fā)生時(shí),系統(tǒng)會(huì)自動(dòng)彈出一個(gè)消息框,在框中顯示異常的消息。退出當(dāng)前模塊后異常類自動(dòng)清除。
3.4.3 異常響應(yīng)方式
異常響應(yīng)為開發(fā)者提供了一個(gè)按需進(jìn)行異常處理的機(jī)制。try?except?end形成了一個(gè)異常響應(yīng)保護(hù)塊。與finally不同的是:正常情況下except 后面的語句并不被執(zhí)行,而當(dāng)異常發(fā)生時(shí)程序自動(dòng)跳到except處,進(jìn)入異常響應(yīng)處理模塊。當(dāng)異常被響應(yīng)后異常類自動(dòng)清除。
下面是異常響應(yīng)方式的一般代碼:
try {程序正常功能} except on ESomething do {響應(yīng)特定異常} else {提供默認(rèn)響應(yīng)} end;保留字on?do用于判斷異常類型。必須注意的是:except后面的語句必須包含在某一個(gè)on?do模塊中,而不能單獨(dú)存在。這是又一個(gè)與finally不同的地方。
3.4.4 提供默認(rèn)響應(yīng)
在異常響應(yīng)模塊中,一般我們只對(duì)希望響應(yīng)的特定異常進(jìn)行處理。如果一個(gè)異常發(fā)生而響應(yīng)模塊并沒有包含對(duì)它的處理代碼,則退出當(dāng)前響應(yīng)模塊,異常類仍被保留。
為了保證任何異常發(fā)生后都能在當(dāng)前響應(yīng)模塊中被清除,可以定義默認(rèn)響應(yīng):
try {程序正常功能} except on ESomething do {響應(yīng)特定異常} else {提供默認(rèn)響應(yīng)} end;由于else可以響應(yīng)任何異常,包括我們一無所知的異常,因此在默認(rèn)響應(yīng)中最好只包括諸如顯示一個(gè)消息框之類的處理,而不要改變程序的運(yùn)行狀態(tài)或數(shù)據(jù)。
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.5 數(shù)學(xué)邏輯單元(1)
此游戲程序最關(guān)鍵的地方是如何將用戶輸入的字符串表達(dá)式解析成數(shù)學(xué)表達(dá)式。為了使程序結(jié)構(gòu)清晰明了,我們將此解析代碼和程序的主代碼分開,單獨(dú)編寫成一個(gè)單元。
3.5.1 算法設(shè)計(jì)
游戲的難點(diǎn)是如何將一字符串形式的表達(dá)式解析成計(jì)算機(jī)能計(jì)算的算術(shù)表達(dá)式。例如對(duì)于字符串“3^(4*(9+4))”,如何讓計(jì)算機(jī)解析、計(jì)算。
我們的想法是按照數(shù)學(xué)四則運(yùn)算規(guī)則,先逐層進(jìn)入最里層的括號(hào),然后在括號(hào)內(nèi)部計(jì)算乘方,接著進(jìn)行乘(除)法運(yùn)算,最后按順序進(jìn)行加(減)運(yùn)算,當(dāng)本層括號(hào)內(nèi)部計(jì)算完成后,返回結(jié)果,去掉括號(hào)內(nèi)部數(shù)據(jù),退出到下一級(jí)括號(hào)(如果有)內(nèi)進(jìn)行計(jì)算。
這里面涉及的技術(shù)細(xì)節(jié)主要有下面幾點(diǎn):
(1)層層剝離括號(hào),然后從最里層的括號(hào)開始計(jì)算。(2)對(duì)于每一個(gè)運(yùn)算符號(hào),找到符號(hào)兩側(cè)的數(shù)字,形成一個(gè)計(jì)算式。
(3)每一個(gè)子計(jì)算式完成后,運(yùn)算結(jié)果返回到原始數(shù)列中,作為子串的一部分,繼續(xù)進(jìn)行上述計(jì)算。
3.5.2 字符串的相關(guān)函數(shù)
在游戲中,用戶輸入的都是字符數(shù)據(jù),我們需要從這些字符中分析得到數(shù)字和運(yùn)算符號(hào),因此要用到與字符串操作有關(guān)的函數(shù)。
function Pos(sub , all:string):integer;這個(gè)函數(shù)含有兩個(gè)參數(shù):sub表示要查找的字符,all表示原字符串。函數(shù)在字符串a(chǎn)ll中尋找指定的字符sub的位置,如果字符串中不存在sub字符,則函數(shù)結(jié)果為0。
function LastDelimiter(sub,all :string):integer 這個(gè)函數(shù)含有兩個(gè)參數(shù):sub表示要查找的字符,all表示原字符串。函數(shù)返回在字符串a(chǎn)ll中所有查找到的指定字符sub的最后一個(gè)的位置,如果字符串中不存在sub字符,則函數(shù)結(jié)果為0。
function Copy(allstring:string;first,length:integer):string 這個(gè)函數(shù)的3個(gè)參數(shù)的含義分別是:allstring代表原來的字符串,first表示拷貝開始的位置,length表示要拷貝的子串長(zhǎng)度。函數(shù)返回拷貝成功的子串。
procedure Delete(str:string;ppos,length:integer)這個(gè)過程用于刪除字符串中的一段字符。參數(shù)str代表將要操作的字符串,ppos代表開始刪除的位置,length表示將要?jiǎng)h除多少個(gè)字符。function Length(S): Integer;Length函數(shù)返回字符串S的長(zhǎng)度。
function Trim(const S: string): string;overload;function Trim(const S: WideString): WideString;overload;Trim函數(shù)返回字符串S去掉前面和后面的空格后的字符串。
下面的例子給出一個(gè)綜合利用字符串處理函數(shù)編寫的一個(gè)處理特定字符串的函數(shù),它的功能是:輸入一個(gè)字符串后,可以返回字符串中兩個(gè)單括號(hào)之間的子字符串,并去掉前面和后面帶著的空格:
function GetMyStr(const S: string): string;begin Result:=Trim(Copy(S,Pos('<',S)+1,Pos('>',S)-Pos('<',S)-1));end;比如我們?cè)诔绦蛑袑懙紾etMyStr(‘This is a test < Result to output > end of test’);,會(huì)得到字符串“Result to output”。
3.5.3 算法的代碼編寫
基于上述的考慮和知識(shí)基礎(chǔ),我們?cè)诼暶鞑糠侄x下列幾個(gè)主要函數(shù):
(1)AnyLastPos函數(shù)定位最后一個(gè)算術(shù)運(yùn)算符的位置。
function AnyLastPos(Str:String):integer;(2)AnyFirstPos函數(shù)定位最先一個(gè)算術(shù)運(yùn)算符的位置。
function AnyFirstPos(Str:String):integer;(3)AnyFirstF函數(shù)判斷最先出現(xiàn)的符號(hào)是+號(hào)、-號(hào)、*號(hào)還是/號(hào)。
function AnyFirstF(Str:String):Char;(4)SubCompute函數(shù)用于計(jì)算不帶()號(hào)的加、減、乘、除運(yùn)算。
function SubCompute(Str:String):integer;(5)TotalCompute函數(shù)用于計(jì)算表達(dá)式的結(jié)果。
function TotalCompute(Str:String):integer;1.尋找最后一個(gè)算術(shù)運(yùn)算符
定義4個(gè)整數(shù)變量SubPos,PluPos,MulPos,DivPos,在給定的字符串中尋找+,-,*,/的最后位置,將這些位置存儲(chǔ)在上述的4個(gè)變量中,然后比較4個(gè)符號(hào)出現(xiàn)的位置,得到數(shù)值最大的運(yùn)算符;在返回的結(jié)果中,返回這個(gè)運(yùn)算符的位置。
程序代碼如下所示:
function AnyLastPos(Str:String):integer;var SubPos:integer;PluPos:integer;MulPos:integer;DivPos:integer;Pos:Integer;begin //定位字符串中最后一個(gè)運(yùn)算符的位置
SubPos:=LastDelimiter('-',Str);PluPos:=LastDelimiter('+',Str);MulPos:=LastDelimiter('*',Str);DivPos:=LastDelimiter('/',Str);Pos:=SubPos;if(Pos
分別在給定的字符串中尋找+,-,*,/第一次出現(xiàn)的位置,然后比較4個(gè)符號(hào)出現(xiàn)的位置,得到數(shù)值最小的運(yùn)算符。在返回的結(jié)果中,傳遞的是這個(gè)運(yùn)算符的位置。
程序代碼如下所示:
function AnyFirstPos(Str:String):integer;var SubPos:integer;PluPos:integer;MulPos:integer;DivPos:integer;ForPos:integer;FirstPos:integer;begin //定位字符串中最先一個(gè)運(yùn)算符的位置
SubPos:=Pos('-',Str);PluPos:=Pos('+',Str);MulPos:=Pos('*',Str);DivPos:=Pos('/',Str);ForPos:=Pos('^',Str);FirstPos:=200;if(SubPos=0)then //如果沒有-號(hào)
SubPos:=200;//將SubPos設(shè)置成一個(gè)不可能的值
if(PluPos=0)then //如果沒有+號(hào)
PluPos:=200;//將PluPos設(shè)置成一個(gè)不可能的值
if(MulPos=0)then //如果沒有*號(hào)
MulPos:=200;//將MulPos設(shè)置成一個(gè)不可能的值
if(DivPos=0)then //如果沒有/號(hào)
DivPos:=200;//將DivPos設(shè)置成一個(gè)不可能的值
if(ForPos=0)then //如果沒有^號(hào)
ForPos:=200;//將ForPos設(shè)置成一個(gè)不可能的值
if(FirstPos>SubPos)then FirstPos:=SubPos;if(FirstPos>PluPos)then FirstPos:=PluPos;if(FirstPos>MulPos)then FirstPos:=MulPos;if(FirstPos>DivPos)then FirstPos:=DivPos;if(FirstPos>ForPos)then FirstPos:=ForPos;
AnyFirstPos:=FirstPos;//結(jié)束函數(shù),返回位置
end;第3章 “速算24”撲克游戲--單元、異常、邏輯
3.5 數(shù)學(xué)邏輯單元(2)
3.得到最先出現(xiàn)的運(yùn)算符類型
這個(gè)函數(shù)的返回結(jié)果是Char類型,代表這是一個(gè)字符變量。實(shí)際上,它返回的是+、-、*、/ 這4個(gè)符號(hào)中最早出現(xiàn)的一個(gè)。
程序分別尋找4個(gè)符號(hào)最早出現(xiàn)的位置,然后判斷最先出現(xiàn)的是哪一種符號(hào),再根據(jù)符號(hào)類型返回代表運(yùn)算符的字符。
在具體的實(shí)現(xiàn)過程中,因?yàn)槲覀円玫阶钕瘸霈F(xiàn)的運(yùn)算符,所以判斷的是每次尋找后各個(gè)運(yùn)算符的位置的最小值。如果不存在這個(gè)運(yùn)算符,則將代表這個(gè)運(yùn)算符位置的相應(yīng)變量設(shè)置為200。對(duì)于本程序來說,這是一個(gè)搜索過程中不可能達(dá)到的值,這樣就排除了這個(gè)位置的繼續(xù)比較的可能。
程序代碼如下所示:
function AnyFirstF(Str:String):Char;var SubPos:integer;PluPos:integer;MulPos:integer;DivPos:integer;Operator:char;tempPos:integer;begin SubPos:=Pos('-',Str);PluPos:=Pos('+',Str);MulPos:=Pos('*',Str);DivPos:=Pos('/',Str);
if(SubPos=0)then //如果沒有-號(hào)
SubPos:=200;//將SubPos設(shè)置成一個(gè)不可能的值
if(PluPos=0)then //如果沒有+號(hào)
PluPos:=200;//將PluPos設(shè)置成一個(gè)不可能的值
if(MulPos=0)then //如果沒有*號(hào)
MulPos:=200;//將MulPos設(shè)置成一個(gè)不可能的值
if(DivPos=0)then //如果沒有/號(hào)
DivPos:=200;//將DivPos設(shè)置成一個(gè)不可能的值
Operator:='-';tempPos:=SubPos;if(tempPos>PluPos)then begin tempPos:=PluPos;Operator:='+';end;if(tempPos>MulPos)then begin tempPos:=MulPos;Operator:='*';end;if(tempPos>DivPos)then begin tempPos:=DivPos;Operator:='/';end;
AnyFirstF:=Operator;//結(jié)束函數(shù),返回位置 end;4.計(jì)算不帶括號(hào)的運(yùn)算表達(dá)式
做完上述工作后,我們可以開始進(jìn)行一些實(shí)際的運(yùn)算了。
包括加、減、乘、除、乘方運(yùn)算的表達(dá)式的程序算法如下所示:
(1)尋找乘方符號(hào)“^”,如果存在,則計(jì)算一次乘方,去掉計(jì)算過的部分,接著循環(huán)查找和計(jì)算子串的乘方。
(2)尋找乘號(hào)“*”或者除號(hào)“/”,如果存在,則計(jì)算一次乘(除)法,去掉計(jì)算過的部分,接著循環(huán)計(jì)算子串的乘除法。
(3)尋找加號(hào)“+”或者減號(hào)“-”,如果存在,則計(jì)算一次加(減)法,去掉計(jì)算過的部分,接著循環(huán)計(jì)算子串的加減法。
上述算法是嚴(yán)格按照順序進(jìn)行的,它體現(xiàn)了數(shù)學(xué)運(yùn)算中的優(yōu)先關(guān)系,經(jīng)過上述的計(jì)算,子字符串被分解,計(jì)算完畢。
無論是乘方、乘除法還是加減法,內(nèi)部實(shí)現(xiàn)的邏輯是基本一致的。下面,我們?cè)O(shè)定有一個(gè)運(yùn)算表達(dá)式:3+2^5/4。
程序代碼如下所示:
function SubCompute(Str:String):integer;var Middle:String;Mul2:String;Right:String;First:integer;tempStr:String;temp:integer;Left:String;Mul1:String;MulPos:Integer;DivPos:Integer;Fuhao:Char;begin Middle:='';Mul2:='';Right:='';
//定位第一個(gè)^號(hào)位置,計(jì)算乘方
First:=Pos('^',Str);While(First<>0)do //循環(huán)計(jì)算乘方
begin tempStr:=Copy(Str,1,First-1);temp:=AnyLastPos(tempStr);Left:=Copy(Str,1,temp);Mul1:=Copy(str,temp+1,First-temp-1);tempStr:=Copy(str,First+1,Length(str)-First);temp:=AnyFirstPos(tempStr);if(temp=200)then begin Mul2:=tempStr;Right:='';end else begin Mul2 :=Copy(tempStr,1,temp-1);Right:=Copy(tempStr,temp,Length(tempStr)-temp+1);end;Middle:=FloatToStr(IntPower(StrToInt(Mul1),StrToInt(Mul2)));Str:=Left+Middle+Right;First:=Pos('^',Str);end;
//定位第一個(gè)*號(hào)或/號(hào)的位置
MulPos:=Pos('*',Str);DivPos:=Pos('/',Str);First:=MulPos;if(MulPos>DivPos)then First:=DivPos;if((DivPos=0)and(MulPos<>0))then begin First:=MulPos;DivPos:=2000;// 將除號(hào)所在位置設(shè)置成一個(gè)大于MulPos但又不可能的值
end;if((DivPos<>0)and(MulPos=0))then begin First:=DivPos;MulPos:=2000;// 將乘號(hào)所在位置設(shè)置成一個(gè)大于DivPos但不可能的值
end;while(First<>0)do //循環(huán)計(jì)算乘、除
begin tempStr:=Copy(Str,1,First-1);temp:=AnyLastPos(tempStr);Left:=Copy(Str,1,temp);Mul1:=Copy(Str,temp+1,First-temp-1);tempStr:=Copy(Str,First+1,Length(Str)-First);temp:=AnyFirstPos(tempStr);if(temp=200)then begin Mul2:=tempStr;Right:='';end else begin Mul2 :=Copy(tempstr,1,temp-1);Right:=Copy(tempStr,temp,Length(tempStr)-temp+1);end;if(MulPos>DivPos)then Middle:=IntToStr(StrToInt(Mul1)div StrToInt(Mul2))else Middle:=IntToStr(StrToInt(Mul1)*StrToInt(Mul2));Str:=Left+Middle+Right;
MulPos:=Pos('*',Str);DivPos:=Pos('/',Str);First:=MulPos;if(MulPos>DivPos)then First:=DivPos;
if((DivPos=0)and(MulPos<>0))then begin First:=MulPos;DivPos:=2000;// 將除號(hào)所在位置設(shè)置成一個(gè)大于MulPos但又不可能的值
end;if((DivPos<>0)and(MulPos=0))then begin First:=DivPos;MulPos:=2000;// 將乘號(hào)所在位置設(shè)置成一個(gè)大于DivPos但不可能的值
end;end;//定位+、-號(hào)首先出現(xiàn)的位置
First:=AnyFirstPos(Str);if(First=200)then //如果沒有+、-號(hào),則可以直接返回結(jié)果
begin SubCompute:=StrToInt(Str);exit;end;Fuhao:=AnyFirstF(Str);//確定首先出現(xiàn)的符號(hào)是+號(hào)還是-號(hào)
while(First<>0)do begin //如果找到+號(hào)或-號(hào)
tempStr:=Copy(Str,1,First-1);temp:=AnyLastPos(tempStr);Left:=Copy(Str,1,temp);Mul1:=Copy(Str,temp+1,First-temp-1);tempStr:=Copy(Str,First+1,Length(Str)-First);temp:=AnyFirstPos(tempStr);if(temp=200)then begin Mul2:=tempStr;Right:='';end else begin Mul2 :=Copy(tempStr,1,temp-1);Right :=Copy(tempStr,temp,Length(tempStr)-temp+1);end;if(Fuhao='+')then Middle:=IntToStr(StrToInt(Mul1)+StrToInt(Mul2))else Middle:=IntToStr(StrToInt(Mul1)-StrToInt(Mul2));Str:=Left+Middle+Right;First:=AnyFirstPos(Str);if(First=200)then break;Fuhao:=AnyFirstF(Str);end;
SubCompute:=StrToInt(Middle);end;程序執(zhí)行過程如下所示:
(1)定位字符串中第一個(gè)乘方符號(hào)“^”的位置First。這個(gè)式子中的First為4。
(2)如果存在乘方符號(hào),即First不等于0,則繼續(xù)進(jìn)行計(jì)算,否則退出循環(huán)。
(3)進(jìn)入循環(huán)體內(nèi)部,得到“^”前面的子串tempStr(“3+2”),尋找tempStr中的最后一個(gè)運(yùn)算符temp(這里是“+”),則Temp和First之間的字符就是乘方符號(hào)的第一個(gè)參數(shù)(“2”)。
(4)同樣的邏輯,得到“^”后面的子串tempStr(“5/4”),尋找tempStr中的第一個(gè)運(yùn)算符位置temp(“/”),則Temp和First之間的字符就是乘方符號(hào)的第二個(gè)參數(shù)(“5”)。
(5)去掉乘方符號(hào)和兩個(gè)參數(shù),得到左側(cè)子串left(“3+”)和右側(cè)子串right(“/4”)。
(6)利用這兩個(gè)參數(shù)和乘方符號(hào),計(jì)算乘方,將結(jié)果返回,并插入在left和right之間,得到一次計(jì)算后的新字符串(“3+32/4”)。
(7)判斷新串內(nèi)部是否包含“^”,如果包含,則返回到步驟(3),不包含則進(jìn)入下一種運(yùn)算。
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.5 數(shù)學(xué)邏輯單元(3)5.計(jì)算整個(gè)表達(dá)式的值
TotalCompute函數(shù)利用循環(huán),找到最內(nèi)層的一對(duì)括號(hào),然后調(diào)用SubCompute函數(shù)處理這一對(duì)括號(hào)中的表達(dá)式。SubCompute函數(shù)處理的表達(dá)式中已經(jīng)沒有括號(hào)了,因此SubCompute只需處理乘方、加、減、乘、除,返回結(jié)果,形成新的字符串。
當(dāng)整個(gè)字符串縮減至空值時(shí),整個(gè)表達(dá)式計(jì)算完成。
程序代碼如下所示:
function TotalCompute(Str:String):integer;var First:integer;Last:integer;SubStr:String;LeftStr:String;Middle:String;Right:String;temp:integer;begin First:=LastDelimiter('(',Str);//定位最后一個(gè)(號(hào)位置 while(First<>0)do begin SubStr:=Copy(Str,First+1,Length(Str)-First);Last:= Pos(')',Str);//Last:=Last+First;//定位最后一個(gè)(號(hào)以后的最開始的)號(hào)位置
LeftStr:=Copy(Str,1,First-1);//(號(hào)左邊的字符串
Middle:=Copy(Str,First+1,Last-First-1);//()號(hào)中間的字符串
Right:=Copy(Str,Last+1,Length(Str)-Last);//)號(hào)右邊的字符串
temp:=SubCompute(Middle);//進(jìn)入下面的計(jì)算
Middle:=IntToStr(temp);
Str:=LeftStr+Middle+Right;First:=LastDelimiter('(',Str);end;
Result:=SubCompute(Str);end;end.在程序中,“計(jì)算”按鈕的OnClick事件處理程序中調(diào)用TotalCompute函數(shù)。函數(shù)中使用了一些數(shù)學(xué)函數(shù)和定位字符串的函數(shù),這些函數(shù)Delphi已經(jīng)在相應(yīng)的系統(tǒng)單元中進(jìn)行了定義,我們需要把這些系統(tǒng)單元包括到文件里面:
uses Sysutils,Math;將前面調(diào)用TotalCompute的注釋去掉,把代碼改回:
procedure TForm1.Button2Click(Sender: TObject);var result:integer;answer:String;begin result:=TotalCompute(Edit1.Text);if(result=24)then Application.MessageBox('您真行,我服了您!','對(duì)了',MB_OK)else begin
第四篇:c++24點(diǎn)游戲
c++24點(diǎn)游戲
#include “iostream” #include “string” using namespace std;
//定義Stack類
const maxsize=20;
enum Error_code { success, overflow, underflow };
template
bool empty()const;bool full()const;int size()const;void clear();
Error_code top(T &item)const;Error_code pop();
Error_code push(const T &item);private: int count;T entry[maxsize];};
template
template
bool Stack
template
bool Stack
template
template
template
Error_code Stack
template
Error_code Stack
template
Error_code Stack
Stack
int set;
// 判斷程序中的異常,以便適時(shí)退出?//
void process(char c)
//計(jì)算兩個(gè)數(shù)的 +-* / 運(yùn)算// { int k=0;double a,b;sign.pop();
if(num.top(b)==success){
num.pop();
if(num.top(a)==success){ num.pop();k=1;} } if(k){ switch(c){
case '+': num.push(a+b);break;case '-': num.push(a-b);break;case '*': num.push(a*b);break;case '/': if(b==0){ set=4;num.push(-1);} else
num.push(a/b);break;} }
else {set=1;num.push(-1);} }
void get_command(string &str){
cout<<“n請(qǐng)輸入要進(jìn)行運(yùn)算的表達(dá)式,包括” +,-,*,/,=,(,)“和數(shù)字,”< <<“注意: 以數(shù)字開頭,等號(hào)結(jié)尾,中間括號(hào)要匹配.”< double do_command(const string &str){ string s=“"; double outcome=-1;char c; for(int i=0;str[i]!='