第一篇:24點(diǎn)游戲介紹
簡(jiǎn)介
它始于何年何月已無(wú)從考究,但它以自己獨(dú)具的數(shù)學(xué)魅力和豐富的內(nèi)涵正逐漸被越來(lái)越多的人們所接受。這種游戲方式簡(jiǎn)單易學(xué),能健腦益智,是一項(xiàng)極為有益的活動(dòng)。
游戲內(nèi)容
24點(diǎn)是把4個(gè)整數(shù)(一般是正整數(shù))通過(guò)加減乘除運(yùn)算,使最后的計(jì)算結(jié)果是24的一個(gè)數(shù)學(xué)游戲,可以考驗(yàn)人的智力和數(shù)學(xué)敏感性。
通常是使用撲克牌來(lái)進(jìn)行游戲的,一副牌中抽去大小王后還剩下52張(如果初練也可只用1~10這40張牌),任意抽取4張牌(稱為牌組),用加、減、乘、除(可加括號(hào))把牌面上的數(shù)算成24。每張牌必須且只能用一次,如抽出的牌是3、8、8、9,那么算式為(9—8)×8×3或3×8÷(9—8)或(9—8÷8)×3等。
普通算方法技巧
“算24點(diǎn)”作為一種撲克牌智力游戲,還應(yīng)注意計(jì)算中的技巧問(wèn)題。計(jì)算時(shí),我們不可能把牌面上的4個(gè)數(shù)的不同組合形式——去試,更不能瞎碰亂湊。這里向大家介紹幾種常用的、便于學(xué)習(xí)掌握的方法:
1.利用3×8=24、4×6=24求解。
把牌面上的四個(gè)數(shù)想辦法湊成3和8、4和6,再相乘求解。如3、3、6、10可組成(10-6÷3)×3=24或(10-3-3)×6=24。又如2、3、3、7可組成(7+3-2)×3=24等。實(shí)踐證明,這種方法是利用率最大、命中率最高的一種方法。
2.利用0、11的運(yùn)算特性求解。
如3、4、4、8可組成3×8+4—4=24等。又如4、5、J、K可組成11×(5—4)+13=24等。
3.在有解的牌組中,用得最為廣泛的是以下六種解法:(我們用a、b、c、d表示牌面上的四個(gè)數(shù))
①(a—b)×(c+d)
如(10—4)×(2+2)=24等。
②(a+b)÷c×d
如(10+2)÷2×4=24等。
③(a-b÷c)×d
如(3—2÷2)×12=24等。
④(a+b-c)×d
如(9+5—2)×2=24等。
⑤a×b+c—d
如11×3+l—10=24等。
⑥(a-b)×c+d
如(4—l)×6+6=24等。
例題1:
3388:解法8/(3-8/3)=24 按第一種方法來(lái)算,我們有8就先找3,你可能會(huì)問(wèn)這里面并沒(méi)有3,其實(shí)除以1/3,就是乘3.例題2:
5551:解法5*(5-1/5)這道題型比較特殊,5*4.8算是比較少見,一般的簡(jiǎn)便算法都是3*8,2*12,4*6,15+9,25-1,但5*4.8也是其中一種
一般情況下,先要看4張牌中是否有2,3,4,6,8,Q,如果有,考慮用乘法,將剩余的3個(gè)數(shù)湊成對(duì)應(yīng)數(shù)。如果有兩個(gè)相同的6,8,Q,比如已有兩個(gè)6,剩下的只要能湊成3,4,5都能算出24,已有兩個(gè)8,剩下的只要能湊成2,3,4,已有兩個(gè)Q,剩下的只要能湊成1,2,3都能算出24,比如(9,J,Q,Q)。如果沒(méi)有2,3,4,6,8,Q,看是否能先把兩個(gè)數(shù)湊成其中之一??傊?,乘法是很重要的,24是30以下公因數(shù)最多的整數(shù)。
(2)將4張牌加加減減,或者將其中兩數(shù)相乘再加上某數(shù),相對(duì)容易。
(3)(3)先相乘再減去某數(shù),有時(shí)不易想到。例如(4,10,10,J)
(6,10,10,K)
(4)(4)必須用到乘法,且在計(jì)算過(guò)程中有分?jǐn)?shù)出現(xiàn)。有一個(gè)規(guī)律,設(shè)4個(gè)數(shù)為a,b,c,d。必有ab+c=24或ab-c=24 d=a或b。若d=a 有a(b+c/a)=24 或 a(b-c/a)=24 如最常見的(1,5,5,5),(2,5,5,10)因?yàn)榧s分的原因也歸入此列。(5,7,7,J)
(4,4,7,7)(3,3,7,7)等等。(3,7,9,K)是個(gè)例外,可惜還有另一種常規(guī)方法,降低了難度。只能用此法的只有10個(gè)。
(5)(5)必須用到除法,且在計(jì)算過(guò)程中有分?jǐn)?shù)出現(xiàn)。這種比較難,比如(1,4,5,6),(3,3,8,8)(1,8,Q,Q)等等。
只能用此法的更少,只有7種。
(6)(6)必須用到除法,且在計(jì)算過(guò)程中有較大數(shù)出現(xiàn),不過(guò)有時(shí)可以利用平方差公式或提公因數(shù)等方法不必算出這個(gè)較大數(shù)具體等于幾。比如(3,5,7,K),(1,6,J,K)等等。只能用此法的只有16種。
(7)最特殊的是(6,9,9,10),9*10/6+9=24,9是3的倍數(shù),10是2的倍數(shù),兩數(shù)相乘的積才能整除6,再也找不出第二個(gè)類似的只能用此法解決的題目了。
需要說(shuō)明的是:經(jīng)計(jì)算機(jī)準(zhǔn)確計(jì)算,一副牌(52張)中,任意抽取4張可有1820種不同組合,其中有458個(gè)牌組算不出24點(diǎn),如A、A、A、5。有1362個(gè)牌組算得出24點(diǎn)。
正負(fù)算方法技巧
可以暫時(shí)先把負(fù)號(hào)都去掉,用正數(shù)算,看能否算出,怎么算,如果可以,再把負(fù)呈加上,有時(shí)需把原來(lái)的“加”改成“減”(例1),有時(shí)需把原來(lái)的“減”改成“加”(例2),有時(shí)不變(例3).。
例1:(3+5)*(1+2)=24 變?yōu)?[3-(-5)]*[1-(-2)]=24
例2:(12-4)*(7-4)=24 變?yōu)?[12+(-4)]*[7+(-4)]=24
例3:(3+5)*(1+2)=24 變?yōu)?[(-3)+(-5)]*[(-1)+(-2)]=24
第二篇:俏點(diǎn)介紹
俏點(diǎn),掀起韓流減胸美胸潮
2012年夏季,減胸美胸?zé)o疑成為韓國(guó)演藝圈最流行的時(shí)尚元素,眾多大牌女星紛紛加入到美胸?zé)岢敝?,成為媒體爭(zhēng)相報(bào)道的熱門話題。據(jù)媒體報(bào)道,金喜善、孫藝珍、李英愛、全智賢、李多海等當(dāng)紅明星的“胸”器,都在悄然發(fā)生改變,一些好事的“狗仔隊(duì)”更是頻頻爆冷:某某女星的胸部變得更堅(jiān)挺了,某某女星的胸部更緊致、胸型更勻稱了,凡此種種,多不勝數(shù)。更令人意想不到的是,就連有美乳女神之稱的韓藝瑟,也成為韓國(guó)“愛茉莉頂級(jí)塑胸美胸品牌中心”的VIP會(huì)員,不甘示弱的加入到了美胸?zé)岢敝小?/p>
據(jù)悉,愛茉莉頂級(jí)塑胸美胸品牌中心最新推出的俏點(diǎn)(胸部緊致活氧冰極霜),正是掀起韓流美胸?zé)岢钡氖甲髻刚?,而其倡?dǎo)的“6度性感美乳”標(biāo)準(zhǔn),更是被亞洲各國(guó)的女性美胸機(jī)構(gòu)奉為新的金科玉律,而被遵守了20多年的“4S美胸”標(biāo)準(zhǔn),正逐漸被“6度美胸“標(biāo)準(zhǔn)所取代。胸部美容概念,在2012年被俏點(diǎn)重新定義。
愛茉莉頂級(jí)塑胸美胸品牌中心,最新推出的終極減胸美胸產(chǎn)品——俏點(diǎn)胸部緊致活氧冰極霜,是37位美胸專家27年的智慧結(jié)晶,也是目前最頂級(jí)的美胸護(hù)理產(chǎn)品。
俏點(diǎn)采用國(guó)際最高端的超臨界無(wú)毒萃取技術(shù)和透皮吸收技術(shù),30多種純天然生物萃取精華可強(qiáng)力滲透到皮下組織、進(jìn)入脂肪堆積部位,通過(guò)發(fā)揮靶向燃脂的作用,迅速抑制胸部脂肪合成,擴(kuò)大脂肪的分解、排出。同時(shí),各種精華液和緊致營(yíng)養(yǎng)成分通過(guò)全面滋養(yǎng)胸部細(xì)胞,防止縮乳后皮膚松弛、乳房下垂,并保持胸型上翹與堅(jiān)挺,讓胸部更輕盈緊致!縮胸美胸安全不反彈!達(dá)到您理想的乳型效果!13萬(wàn)率先使用俏點(diǎn)的乳房肥大患者反饋?zhàn)C實(shí):一般2個(gè)周期,胸型即可無(wú)限接近34B,胸部曲線變得更加完美、緊致、不下垂、不外擴(kuò)、不走形、雙乳勻稱挺拔、彈力十足,讓所有的男人為您怦然心動(dòng)。
韓國(guó)俏點(diǎn),全稱俏點(diǎn)胸部緊致活氧冰極霜,特有的CHF初乳活性營(yíng)養(yǎng)成分及酥梨提取液,有效凈化乳房循環(huán),全方位滋養(yǎng)乳房,修復(fù)耗損的腺泡和結(jié)締組織,強(qiáng)化乳房支撐和塑形力,防止脂肪擴(kuò)散、乳房萎縮,帶動(dòng)高濃度的膠原蛋白有效促進(jìn)乳房?jī)?nèi)彈力纖維修復(fù)和網(wǎng)絡(luò)的形成,增加肌肉組織和彈力纖維的力量,增強(qiáng)乳房的筋膜和韌帶彈性,加強(qiáng)乳房的支持,保持乳房的形狀,達(dá)到改善乳房彈性,結(jié)實(shí)乳房組織,提升胸形效能,可使女性胸部平均提升25度,充滿彈性、白嫩、柔滑,讓您成為最具誘惑力的美乳女神。
五大權(quán)威保證
權(quán)威一:國(guó)際頂尖美胸品牌中心研制 全球久具盛名的知名美胸品牌公司——韓國(guó)“愛茉莉頂級(jí)塑胸美胸品牌中心”最新研發(fā)成果,匯聚全球減胸美胸最前沿的巔峰技術(shù),6度美胸標(biāo)準(zhǔn)的奠基者和引導(dǎo)著,備受13萬(wàn)上層女性寵愛的終極減胸美胸產(chǎn)品。
權(quán)威二: 最科學(xué)的燃脂減胸美胸技術(shù)美國(guó)哈佛大學(xué)生物技術(shù)研究院獨(dú)家授權(quán),具有全球領(lǐng)先的燃脂減胸美胸技術(shù)被首次應(yīng)用于俏點(diǎn),經(jīng)全球12家頂級(jí)美容機(jī)構(gòu)嚴(yán)格的臨床證實(shí),俏點(diǎn)7天起效、1周期明顯見效,2周期即可塑造完美胸型,有效率高達(dá)99.65%。
權(quán)威三: 最天然安全的植物精華成份外用靶向滲透,不傷肝腎;純天然植物精華,絕不添加任何違禁成份,成為首個(gè)通過(guò)美國(guó)FDA認(rèn)證的韓國(guó)民族美容品牌。
權(quán)威四: 最持久的減胸美胸終極產(chǎn)品 減胸美胸不反彈,經(jīng)13萬(wàn)女性聯(lián)合聯(lián)合驗(yàn)證,只需足量使用2—3個(gè)周期俏點(diǎn),即可重新建立乳房?jī)?nèi)分泌協(xié)調(diào)機(jī)制,從根源上促進(jìn)乳房自我免疫調(diào)節(jié)能力,確保40年不反彈,成為韓國(guó)效果最持久的美胸終極產(chǎn)品。
權(quán)威五:亞太13國(guó)和地區(qū)女性美胸協(xié)會(huì)聯(lián)合認(rèn)證韓國(guó)、日本、中國(guó)大陸、臺(tái)灣、香港、新加坡等13國(guó)和地區(qū)女性美胸協(xié)會(huì)全程聯(lián)合公證,俏點(diǎn)效果可靠、安全可靠,成為首個(gè)亞太地區(qū)免檢的知名品牌。
俏點(diǎn)30天打造6度性感美胸
豐滿度:韓國(guó)俏點(diǎn)純天然生物精華成份通過(guò)發(fā)揮靶向燃脂作用,迅速抑制胸部脂肪合成,擴(kuò)大脂肪的分解、排出,只需短短40天,就能使胸部無(wú)限趨近34B,豐而不肥、滿而不大的完美“胸”器,盡顯自然和諧極致之美。
挺拔度:俏點(diǎn)特有純天然生物精華,通過(guò)修復(fù)耗損的腺泡和結(jié)締組織,強(qiáng)化乳房支撐和塑形力,只需30天,就能使松松垮垮的乳房挺起來(lái),二指深的誘惑乳溝、挺拔傲立的乳峰,都讓男人欲罷不能、如癡如醉。
緊致度:俏點(diǎn)植物精華緊致成分通過(guò)全面滋養(yǎng)胸部細(xì)胞,防止縮乳后皮膚松弛、乳房下垂,并能持續(xù)保持胸型上翹與堅(jiān)挺,讓胸部更輕盈緊致富有彈性,僅需30天,就能快速塑造出優(yōu)雅迷人的性感曲線。
嫩滑度:俏點(diǎn)特有的營(yíng)養(yǎng)精華成分,通過(guò)整體胸部調(diào)節(jié)內(nèi)分泌、補(bǔ)充各種營(yíng)養(yǎng),讓胸部細(xì)胞吃飽喝足,加快細(xì)胞新陳代謝、強(qiáng)化細(xì)胞再生,讓胸部24小時(shí)白嫩柔滑,讓男人在波動(dòng)誘惑面前心動(dòng)神搖。
勻稱度:俏點(diǎn)特有精華成分,通過(guò)靶向燃燒乳房?jī)蓚?cè)的多余厚脂肪,使外擴(kuò)、走形的胸部迅速上翹勻稱、渾然天成,當(dāng)您勻稱挺拔的胸部略微挺起的那一刻,男人早已經(jīng)心猿意馬、徹底傾倒。
敏感度:俏點(diǎn)豐富的精華成分,能夠逐漸激活乳房韌帶結(jié)締組織細(xì)胞,增強(qiáng)細(xì)胞與細(xì)胞質(zhì)間的結(jié)合度,提高乳腺基底細(xì)胞興奮度,讓女性胸部細(xì)胞的敏感度迅速提高
五類女性急需俏點(diǎn)美胸 肥大人群:
胸部自身組織大,乳腺胸,人不高,也不胖,就是胸部很大,與身材不配,整體不和諧,或者是家族遺傳者;胸部脂肪堆積人群:
身軀較小、身材單薄,但是由于雌性激素分泌過(guò)旺、脂肪過(guò)多導(dǎo)致乳房重度肥大,形成巨乳人群;胸型嚴(yán)重失衡人群:
因?yàn)楦鞣N原因?qū)е碌男匦屯鈹U(kuò)、走形、贅肉、大小不
一、高低不一的女性人群;
胸部下垂、松弛人群:
隨著乳房增大,而使乳房彈性降低,加之重力的作用,致使乳房松馳、下垂、乳房外擴(kuò)的各類人群; 胸部急需護(hù)理人群:
乳房左右不勻稱、不夠白皙、彈滑、乳暈色澤暗沉的愛美女性,急需專業(yè)呵護(hù)保養(yǎng)的廣大人群;
第三篇:delphi24點(diǎn)游戲
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.1 “速算24”撲克游戲效果說(shuō)明
“速算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í)間。下面我們來(lái)生成游戲的基本框架。
3.2.1 Image組件
Image組件在Additional頁(yè)上,用來(lái)在窗口中顯示一幅圖片。它擁有如下幾個(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ù)它所包含的圖像的大小來(lái)調(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)沒(méi)有作用。
上述的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頁(yè)上的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無(wú)關(guān)的邏輯和應(yīng)用事件時(shí)極其有用。可以模擬時(shí)鐘或計(jì)時(shí)器,可視地顯示經(jīng)過(guò)的時(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í)間超過(guò)Interval的設(shè)定值,就可能錯(cuò)過(guò)事件,因?yàn)楫?dāng)下一次觸發(fā)到來(lái)時(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頁(yè)中的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事件句柄中,增加下面的語(yǔ)句,使Timer1無(wú)效:
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頁(yè)中的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ù)字,通過(guò)加減乘除運(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)頁(yè)中的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í)界面,只有界面沒(méi)有事件響應(yīng)。是程序創(chuàng)建過(guò)程中的一個(gè)步驟的檢驗(yàn)。但是,這個(gè)程序還沒(méi)有什么具體的功能,為了讓游戲運(yùn)行起來(lái),必須添加代碼,創(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)語(yǔ)句,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)則利用初始化過(guò)后的隨機(jī)數(shù)種子產(chǎn)生一個(gè)1~i之間的隨機(jī)數(shù)。這里i設(shè)定為13,以配合撲克牌的張數(shù)13。
???????????????????用來(lái)將一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)字符串,和上一章中的??????????????????的功能恰好相反。?我們已經(jīng)預(yù)先準(zhǔn)備了位圖文件,它們都是???形式,文件名則是利用數(shù)字????命名。??????中特殊的字符串運(yùn)算符???將兩個(gè)字符串串聯(lián)起來(lái),產(chǎn)生一個(gè)新的字符串,我們需要的位圖文件后綴是???,因此,在產(chǎn)生文件名的時(shí)候,在數(shù)字后面加上??????這個(gè)字符串。?????語(yǔ)句在上一章中已經(jīng)講過(guò),單擊?開始?按鈕后,準(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é)果以提示
用戶。
在語(yǔ)句“result:=TotalCompute(Edit1.Text)”中用到了一個(gè)自定義的函數(shù)TotalComp-ute,我們用它來(lái)計(jì)算用戶輸入的表達(dá)式?,F(xiàn)在我們還沒(méi)編寫這個(gè)函數(shù)的代碼,所以,目前這段代碼是無(wú)法運(yùn)行的。沒(méi)關(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;在上一章中我們提到可以用?????????????????????代替?????,但這里使用?????來(lái)結(jié)束程序的運(yùn)行。這樣,可以通過(guò)????????????事件來(lái)指定在什么條件下窗體可以關(guān)閉。
第3章 “速算24”撲克游戲--單元、異常、邏輯
????生成和建立程序???????????5.OnCloseQuery事件
當(dāng)調(diào)用?????方法來(lái)關(guān)閉窗體時(shí),????????????事件發(fā)生。利用????????????事件來(lái)指定在什么條件下窗體可以關(guān)閉。????????????事件包含一布爾型的????????參量,可以用它來(lái)決定窗體是否關(guān)閉。????????的默認(rèn)值為????。?可以利用????????????事件來(lái)詢問(wè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ì)話框詢問(wèn)的訊息,是一個(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ù)是用來(lái)描述幫助索引的長(zhǎng)整型變量,用來(lái)獲取提示用戶的幫助信息,這里我們沒(méi)有任何幫助信息,先不管它。??????????函數(shù)和用戶交互,返回一個(gè)????類型的數(shù)字,??????預(yù)先定義了一套數(shù)字,用來(lái)直觀地表示對(duì)話框返回信息。如果用戶單擊了??按鈕,這個(gè)對(duì)話框返回????,效果如圖???所示。?
圖3.9 關(guān)閉窗口時(shí)詢問(wèn)用戶
現(xiàn)在,我們已經(jīng)完成了程序的主體部分。??第3章 “速算24”撲克游戲--單元、異常、邏輯
????單元間的互相引用????????3.3.1 單元引用的概念
在第?章關(guān)于單元的知識(shí)里,我們已經(jīng)知道??????可以定義不包含窗體的單元,它集中定義了程序中使用的函數(shù),這一節(jié)里,我們就要實(shí)現(xiàn)這樣的一個(gè)單元,用來(lái)實(shí)現(xiàn)上面提到的????????????函數(shù)。?我們可以在任何單元中編寫自己的函數(shù),當(dāng)然包括與窗體相連的單元。可是我們常常需要用到一些常用的函數(shù),這時(shí)最好是創(chuàng)建一個(gè)不與窗體相連的獨(dú)立單元,用它來(lái)容納自己的函數(shù),這稱為獨(dú)立的單元文件。當(dāng)創(chuàng)建了不與窗體相連的獨(dú)立單元文件后,項(xiàng)目中的其他單元就能很容易地共享這些函數(shù),其他項(xiàng)目也可以很容易地調(diào)用這些函數(shù)了。?對(duì)于單元間的引用,要用到????語(yǔ)句。?3.3.2 uses語(yǔ)句
????語(yǔ)句告訴程序在最終的執(zhí)行代碼中需要用到哪些函數(shù)和過(guò)程。??????會(huì)自動(dòng)把一些必須的單元包括進(jìn)來(lái),例如???????,????????,????????等。對(duì)于我們自己編寫的單元,如果程序中使用了該單元的函數(shù)或代碼,也需要包括在????部分中。?????語(yǔ)句具有兩種類型:公有引用和私有引用。?在?????????部分包含的????語(yǔ)句代表的是本單元的公有引用,就是說(shuō),這部分的引用可以被其他引用本單元的單元繼承性地引用。在?????????部分的????語(yǔ)句應(yīng)包含在?????????部分中的代碼所需要的單元,去掉那些??????可以自動(dòng)加入到程序中的單元。?在?????????部分包含的????語(yǔ)句代表的是本單元的私有引用,就是說(shuō),這部分的引用只能被本單元內(nèi)部使用。在??????????????部分的????語(yǔ)句應(yīng)只包含在??????????????部分中的代碼所需的單元的名字。?對(duì)于單元間的引用,要避免交叉引用。假設(shè)有兩個(gè)單元?和?,如果?出現(xiàn)在?的?????????部分的????語(yǔ)句中,那么單元?便不能出現(xiàn)在單元?的?????????的????語(yǔ)句中。因?yàn)檫@樣會(huì)產(chǎn)生對(duì)單元的循環(huán)訪問(wè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)前文件沒(méi)有連接的所有文件,只需選擇需要連接的文件即可。當(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í)再編譯,程序就沒(méi)有任何錯(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è)很重要的問(wèn)題。在 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ā)生是程序無(wú)法控制的,如輸入非法字符、磁盤不能讀寫等。這些情況不僅會(huì)導(dǎo)致應(yīng)用程序異常中止,而且可能引起系統(tǒng)的崩潰。針對(duì)這些問(wèn)題,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ī)制來(lái)確保即使在異常發(fā)生的情況下,釋放資源的語(yǔ)句仍能被執(zhí)行,而Delphi的異常處理正提供了這種機(jī)制。
Delphi提供了一個(gè)保留字finally,用于實(shí)現(xiàn)資源的保護(hù)。
{分配資源}
try {資源使用情況} finally {釋放資源}
end;try?finally?end就形成了一個(gè)資源保護(hù)塊。finally后面的語(yǔ)句在任何情況下(不論程序是否發(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 后面的語(yǔ)句并不被執(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后面的語(yǔ)句必須包含在某一個(gè)on?do模塊中,而不能單獨(dú)存在。這是又一個(gè)與finally不同的地方。
3.4.4 提供默認(rèn)響應(yīng)
在異常響應(yīng)模塊中,一般我們只對(duì)希望響應(yīng)的特定異常進(jìn)行處理。如果一個(gè)異常發(fā)生而響應(yīng)模塊并沒(méi)有包含對(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)任何異常,包括我們一無(wú)所知的異常,因此在默認(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代表原來(lái)的字符串,first表示拷貝開始的位置,length表示要拷貝的子串長(zhǎng)度。函數(shù)返回拷貝成功的子串。
procedure Delete(str:string;ppos,length:integer)這個(gè)過(guò)程用于刪除字符串中的一段字符。參數(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 //如果沒(méi)有-號(hào)
SubPos:=200;//將SubPos設(shè)置成一個(gè)不可能的值
if(PluPos=0)then //如果沒(méi)有+號(hào)
PluPos:=200;//將PluPos設(shè)置成一個(gè)不可能的值
if(MulPos=0)then //如果沒(méi)有*號(hào)
MulPos:=200;//將MulPos設(shè)置成一個(gè)不可能的值
if(DivPos=0)then //如果沒(méi)有/號(hào)
DivPos:=200;//將DivPos設(shè)置成一個(gè)不可能的值
if(ForPos=0)then //如果沒(méi)有^號(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)過(guò)程中,因?yàn)槲覀円玫阶钕瘸霈F(xiàn)的運(yùn)算符,所以判斷的是每次尋找后各個(gè)運(yùn)算符的位置的最小值。如果不存在這個(gè)運(yùn)算符,則將代表這個(gè)運(yùn)算符位置的相應(yīng)變量設(shè)置為200。對(duì)于本程序來(lái)說(shuō),這是一個(gè)搜索過(guò)程中不可能達(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 //如果沒(méi)有-號(hào)
SubPos:=200;//將SubPos設(shè)置成一個(gè)不可能的值
if(PluPos=0)then //如果沒(méi)有+號(hào)
PluPos:=200;//將PluPos設(shè)置成一個(gè)不可能的值
if(MulPos=0)then //如果沒(méi)有*號(hào)
MulPos:=200;//將MulPos設(shè)置成一個(gè)不可能的值
if(DivPos=0)then //如果沒(méi)有/號(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ì)算過(guò)的部分,接著循環(huán)查找和計(jì)算子串的乘方。
(2)尋找乘號(hào)“*”或者除號(hào)“/”,如果存在,則計(jì)算一次乘(除)法,去掉計(jì)算過(guò)的部分,接著循環(huán)計(jì)算子串的乘除法。
(3)尋找加號(hào)“+”或者減號(hào)“-”,如果存在,則計(jì)算一次加(減)法,去掉計(jì)算過(guò)的部分,接著循環(huán)計(jì)算子串的加減法。
上述算法是嚴(yán)格按照順序進(jìn)行的,它體現(xiàn)了數(shù)學(xué)運(yùn)算中的優(yōu)先關(guān)系,經(jīng)過(guò)上述的計(jì)算,子字符串被分解,計(jì)算完畢。
無(wú)論是乘方、乘除法還是加減法,內(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 //如果沒(méi)有+、-號(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í)行過(guò)程如下所示:
(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)沒(méi)有括號(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]!='