在日常學(xué)習(xí)、工作或生活中,大家總少不了接觸作文或者范文吧,通過文章可以把我們那些零零散散的思想,聚集在一塊。范文怎么寫才能發(fā)揮它最大的作用呢?接下來小編就給大家介紹一下優(yōu)秀的范文該怎么寫,我們一起來看一看吧。
delphi游戲開發(fā)篇一
填空題20×1 簡答題5×6 程序填空題11×2 編程題2×14 資料整理的不是完全完整,結(jié)合這些重點可以在書上再仔細復(fù)習(xí)。希望好好復(fù)習(xí),大家都能通過!
第一章delphi簡介
1.1delphi概念 delphi的主要特點: borland公司的pascal編譯器 delphi以object pascal為編程語言 delphi充分發(fā)揮了windows的強大功能 delphi提供了豐富的32位可視組件庫
delphi在數(shù)據(jù)庫和網(wǎng)絡(luò)處理功能方面是同類產(chǎn)品中最強的
1.2delphi7集成開發(fā)環(huán)境
主窗口:包括菜單欄,工具欄及組件欄; 對象游覽器:包括屬性頁和事件頁; 對象樹性列表; 窗體設(shè)計器; 代碼編輯器;
1.3delphi程序的基本結(jié)構(gòu)
擴展名為dpr的是項目文件;擴展名為pas的單元文件;擴展名為dfm的是窗體文件
單元文件的格式如下:
單元頭:該單元指定單元的名稱
接口部分:該部分從保留字interfact開始,到保留字implementation之前結(jié)束。接口部分可以有uses語句,還可以用來聲明常量,數(shù)據(jù)類型,變量,過程和函數(shù)等。其中uses語句必須緊跟在保留字interfact之后。在整個程序中都可以被訪問
實現(xiàn)部分:這些聲明可以在本單元中被訪問,不可以在其他單元中被訪問,類的方法必須在實現(xiàn)部分實現(xiàn)
初始化部分:從保留字implementation開始,到保留字finalization之前結(jié)束。一個單元中可以沒有該部分。
結(jié)束部分:一個單元中只有出現(xiàn)了初始化部分,才可以有結(jié)束部分
第二章object pascal語言基礎(chǔ) 2.1詞法符號 保留字
標識符:1標識符由字母,數(shù)字或下劃線組成 2標示符的第一個字符必須是字母或下劃線 3標識符的長度不應(yīng)超過255個字符 4不能將保留字用作標識符 5標識符不區(qū)分大,小寫
標準標識符是可以重新定義的,而保留字卻不允許重新定義
因system單元是自動應(yīng)用的,不必也不允許在引用部分列出system單元 absolute指令字用于指示相同類型的另一標識符存放在同一段內(nèi)存區(qū)域中 2.2常量和變量
布爾常量是指false和true這兩個值 用#引導(dǎo)一個整數(shù),整數(shù)表示該字符的ascii碼 用‘’‘’表示單引號字符 2.3簡單數(shù)據(jù)類型
數(shù)據(jù)類型分為簡單數(shù)據(jù)類型,字符串類型,結(jié)構(gòu)類型,指針類型,過程與函數(shù)類型和可變類型等是一種常見的分類方法
有序數(shù)據(jù)類型特點:
1、數(shù)據(jù)的分布是離散的;
2、除了第一個元素外,其他任何元素都有一個前驅(qū)元素;
3、除了最后一個元素外,其他任何元素都有一個后繼元素
關(guān)系運算符號:=,<>,>≡,>,<≡,< 整型數(shù)的邏輯運算符:not,and,or,xor 左,右移位運算符:shl,shr 基本字型有ansichar和widechar pascal語言提供的自變量為實型的標準函數(shù)由: 1絕對值函數(shù)abs(x):函數(shù)值為x的絕對值 2平方函數(shù)sqr(x):函數(shù)值為x的平方
3正弦函數(shù)sin(x):函數(shù)值為x的正弦,其中x的單位為弧度 4余弦函數(shù)cos(x):函數(shù)值為x的余弦,其中x的單位為弧度 5反正切函數(shù)arctan(x):函數(shù)值為x的正反切,函數(shù)值的單位為弧度 6指數(shù)函數(shù)exp(x):函數(shù)值為指數(shù)e 的x次方 7對數(shù)函數(shù)in(x):函數(shù)值為x的自然對數(shù) 8平方根函數(shù)sqrt(x):函數(shù)值為x的平方根
9舍入函數(shù)round(x):對實數(shù)x作四舍五入,結(jié)果為整數(shù) 10截尾取整函數(shù)trunc(x):截去實數(shù)x的小數(shù)部分,結(jié)果為整數(shù) object pascal提供了豐富的日期時間處理函數(shù),常用的有: 1date0:函數(shù)返回系統(tǒng)當前日期,無參數(shù),返回數(shù)據(jù)是tdate time型 2time0:函數(shù)返回系統(tǒng)當前時間,無參數(shù),返回數(shù)據(jù)是tdate time型 3now0:函數(shù)返回系統(tǒng)當前日期和時間,無參數(shù),返回數(shù)據(jù)是tdate time型 4strtodte(日期字符串):字符串轉(zhuǎn)換為日期時間函數(shù),返回數(shù)據(jù)是tdate time型
2.4結(jié)構(gòu)類型 結(jié)構(gòu)數(shù)據(jù): —集合類型(set)—數(shù)組類型(arry)—記錄類型(record)—文件類型(file)—類類型(class)
—類引用類型(class reference)—接口類型(interfact)
object pascal中規(guī)定了基類型只能是不超過265個有序值的集合,集合元素的敘數(shù)值必須介于0~~255之間
集合運算有交(*),并(+),差(—),運算對象是兩個相同類型的集合,運算結(jié)果也是集合。例如,若有為[1,3,5],y為[3,4,5],則x*y為[3,5],x+y為[1,3,4,5],x-y為[1] 數(shù)組的定義:type arry [indextype。。,indextypen] of basetype ①對于通用字符串類型string,指定其最大長度(0------255)。此時string型被視為shortstring型
②shortstring型不是以null(空字符#0)作為字符串的結(jié)果標志,而是將長度保存在字符串數(shù)組下標為0的儲存單元中 ③ansistring以full結(jié)束
記錄的定義: type 記錄類型標識符=record 域1:類型1 域2:類型2。。。。域n:類型n 2.6語句流程 語法形式: 輸入語言
read([文件變量]變量列表)
readln([文本文件變量]變量列表)有回車 省略文本變量參數(shù)表示從鍵盤輸入中讀取數(shù)據(jù) 輸出語言
write([文件變量]輸出項表)
writeln([文本文件變量]輸出項表)有回車
注釋和編譯指令 //單行注釋內(nèi)容 {注釋內(nèi)容}(*注釋內(nèi)容*)
case語句的語法格式: case選擇表達式of 常量1:語句1 常量2:語句2。。。。
常量n-1:語句n-1 [else語句n;] end;
保留字case后的選擇表達式,其值必須是有序類型,如整型,字符型,布爾型,枚舉型或子界型 p45頁程序
while語句的執(zhí)行過程是:先計算布爾表達式的值,當值為true時,執(zhí)行循環(huán)體中的語句序列,然后重新計算布爾表達式的值,若仍為true則再執(zhí)行一遍循環(huán)體
while語句的特點是先判斷條件,當條件為true才執(zhí)行。當?shù)谝淮螚l件為false時,循環(huán)次數(shù)為0
repeat語句的執(zhí)行過程是:先執(zhí)行repeat到until之間的語句,然后計算布爾表達式的值,若為false,則再執(zhí)行repeat到until之間的語句,若為true則推出循環(huán)體
break過程,可使程序的執(zhí)行流程立即退出該層循環(huán) continue過程將使程序直接轉(zhuǎn)入下一次循環(huán) 2.7過程與函數(shù)
procedure過程名(參數(shù)表)
function函數(shù)名(參數(shù)表):返回數(shù)據(jù)類型 過程由過程首部、局部聲明部分和過程體組成。函數(shù)由函數(shù)首部、局部聲明部分和函數(shù)體組成。
參數(shù)的傳遞如下:
1值參數(shù)聲明時,形參前面無任何修飾
2變量參數(shù)聲明時 變參傳遞的是一個變量的地址,即實參把地址傳遞的是一個變量的地址,即實參把地址傳遞給變參,變參和實參指向的是同一地址空間。在過程和函數(shù)中對變參的修改直接影響實參 3常量參數(shù)聲明時,形參的前面用保留字const修飾
過程和函數(shù)重裁是指定義多個名稱相同,而參數(shù)列表不同的過程和函數(shù)。編譯器根據(jù)調(diào)用時實參表中的參數(shù)個數(shù)和類型,自動匹配一個重裁的過程或函數(shù)。重裁過程或函數(shù)使用默認參數(shù)可能會導(dǎo)致二義性錯誤 2.8程序與單元的結(jié)構(gòu) 單元結(jié)構(gòu): 1單元首部
2接口部分:定義的這些標識符可以被引用該單元的程序訪問 3實現(xiàn)部分:在實現(xiàn)部分定義的標志符不能被其他單位或程序訪問 4初始部分 5終結(jié)部分
2.9標識符的作用域
標識符的作用域是指其在程序中起作用的范圍。
單元中接口部分定義的標識符包括數(shù)據(jù)類型,類,常數(shù),變量,過程和函數(shù)導(dǎo)等 他們在引用該單元的程序(項目文件,其他單元)中都可以被訪問
第三章 delphi中的面向?qū)ο?3.1面向?qū)ο蟪绦蛟O(shè)計概述
將具有相同屬性和行為的對象抽象為類,每個對象都屬于某個類。通過繼承關(guān)系構(gòu)成類的層次結(jié)構(gòu),子類可以直接繼承父類的性質(zhì)和功能。3.2類與對象
類是具有相同或相似屬性和行為的一組對象的共同描述,是對相似對象建立的模板。
對象由屬性和方法構(gòu)成。屬性是描述對象靜態(tài)特征的一組數(shù)據(jù)想:方法描述了該類對象動態(tài)特征的一個操作序列,體現(xiàn)對象的行為特征或功能。定義類:type 類名=class 數(shù)據(jù)成員
成員函數(shù)或過程 end;
注意:在函數(shù)或過程名前必須帶有類名。procedure ; 聲明對象一般形式為:var 對象名:類名; 訪問對象成員:對象名.成員
構(gòu)造函數(shù)和析構(gòu)函數(shù)的定義,作用和特點:
構(gòu)造函數(shù)是專用的創(chuàng)建對象和初始化對象的成員函數(shù)。定義時用保留字constructor,函數(shù)名通常為create。在定義的構(gòu)造函數(shù)中,不僅可以為類對象分配內(nèi)存空間,而且可以打開文件或數(shù)據(jù)庫讀取數(shù)據(jù)或控制設(shè)備復(fù)位。析構(gòu)函數(shù)是專用的刪除對象和為對象進行善后處理的成員函數(shù)。定義時用保留字destructor,函數(shù)名通常為destroy。在析構(gòu)函數(shù)中,不僅可以釋放相應(yīng)的內(nèi)存資源,還可以保存數(shù)據(jù)信息,關(guān)閉文件或者數(shù)據(jù)庫,控制設(shè)備復(fù)位并關(guān)機。3.3類成員的訪問權(quán)限
封裝是把一組數(shù)據(jù)和與這組數(shù)據(jù)有關(guān)的操作集合組裝在一起,形成一個能動的實體,也就是對象。
訪問權(quán)限分為:private:私有數(shù)據(jù)成員、成員函數(shù)、過程。不能被類所在單元以外的程序訪問,但本單元是可見的。
protected:保護??。被該類及該類的所有派生類訪問,并成為派生類的私有成員。
public:共有??。被該類以外的類訪問。
published:公布??。在設(shè)計期間的對象觀察器窗口中可見。
automated:自動??。用于響應(yīng)對象鏈接與嵌入自動化類型信息的公共接口。3.4繼承
繼承的實質(zhì)是在既有類的基礎(chǔ)上構(gòu)造新的類,即新類從一個或者多個已有類中繼承數(shù)據(jù)和方法,同時增加或重新定義數(shù)據(jù)和方法,由此構(gòu)造出一個新的類型,稱為派生類。已有的類稱為基類。繼承的主要目的是實現(xiàn)代碼的重用。派生類的定義:type 派生類=class(基類){派生類新增或改寫部分} end;
派生類的構(gòu)造和析構(gòu)函數(shù):在派生類構(gòu)造函數(shù)的開始部分,使用inherited保留字來調(diào)用基類的構(gòu)造函數(shù),首先初始化基類的成員,然后構(gòu)造派生類的特有成員。在派生類的析構(gòu)函數(shù)的結(jié)尾部分,使用inherited保留字來調(diào)用基類的析構(gòu)函數(shù),最后釋放基類的成員部分。
構(gòu)造函數(shù)越上層越早被調(diào)用,析構(gòu)函數(shù)越下層越早被調(diào)用。3.5多態(tài)性
多態(tài)性是指同一的操作,在不同的對象中具體實現(xiàn)過程不同。object pascal 支持兩種多態(tài)性和運行時的多態(tài)性。編譯時的多態(tài)性通過重載來實現(xiàn),運行時的多態(tài)性用虛方法來實現(xiàn)。
重載函數(shù)或者過程用保留字overload來說明。例如:function max(x:integer):integer;integer; 虛方法的定義如p79 虛方法與動態(tài)方法的區(qū)別:在運行時才能確定對象方法的調(diào)用地址,這種調(diào)用方法為動態(tài)聯(lián)編。虛方法與動態(tài)方法在功能上是等價的,不同在于虛方法額調(diào)用速度比較快,動態(tài)方法的代碼比較少。
抽象類與抽象方法:使用指令字abstract說明,則該方法稱為抽象方法,包含抽象方法的類稱為抽象類。定義:procedure 過程名;virtual;abstract;
第四章
4.1 vcl基礎(chǔ)
四種基本的組件類型:標準組件,自定義組件,圖形組件,非可視組件。圖形組件與標準組件的的區(qū)別在于:①標準組件可以獲得輸入焦點,即可用tab鍵依次獲得焦點;圖形組件不能獲得輸入焦點。②標準組件可以包含其他組件,即可以是其他組件的父類;圖形組件不能包含其他組件。③標準組件具有一個windows句柄,圖形組件沒有windows句柄。
4.2窗體設(shè)計
窗體組件的屬性值設(shè)置為 組件名.屬性:=屬性值。重點看一下caption、visible、hint。
窗體的方法和事件詳見p91.4.3常用vcl組件
對于memo組件的編程填空要注意。列表框組件(listbox)的常用屬性見p104 4.4菜單設(shè)計
對菜單項可以指定其加速鍵,方法是在菜單項的caption屬性中,在要作為加速鍵的字母前添加符號“&”,則運行時該字母帶有下劃線,按下alt+加速字母鍵就執(zhí)行此菜單項。
4.6對話框的使用
showmessage過程:調(diào)用showmessage過程會彈出一個簡單的對話框,對話框上顯示提示信息及“確定”按鈕,單擊該按鈕,就關(guān)閉對話框。
inputbox函數(shù):調(diào)用inputbox函數(shù)顯示一個能夠接受喲娜防護輸入數(shù)據(jù)的對話框,并返回用戶輸入的數(shù)據(jù)值。
inputquery函數(shù):與inputbox函數(shù)最大的不同是他的返回值是一個邏輯值。
第五章 5.1程序調(diào)試
錯誤的種類及處理方式:
1、語法錯誤:沒有遵守語言的語法規(guī)則而產(chǎn)生。
2、運行錯誤:程序在執(zhí)行過程中發(fā)生了錯誤。程序試圖打開一個不存在的文件或試圖修改一個只讀文件,程序運行過程中出現(xiàn)除零錯誤或用戶輸入了非法數(shù)據(jù)等。
3、邏輯錯誤:運行的結(jié)果與設(shè)想的結(jié)果不同。
解決邏輯錯誤可以從三步驟來解決:猜測出程序可能出錯的地方,并在此設(shè)置斷點。讓程序執(zhí)行到斷點停止運行,觀察所有中間變量及對象內(nèi)容。讓程序單步運行,同時觀察每一個變量及對象內(nèi)容的變化。
事件變量和相關(guān)數(shù)據(jù)的值:提示文本,watch list窗口,evaluate 窗口。5.2異常保護和處理
1、異常保護與try?finally?end;語句 try ? //被保護的代碼塊 finally ? //處理語句 end;
2、響應(yīng)異常和try?except?end;語句 try //以下為保護代碼塊 ?
if <異常條件> raise<異常對象> except //以下為異常處理快
on <異常類1> do <處理過程1或語句1> on <異常類2> do <處理過程2或語句2> on ?
else <其他處理過程或語句> end;
通過繼承類exception可以自定義新的異常類。
第6章 delphi7與數(shù)據(jù)庫
6.1數(shù)據(jù)庫簡介 數(shù)據(jù)庫可以長期存儲、有組織、可共享的數(shù)據(jù)集合。
數(shù)據(jù)庫系統(tǒng)(database system,dbs)是指具有數(shù)據(jù)管理功能的計算機系統(tǒng)。它一般由數(shù)據(jù)庫、數(shù)據(jù)庫管理系統(tǒng)和應(yīng)用系統(tǒng)構(gòu)成。
數(shù)據(jù)庫系統(tǒng)根據(jù)的組織方式主要分為層次數(shù)據(jù)庫系統(tǒng)、網(wǎng)狀數(shù)據(jù)庫系統(tǒng)、關(guān)系型數(shù)據(jù)庫系統(tǒng)很面向?qū)ο髷?shù)據(jù)庫系統(tǒng)等幾類
delphi支持關(guān)系型數(shù)據(jù)庫,關(guān)系型數(shù)據(jù)庫由表組成。標的定義了事物的一組屬性數(shù)據(jù),稱為記錄。表的列定義了事物的某種屬性,稱為字段。6.2 delphi7的數(shù)據(jù)庫訪問機制
borland推出了一個數(shù)據(jù)庫引擎(borland database engine,bde)bde管理器(bde administrator)是設(shè)置和管理bde的工具,它可以用來管理bde中的數(shù)據(jù)庫別名和驅(qū)動器。datebase desktop的使用:
1、定義數(shù)據(jù)庫別名
2、設(shè)置工作目錄及私有目錄
3、建立數(shù)據(jù)表結(jié)構(gòu)
4、保存數(shù)據(jù)表文件
5、建立索引(1)建立主索引(2)建立次索引
6、設(shè)置有效性檢查
7、設(shè)置口令
8、設(shè)置參照完整性
9、輸入部分數(shù)據(jù)
數(shù)據(jù)庫游覽器可用于定義數(shù)據(jù)庫別名、查詢或編輯數(shù)據(jù)庫中的各類信息,如數(shù)據(jù)庫的參數(shù)設(shè)置、各類據(jù)表文件的結(jié)構(gòu)及數(shù)據(jù),也可以使用sql語句進行查詢 6.3數(shù)據(jù)庫組件
使用ttable組件連接并顯示數(shù)據(jù)表的一般步驟
1、把一個ttable組件放到窗體上
2、tablename屬性指定要訪問的表
3、tdatasource組件放到窗體上,設(shè)置dataset屬性指向該ttable組件
4、把數(shù)據(jù)控制組放到窗體上,設(shè)置tdatasource屬性指向該tdatasource組件
5、把ttable組件的active屬性設(shè)為true [0].asstring:=editl = tablel fields [0].asstring := yname(‘name’).asstring 當表結(jié)構(gòu)改變引起字段索引號改變時,就要修改相應(yīng)的程序,所以使用第二種方法比較好。
dataset屬性:表明于當 前數(shù)據(jù)源組件相聯(lián)系的數(shù)據(jù)集組件對象的名字
enabled屬性:如果enabled屬性值為true(默認值),數(shù)據(jù)控制組件將顯示數(shù)據(jù):如果enabled屬性值為false,則所有與此數(shù)據(jù)源組件相連的數(shù)據(jù)控制組件都將不顯示任何數(shù)據(jù)。
columna屬性用于指定tdbgrid對象中各欄目的特征 6.4 tfield對象的使用
動態(tài)字段對象與永久字段對象的概念,區(qū)別,使用場合:delphi會為數(shù)據(jù)中的每一個字段自動生成一個動態(tài)的字段對象。數(shù)據(jù)集的結(jié)構(gòu)和其他信息改變,當應(yīng)用程序重新打開這個數(shù)據(jù)集時,就會基于最近的結(jié)構(gòu)和信息重建所有的字段對象。當數(shù)據(jù)集關(guān)閉時,這些對象也跟著取消。
動態(tài)對象的最大特點是適應(yīng)性強,缺點是要想改變字段的顯示屬性、數(shù)據(jù)格式就要編寫代碼,不能把某些字段暫時隱去,也不能增加新的字段。
永久字段最大的好處是可以在設(shè)計時設(shè)置它的屬性。可以選擇部分字段,增加新的字段。再永久字段對象列表中刪除某些需要保護的字段,避免用戶訪問這些字段;在數(shù)據(jù)庫查詢或特定數(shù)據(jù)表的字段基礎(chǔ)上定義新的字段,代替現(xiàn)存的字段;改變原有的字段的顯示和編輯屬性。6.5 數(shù)據(jù)集的操作 數(shù)據(jù)集的打開與關(guān)閉:
1、設(shè)置active屬性 :=true;//打開數(shù)據(jù)集,數(shù)據(jù)集組件對數(shù)據(jù)表進行讀寫操作。:=false;//關(guān)閉數(shù)據(jù)集,數(shù)據(jù)集組件不能對數(shù)據(jù)表進行讀寫操作。
2、調(diào)用open和close方法 //打開數(shù)據(jù)集和 //關(guān)閉數(shù)據(jù)集。移動記錄指針:
1、bof屬性:如果bof為true,表明當前記錄指針所處的位置為數(shù)據(jù)集的第一條記錄;反之,則不是第一條記錄。
2、eof屬性:如果eof為true,表明當前記錄指針所處的位置為數(shù)據(jù)集的最后一天記錄;反之,則不為最后一條記錄。
3、first方法:將記錄指針移至數(shù)據(jù)集的第一條記錄處,并使之成為當前記錄,同時將bof屬性值設(shè)置為true。
4、last方法:將記錄指針移至數(shù)據(jù)集最后一條記錄處,并使之成為當前記錄,同時將bof屬性設(shè)置為true。
5、next方法:將記錄指針后移一條記錄,并使之成為當前記錄。如果記錄指針指向了數(shù)據(jù)集的最后一條記錄,將eof屬性設(shè)置為true。
6、prior方法:將記錄指針前移一條記錄,并使之成為當前記錄。如果記錄指針指向了數(shù)據(jù)集的第一條記錄,將bof屬性設(shè)置為true。
7、moveby方法:將記錄指針從當前記錄開始向后或向前移動若干條記錄。格式如下:function moveby(distance:integer):integer;
限制記錄集:
1、setrangestart方法和setrangeend方法可以過濾記錄。setrangestart方法用來限制記錄集的開始,setrangeend方法用來限制記錄集的結(jié)束,調(diào)用applyrange方法使限制生效,調(diào)用cancelrange方法取消為數(shù)據(jù)表設(shè)定的限制范圍。
2、使用數(shù)據(jù)集的filter屬性
filter屬性值是一個用來指明數(shù)據(jù)表過濾標準的字符串,filter屬性決定了過濾器是否起作用。
查找記錄:
1、使用findkey方法。使用table的findkey方法或findnearest方法。
2、搜索特定記錄(locate)。findkey或findnearest方法只能在ttable組件中使用,如果使用的是tquery或tstoreproc組件,就要使用locate方法來查找記錄。locate函數(shù)適合于所有數(shù)據(jù)集組件,也適合于ttable組件。appendrecord方法與insertrecord方法:這里兩個方法分別與append方法與insert方法相似,都是用于在表中插入一條新紀錄,但appendrecord方法與insertrecord方法比append方法與inser t方法更簡單、更方便一些,不需要調(diào)用post方法。過程形式如下:procedure appendrecord(const values:array of const);
procedure insertrecord(const values:array of const);
建立數(shù)據(jù)表的主從關(guān)系:設(shè)置表之間的主從關(guān)系是通過設(shè)置從表的mastersource屬性和masterfield屬性來實現(xiàn)的,且從表必須按masterfield屬性中指定的字段建立了索引。
6.6tquery組件
tquery組件和ttable組件的比較:同屬于數(shù)據(jù)集組件。
不同之處為:tquery組件主要功能是用來支持sql語言訪問本地或遠程數(shù)據(jù)庫;tquery組件允許用戶同時訪問多個表,而ttable組件一次只能訪問一個表格;tquery組件訪問的是表格中的特定數(shù)據(jù)內(nèi)容,而ttable組件只有在提供過濾或限定檢索范圍時才能訪問表格中的特定數(shù)據(jù)內(nèi)容,否則訪問的將是表格中的全部數(shù)據(jù)。掌握p193 bde綜合實例。
6.8 ado技術(shù)
通過ado不僅能夠訪問基于sql server的所有數(shù)據(jù)庫,而且可以通過odbc訪問所有支持odbc的數(shù)據(jù)庫。
odbc是一種采用開放式結(jié)構(gòu)進行數(shù)據(jù)庫鏈接的接口標準,是一種開放的獨立于廠商的api應(yīng)用程序接口。掌握p208 ado應(yīng)用實例
第七章 windows編程基礎(chǔ)
7.1動態(tài)鏈接庫(dll)
windows允許同時運行的多個程序共享一組函數(shù)的單一備份,于是引入了動態(tài)鏈接方式,將可共享的程序代碼以及各種數(shù)據(jù)資源編譯成單獨的模塊。
一般項目的格式如下: program 程序標識符; uses 單元列表; begin 程序體; 項目文件的格式如下: library 程序標識符號; uses 單元列表;
exports 過程和函數(shù)標識符列表; begin 程序體; end.兩者的區(qū)別的原因在于:delphi編譯器是一句項目文件頭的保留字是program還是library來決定編譯生成的是exe文件還是dll文件。若dll 要輸出共其他應(yīng)用程序調(diào)用的函數(shù)或過程,則需要在其項目文件的保留字exports之后一一列出,這些dll函數(shù)或過程將被編譯成遠程地址調(diào)用。
window系統(tǒng)自身包含三個dll,分別是kernel,user,gd1。dll調(diào)用必須使用標準方式,其一是靜態(tài)引用,其二是動態(tài)引用。靜態(tài)引入:
加載引用的dll文件是,庫文件的查找順序是:
1、當前路徑;
2、windows系統(tǒng)的安裝目錄;
3、windows的系統(tǒng)目錄system和system32;
4、列在環(huán)境變量path中的路徑。
引入方法:
1、最簡單的是名字引入;
2、使用索引引入;
3、若名字引入會引起標識符沖突,可以使用換名引入。
delphi游戲開發(fā)篇二
delphi 字符串類型淺析 收藏
參考資料《delphi 5開發(fā)人員指南》“第2章object pascal語言” 《pascal精要》“第7章 字符串操作” “delphi中string類型和char類型的比較” “object pascal中string類型的內(nèi)幕探討”
基本知識字符串類型
?ansistring這是pascal缺省的字符串類型,它由ansichar字符組成,其長度沒有限制,同時與null結(jié)束的字符串相兼容。
?shortstring保留該類型是為了向后兼容delphi1.0,它的長度限制在255個字符內(nèi)。
?widestring功能上類似于ansistring,但它是由widechar字符(unicode字符集)組成的。引入這種類型,主要是為了支持ole編程。
?pchar指向null結(jié)束的char字符串的指針,類似于c的char*或lpstr類型。
?pansichar指向null結(jié)束的ansichar字符串的指針。
?pwidechar指向null結(jié)束的widechar字符串的指針。
字符類型
?ansichar,以 8 位表示(共有 256 個不同的符號)。
?widechar,以 16 位表示(共有 64,000 個不同的符號)。
string類型
注意:以下是指delphi2007以前的編譯器(包括delphi2007)。
1、缺省情況下,如果用如下的代碼來定義字符串,編譯器認為是ansistring字符串: var
s:string;//編譯器認為s的類型是ansistring
2、編譯開關(guān)$h
“$h編譯開關(guān)”的值用來決定當變量聲明為string時,它是被當作ansistring類型還是被當作shortstring類型。當“$h”值為負時,string變量是shortstring類型;當“$h”值為正時(缺省情況),string變量是ansistring類型。下面的代碼演示了這種情況: var
{$h-}
s1:string;//s1是shortstring類型 {$h+}
s2:string;//s2是ansistring類型
使用$h規(guī)則的一個例外是,如果在定義時特地指定了長度(最大在255個字符內(nèi)),那么總是shortstring。var
s:string[63];//63個字符的shortstring字符串
char類型
1、delphi2007以前的編譯器(包括delphi2007)缺省情況下認為char是ansichar類型,pchar是pansichar類型。
2、delphi2009的編譯器缺省情況下認為char是widechar類型,pchar是pwidechar類型。請注意,沒有任何方法可變更這個新的編譯器預(yù)設(shè)設(shè)定。對于字符串類型而言,會以固定的硬式編碼方式將 char 類型對應(yīng)到特定的數(shù)據(jù)類型。
ansistring類型
1、ansistring是生存期自管理類型。
2、ansistring字符串總是以null字符結(jié)束的,這使得ansistring字符串能與win32api中的字符串兼容。
3、ansistring類型是一個指向在堆棧中的字符串結(jié)構(gòu)的指針。可以使用sizeof去讀取ansistring類型的大小,不論字符串的實際長度是多少,sizeof(astring)永遠是4。
4、ansistring字符串在內(nèi)存中分配的情況 注意:
在delphi2.0以后版本中,不能再通過字符串的第0個元素來設(shè)置或得到字符串的長度,只能通過length()函數(shù)來得到字符串的長度,通過setlength()過程來設(shè)置字符串的長度。borland并不保證string的內(nèi)存結(jié)構(gòu)在以后的delphi版本中會保持不變。
(1)、delphi5內(nèi)存結(jié)構(gòu)如下:
(2)、delphi7內(nèi)存結(jié)構(gòu)如下:
ansistring指向一塊內(nèi)存起始偏移8字節(jié)處,前面8字節(jié)依次為引用計數(shù)和長度計數(shù)兩個整數(shù)。(3)、delphi2009內(nèi)存結(jié)構(gòu)如下:-12-10-8-4
最后一位
字碼頁
字符大小
引用計數(shù)
字串長度
字串內(nèi)容
0
除了字串長度及引用計數(shù)外,新的ansistring格式包括字符大小及字碼頁。字符大小可用來區(qū)分 ansistring 及unicodestring,而字碼頁特別適用于 ansistring 類型(可用于 delphi 2009),unicodestring 類型的字碼頁則固定為 1200,字碼包括utf-
8、gbk等,例如“$03a8就是936,查msdn 936sizeof(strrec));
showmessage(format('分配大小:%d 引用計數(shù):%d 字串長度:%d', [iz,,]));end;
示例:delphi7字符串內(nèi)存結(jié)構(gòu)
代碼:
procedure 1click(sender: tobject);type
pstrrec = ^strrec;
strrec = packed record
refcnt: longint;
length: longint;
end;var
str: string;
p: pstrrec;
begin
str:='123';
p := pointer(integer(str)sizeof(strrec));
showmessage(format('字碼頁:%d 字符大小:%d 引用計數(shù):%d [ge,ze,,]));end;
示例:widestring的長度
代碼:
字串長度:%d', procedure 1click(sender: tobject);
//---
function _wstrlen1(const s: widestring): integer;
begin
if pointer(s)= nil then
result := 0
else
result := pinteger(integer(s)-4)^ span sizeof(widechar);
end;var
str: widestring;
begin
str := '測試123';
showmessage(format('字串長度:%d', [_wstrlen1(str)]));end;
本文來自csdn博客,轉(zhuǎn)載請標http:///starsky2006/archive/2010/07/31/
出處明:
delphi游戲開發(fā)篇三
實習(xí)報 告 書 專 用 紙
實習(xí)報 告 書
引言
題
目: delphi 學(xué)
院:
專
業(yè): 地理信息系統(tǒng) 班
級:
姓
名: 學(xué)
號:
2013年
6月日
實習(xí)報 告 書 專 用 紙
娛樂場所信息查詢軟件,軟件界面設(shè)計簡潔,美觀,其人性化的軟件流程,可以讓一般人方便的查詢娛樂場所,上手極易,不用打開多個窗口可重復(fù)查詢。系統(tǒng)需求分析
根據(jù)用戶的需求,對本系統(tǒng)做整體的需求分析,這是保證系統(tǒng)有效性和實用性的前提。
2.1 功能需求分析
在設(shè)計本系統(tǒng)之前,作者與相關(guān)工作人員進行了交流,并對此進行了歸納提煉,得出建立一個娛樂場所信息查詢應(yīng)具備如下功能:
(1)娛樂場所信息查詢。可以對任何一個娛樂場所的詳細信息進行查詢,其中包括名稱、所處路名、id等。
(2)娛樂場所所在地區(qū)的地圖顯示。(3)最短路徑的分析。(4)地圖打印。
2.2 數(shù)據(jù)需求
根據(jù)功能需求的要求,需要有一系列的數(shù)據(jù)來支撐,本系統(tǒng)需要的數(shù)據(jù)包括所處地區(qū)的地圖模板、道路信息、娛樂場所信息等 系統(tǒng)設(shè)計
為確保系統(tǒng)順利的實施,本系統(tǒng)遵循軟件工程原理和方法,對系統(tǒng)進行總體設(shè)計和詳細設(shè)計;其次,應(yīng)滿足先進性原則,依照國際標準,借鑒主流系統(tǒng)的體系結(jié)構(gòu),保證系統(tǒng)具有較長的生命力和擴展能力;此外,還應(yīng)滿足成熟性原則、實用性原則、高可靠性原則等。根據(jù)需求分析的結(jié)果,本著以上原則展開對本系統(tǒng)的設(shè)計。
3.1 界面設(shè)計
為了界面設(shè)計,增強系統(tǒng)的美觀性、靈活性,使系統(tǒng)易于操作,采用了很多優(yōu)秀的
實習(xí)報 告 書 專 用 紙
3.1.1 登錄界面
該系統(tǒng)需要輸入用戶名、密碼才可運用,具有較好的保護性
3.1.2 關(guān)于界面
3.2 技術(shù)路線
本系統(tǒng)采用embarcadero delphi xe3作為開發(fā)工具。delphi,是windows平臺下著名的快速應(yīng)用程序開發(fā)工具,最早的版本由美國borland(寶蘭)公司于1995年開發(fā)。
實習(xí)報 告 書 專 用 紙
delphi是一個集成開發(fā)環(huán)境(ide),使用的核心是由傳統(tǒng)pascal語言發(fā)展而來的object pascal,以圖形用戶界面為開發(fā)環(huán)境,通過集成開發(fā)環(huán)境、vcl工具與編譯器,配合連結(jié)數(shù)據(jù)庫的功能,構(gòu)成一個以面向?qū)ο蟪绦蛟O(shè)計為中心的應(yīng)用程序開發(fā)工具。
“真正的程序員用c,聰明的程序員用delphi”,這句話是對delphi最經(jīng)典、最實在的描述。delphi最大的特點是簡單易學(xué)、執(zhí)行高效而且功能強大。和microsoft visual studio c++ 相比,delphi更易于掌握,學(xué)習(xí)周期也比較短,而在功能上卻絲毫不遜色;而與visual basic相比,delphi功能更強大、更實用,尤其在開發(fā)數(shù)據(jù)庫方面,它的特點更是體現(xiàn)得淋漓盡致。這正是作者選用delphi作為開發(fā)工具的原因。
delphi發(fā)展至今,從delphi 1到現(xiàn)在的delphi xe2,不斷添加和改進各種特性,功能越來越強大。delphi 2010內(nèi)置了direct 2d模塊及開發(fā)庫,其新加的功能包括:○1○1支持64位windows操作系統(tǒng)的開發(fā);○2○2稱為firemonkey的新的跨平臺框架;○3○3在windows上開發(fā),用來編譯max os x的交叉編譯器;④firemonkey支持ios(apple ipad及iphone)的開發(fā);⑤livebindings的新的數(shù)據(jù)綁定功能,允許你將任何可視對象綁定到任何使用表達式的源對象。系統(tǒng)實現(xiàn)
4.1 概述
在完成了需求分析、系統(tǒng)設(shè)計和技術(shù)路線的選定后,按照前期工作的思路,逐步的實現(xiàn)商品管理系統(tǒng)。本系統(tǒng)以delphi xe3為開發(fā)環(huán)境,實現(xiàn)了連云港娛樂場所信息查詢功能。
4.2 功能模塊實現(xiàn)
4.2.1 登錄模塊
實習(xí)報 告 書 專 用 紙
操作部分核心代碼如下所示:
procedure 1click(sender: tobject);begin
;clientdataset1
.commandtext
:='select
*
from
table01
where name='''++''' and “passwords” ='''++'''';;if count=0 then begin showmessage('口令錯誤');end else begin modalresult:=mrok;end;end;4.2.2 圖層管理
實習(xí)報 告 書 專 用 紙
操作部分核心代碼如下所示:
procedure eate(sender: tobject);var denglu: tform2;begin pshplayer := ; := 'd:';(pshplayer);pshplayer := ; := 'd:';(pshplayer);pshplayer := ; := 'd:'; := '名稱'; := clred;(pshplayer);tent;pshplayer1 := [0] as tgis_layervector;pshplayer2 := [1] as tgis_layervector;pshplayer3 := [2] as tgis_layervector;denglu := (self);dal;
實習(xí)報 告 書 專 用 紙
;end;4.2.3 圖層的放大縮小(1)點擊縮放
操作部分核心代碼如下所示
procedure 2click(sender: tobject);begin := giszoomex;end;
(2)點擊暫停縮放
操作部分核心代碼如下所示:
procedure 3click(sender: tobject);begin := gisselect;end;4.2.4點擊地圖平移
實習(xí)報 告 書 專 用 紙
操作部分核心代碼如下所示:
procedure 5click(sender: tobject);begin := gisdrag;end;4.2.5點擊屬性查詢
實習(xí)報 告 書 專 用 紙
操作部分核心代碼如下所示:
procedure 4click(sender: tobject);begin := gisselect;end;4.2.6路名顯示 點擊路名顯示
操作部分核心代碼如下所示:
procedure 8click(sender: tobject);begin e := false; := '名稱'; := '路名';tent;end;4.2.7最短路徑分析 點擊最短路徑查詢
實習(xí)報 告 書 專 用 紙
操作部分核心代碼如下所示:
procedure 6click(sender: tobject);var ii, jj: integer;i: integer;aa, bb: string;begin presultlayer := ; := ; := clred; := 40;omlegend := true;(presultlayer);
proadlayer := [1] as tgis_layervector;
pgeocoding := (proadlayer);me := 'gis_uid';(('tgis_geocoding')
as
實習(xí)報 告 書 專 用 紙
tgis_layervector).hidefromlegend := true;
pshortespath := (ttkviewer1);edata(proadlayer);me := 'gis_uid ';thedata;pshape := rst(, '路名=''' + + '''');aa := ld('gis_uid');ii := (aa);if ii > 0 then begin pstartpoint := [0]; := [0];nt(pstartpoint, 3 / , nil);end else begin showmessage( + ' 是無效地名');exit;end;
pshape := rst(, '路名=''' + + '''');bb := ld('gis_uid');jj := (bb);if jj > 0 then begin pstoppoint := [0]; := [0];nt(pstoppoint, 3 / , nil);end else
實習(xí)報 告 書 專 用 紙
begin showmessage( + ' 是無效地名');exit;end;
thedata;if (pstartpoint, pstoppoint)then begin all;for i := 0 to ount-1 do begin pshape [i].pe([i].uid);if pshape <> nil then pe(pshape);end;eextent := ; := * 0.8;;end else begin showmessage(' 此路不通 ');end;end;4.2.8打印 點擊打印
:=
實習(xí)報 告 書 專 用 紙
操作部分核心代碼如下所示:
procedure 9click(sender: tobject);begin w;end;4.2.9定點查詢 點擊定點查詢
操作部分核心代碼如下所示:
procedure 1click(sender: tobject);var pshape: tgis_shape;
實習(xí)報 告 書 專 用 紙
player: tgis_layervector;begin player := [2] as tgis_layervector;pshape := rst(, '名稱=''' + + '''');if pshape <> nil then begin := id;pshape := itable;cted := true;ape(pshape);e := true;;end;end;4.2.9關(guān)于模板
4.3 系統(tǒng)功能及效率分析
經(jīng)過測試,系統(tǒng)總體的執(zhí)行效率比較高。能夠滿足用戶的基本要求。總結(jié)
本論文主要是探討娛樂場所信息查詢服務(wù)的設(shè)計與實現(xiàn)問題。在系統(tǒng)設(shè)計之初,盡管作者做了調(diào)查,但依然缺少足夠的管理方面的經(jīng)驗,在結(jié)構(gòu)和功能方面尚有考慮不到的地方。
delphi游戲開發(fā)篇四
c++24點游戲
#include “iostream” #include “string” using namespace std;
//定義stack類
const maxsize=20;
enum error_code { success, overflow, underflow };
template
class stack { public: stack();
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
stack
::stack(){ count=0;}
template bool stack::empty()const { return count==0;}
template bool stack::full()const { return count==maxsize;}
templateint stack
::size()const { return count;}
templatevoid stack
::clear(){ count=0;}
template error_code stack::top(t &item)const { if(empty())return underflow;item= entry[count-1];return success;}
template error_code stack::pop(){ if(empty())return underflow;count--;return success;}
template error_code stack::push(const t &item){ if(full())return overflow;entry[count++]=item;return success;}
stacksign;stack
num;
int set;// 判斷程序中的異常,以便適時退出?//
void process(char c)
//計算兩個數(shù)的 +-* / 運算// { int k=0;double a,b;();
if((b)==success){
();
if((a)==success){ ();k=1;} } if(k){ switch(c){
case '+': (a+b);break;case '-': (a-b);break;case '*': (a*b);break;case '/': if(b==0){ set=4;(-1);} else
(a/b);break;} }
else {set=1;(-1);} }
void get_command(string &str){
cout<<“n請輸入要進行運算的表達式,包括” +,-,*,/,=,(,)“和數(shù)字,”<
<<“注意: 以數(shù)字開頭,等號結(jié)尾,中間括號要匹配.”<
>str;}
double do_command(const string &str){ string s=“";double outcome=-1;char c;
for(int i=0;str[i]!='';i++){
if(set!=0)break;//例外 則停止運行
while(1){ //分離數(shù)據(jù)與運算符
if(str[i]<='9' && str[i]>='0' || str[i]=='.'){ s+=str[i];i++;} else { if(s!=”“){
if((atof(s.c_str()))==overflow)set=3;s=”“;} break;} }
char ch= str[i];
switch(ch){ //處理運算的優(yōu)先級,并注意例外拋出
case '*': case '/':
if((c)==success)if(c=='*'||c=='/')process(c);if((ch)==overflow)set=3;break;case '+': case '-':
while((c)==success){ if(c!='(')process(c);else break;}
if((ch)==overflow)set=3;break;case '(':
if((ch)==overflow)set=3;break;case ')':
while((c)==success){ if(c!='(')process(c);else break;}
();break;case '=':
while((c)==success){ if(c!='(')process(c);else break;} break;
default: set=2;break;} }
if(()==1 && ()==0)(outcome);else set=1;
if(set==0)cout<<”運算結(jié)果是:n“<
if(set==1)cout<<”n您輸入的不匹配,有錯誤發(fā)生。result lost!“<
if(set==4)cout<<”n 分母為0,不能進行除法運算,出現(xiàn)溢出,lost result!“<
return outcome;}
void main()int f(){ double out;do { string str,s;set=0;
get_command(str);s=str;
if(str[0]=='-')str='0'+str;//處理表達式中的負號
for(int i=1;str[i]!='';i++){ if(str[i]=='-' && str[i-1]=='('){ (i,”0“);i++;} } out= do_command(str);
cout<
我gai過此行
cout<<”如果你算的結(jié)果不等于24,需要重新計算請輸入你算出的結(jié)果,程序有漏洞,請合作。“<
>out;cout<<”謝謝合作“<
return out;}
int main(void)
{
int ii,zz,jj;
printf(”0-12的4個數(shù)字nn“);
for(jj=0;jj<2;)
{
for(ii=0;ii<4;ii++)
{
zz=rand()()% 12;
cout<
}
cout<<”請用這4個數(shù)字算出24“<
f();
cout<<”是否繼續(xù);是1否2"<
cin>>jj;
cout<
}
delphi游戲開發(fā)篇五
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.1 “速算24”撲克游戲效果說明
“速算24”是一個考察心算能力、有助于開發(fā)智力的撲克游戲。在給出4張撲克牌之后,要求應(yīng)用這些撲克牌數(shù)字做數(shù)學(xué)運算,迅速構(gòu)造出一個數(shù)學(xué)表達式,得出結(jié)果24。這個游戲的關(guān)鍵在于迅速判斷用戶輸入的表達式是否正確,并做出相應(yīng)的反饋,告訴用戶是算對了還是算錯了。游戲的初始界面如圖3.1所示。
圖3.1 游戲的初始界面
當用戶單擊“開始”按鈕時,系統(tǒng)開始發(fā)牌,隨機發(fā)出4張牌,如圖3.2所示為隨機開始的一局游戲,給出的4張紙牌分別為“9”,“8”,“9”,“2”。在文本框中輸入運算表達式,比如,輸入“8*(2+(9-9))”,單擊“計算”按鈕,系統(tǒng)會出現(xiàn)提示框,顯示“您輸入的表達式的計算結(jié)果為16!”,告訴你該表達式的結(jié)果不是“24”,如圖3.3所示。單擊“確定”按鈕,再次在文本框中輸入表達式,比如“8*(2+(9/9))”,單擊“計算”按鈕,系統(tǒng)會出現(xiàn)提示框,顯示“您真行,我服了您!”,表明運算正確,如圖3.4所示。
圖3.2 系統(tǒng)隨機發(fā)4張紙牌
圖3.3 運算式不正確
圖3.4 運算式正確
這個游戲具體的規(guī)則如下:
(1)單擊“開始”按鈕,游戲開始,系統(tǒng)將隨機發(fā)牌。
(2)請迅速在文本框中輸入運算表達式,然后單擊“計算”按鈕。
(3)這時系統(tǒng)會提示您的運算是對了還是錯了,在彈出的對話框中單擊“ok”按鈕,再次輸入新的運算表達式,重復(fù)上一步,直到您的運算表達式結(jié)果正確,這時系統(tǒng)會恭喜您!
(4)如果結(jié)果錯了還想繼續(xù)或者中途想計算另一局撲克牌,就單擊“重新開始”按鈕,得到新一局撲克牌進行游戲。
下面,我們開始循序漸進地創(chuàng)建這個小游戲。在最開始,游戲的界面和效果都會非常簡單,在后面我們會逐漸地完善它。
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.2 生成和建立程序(1)在程序中用到了image組件,用于放置圖片。還用到了timer組件,用于計算用戶操作時間。下面我們來生成游戲的基本框架。
3.2.1 image組件
image組件在additional頁上,用來在窗口中顯示一幅圖片。它擁有如下幾個主要屬性: e屬性
可以在picture屬性中調(diào)入圖像文件。delphi支持多種圖像格式,如位圖(.bmp)、圖標(.ico)、圖元(.wfm)、動畫光標(.ani)、jpeg圖片(.jpg、.jpeg)等。
ze屬性
當autosize為true時,image組件將根據(jù)它所包含的圖像的大小來調(diào)整自身的大小;當autosize為false時,不論圖像有多大,組件將保持設(shè)計時的大小。如果組件比圖像小,那么只有一部分圖像是可見的。
h屬性
當stretch為true時,位圖圖像將根據(jù)組件的大小調(diào)整自身的大小,當組件大小改變時,上述三種文件也做相應(yīng)變化。stretch屬性對圖標沒有作用。
上述的autosize和stretch屬性決定了圖像在窗口中的顯示尺寸。
圖3.5演示的3個image分別為:autosize為true,autosize為false,stretch為true的情形。可以看到,image的原始尺寸比圖片寬,矮,在上面的屬性設(shè)置下,就會有不同的顯示效果。
圖3.5 autosize和stretch的設(shè)置 3.2.2 timer組件
在delphi中,組件分可視組件和非可視組件。可視組件是指那些在運行期間仍然能顯示的組件,例如label,button,image組件等。非可視組件是指那些在程序界面設(shè)計期間可見,而在程序運行時不可見的組件,例如在system頁上的timer組件。
timer組件能夠有規(guī)律地觸發(fā)ontimer事件,發(fā)送信息給應(yīng)用程序,它是編制應(yīng)用程序時最為重要的組件之一。
組件的屬性
enabled屬性表示timer是打開還是關(guān)閉。用interval屬性設(shè)置兩個ontimer事件間的間隔,單位是毫秒。將間隔設(shè)置為0相當于關(guān)閉計時器,interval是cardinal類型的,最大值可到4294967295,當然程序中一般不會把interval設(shè)成很大的值。組件的使用
timer是獨立的對象,在啟動與windows無關(guān)的邏輯和應(yīng)用事件時極其有用。可以模擬時鐘或計時器,可視地顯示經(jīng)過的時間;可以用作系統(tǒng)延時,delphi提示信息出現(xiàn)只需在該區(qū)域停頓幾秒,就是timer組件應(yīng)用的一個例子;可以檢查系統(tǒng)環(huán)境、事件,根據(jù)結(jié)果進行響應(yīng);也可以在窗口中閃爍一段正文或圖像,提示某種操作或處理正在進行等等。
盡管delphi的計時器每秒可以產(chǎn)生1000次激發(fā),在編程中還必須注意程序?qū)imer觸發(fā)的響應(yīng)。如果程序處理ontimer事件的時間超過interval的設(shè)定值,就可能錯過事件,因為當下一次觸發(fā)到來時,系統(tǒng)正忙于處理上一事件,則這次觸發(fā)就會被忽略。同時要注意其他的windows應(yīng)用程序是否會影響timer的觸發(fā)。如果后臺正運行著一個占用處理器的程序,就可能會導(dǎo)致timer的觸發(fā)不準確,從而使前臺程序運行出現(xiàn)錯誤。
這里要強調(diào)的是timer組件是一個非可視組件,可以把它放置到窗體或者其他容器組件上的任何位置。3.實現(xiàn)游戲計時功能
在本章的游戲中,我們加入一個timer組件,實現(xiàn)游戲的計時功能。
在窗體中加入一個label組件,將此組件的caption屬性設(shè)置為“使用時間”,然后從組件面板上選擇system頁中的timer組件。
在unit1中加入form1的一個私有成員spendtime,記錄用戶計算所用的時間。代碼如下所示:
private { private declarations } spendtime:integer;在form1的oncreate事件中加入如下代碼。將spendtime設(shè)置為0,并將timer1的enabled屬性設(shè)置為false,使timer1組件不能響應(yīng)ontimer事件;并將timer1的interval屬性設(shè)置為1000,表示當timer1有效時,每間隔1000ms(即1秒)發(fā)生一次ontimer事件:
procedure eate(sender: tobject);var i:integer;begin //初始化,設(shè)置數(shù)組randomdata的長度為4 //并將每個數(shù)組元素初始化為零
setlength(randomdata,4);for i := 0 to 3 do randomdata[i]:=0;spendtime:=0;d:=false;al:=1000;end;然后在標題為“開始”的“開始”按鈕的onclick事件中,加入如下所示的代碼,將timer1的enabled屬性設(shè)置為true,使timer1組件有效,即現(xiàn)在timer1能響應(yīng)ontimer事件,計時開始。并將spendtime重新設(shè)置為0:
d:=true;al:=1000;spendtime:=0;//將spendtime重新設(shè)為0 再在“計算”按鈕的onclick事件句柄中,增加下面的語句,使timer1無效:
d:=false;最后雙擊timer1組件,創(chuàng)建timer1的ontimer事件句柄,在其中加入如下所示的代碼,將spendtime加1,并設(shè)置label5的caption屬性:
procedure tform1timer(sender: tobject);begin spendtime:=spendtime+1;n:='使用時間:'+inttostr(spendtime)+'秒';end;這樣,每隔1秒鐘,程序就刷新一次使用時間。
3.2.3 設(shè)計初始界面
按住shift鍵,然后單擊組件面板中additional頁中的image組件,這時該組件邊緣出現(xiàn)藍色的邊框,并且凹陷下去,表示可以在窗體上連續(xù)加入幾個image組件。選擇好image組件后,在窗體的左上角單擊,加入1個image組件,然后依次向右單擊鼠標3次,再加入3個image組件。最后再單擊組件面板中最左邊的箭頭。
為了排列這4個image組件,先利用shift鍵將它們同時選上,然后右擊,選擇align命令,在隨后出現(xiàn)的alignment對話框中的horizontal選項組中選擇space equally,在vertical選項組中選擇tops,表示這4個組件頂端對齊,水平方向上間距相等。
按照同樣的方法加入4個label組件、3個button組件和1個edit組件。按照表3.1所示設(shè)置各個組件的屬性。
表3.1 各個組件的屬性
組件名 form1 label1 屬性名 caption caption autosize wordwrap caption
屬性值 速算24
1.單擊“開始”按鈕,游戲開始,系統(tǒng)將發(fā)出4張撲克牌
false false
2.要求用戶利用撲克牌顯示的數(shù)字,通過加減乘除運算,以最快的速度得出24(可以使用括號),jqka和“王”算做1。然后在文本框中寫好表達式,接
著單擊“計算”按鈕
label2
label3 autosize wordwrap caption
false true
3.這時系統(tǒng)會計算輸入表達式的結(jié)果,告訴用戶是對還是錯了。在彈出的對話框中單擊“ok”按鈕,如果錯了可以再次輸入新的表達式,重復(fù)上一步。直
到您的表達式正確,這時系統(tǒng)會恭喜算對了!
label4 autosize wordwrap caption autosize caption caption caption text
false true 在下面輸入數(shù)學(xué)表達式
false 開始 計算 退出游戲 空
button1 button2 button3 edit1
現(xiàn)在同時選擇label1,label2和label3,將它們左對齊,垂直方向等距離排列。將button1,button2和button3左對齊,垂直方向等距離排列。
下面放置4個image組件,用于放置4張紙牌的圖片。
先選擇image1,然后切換到對象查看器中的屬性編輯器,選擇屬性選項頁中的picture屬性,然后在picture屬性值欄中雙擊,或單擊此屬性值旁邊的帶有省略號的按鈕,打開picture editor對話框,如圖3.6所示。然后單擊load按鈕,彈出load picture對話框,文件。最后單擊ok按鈕,退出picture editor對話框。
圖3.6 指定圖片
使用同樣的方法,設(shè)定其他3個image組件的picture屬性。
保存我們的新項目,運行之后界面如圖3.7所示,與運行時的界面圖3.1稍有不同。這里是設(shè)計時界面,只有界面沒有事件響應(yīng)。是程序創(chuàng)建過程中的一個步驟的檢驗。但是,這個程序還沒有什么具體的功能,為了讓游戲運行起來,必須添加代碼,創(chuàng)建相應(yīng)的事件處理程序。
第3章 “速算24”撲克游戲--單元、異常、邏輯
????生成和建立程序????
???????
3.2.4 事件處理
需要添加?個事件:第一個用于響應(yīng)單擊?開始?按鈕,在此事件中完成發(fā)牌,即隨機顯示圖片;第二個用于響應(yīng)單擊?計算?按鈕,解析用戶在文本框中輸入的表達式,計算表達式的結(jié)果,并判斷表達式的結(jié)果是否等于??;第三個用于響應(yīng)單擊?退出游戲?按鈕,退出游戲(程
序)。?
1.數(shù)據(jù)初始化
創(chuàng)建窗體的????????事件處理程序,在這里進行必要的初始化。?第一步先在unit1中添加form1的私有成員數(shù)組:
private
{ private declarations }
randomdata:array of integer;然后,在對象查看器中選中form1,選中event選項卡,在oncreate一欄對應(yīng)的右邊的空白欄中雙擊,創(chuàng)建oncreate函數(shù)。添加如下代碼。
procedure eate(sender: tobject);
var
i:integer;
begin //初始化,設(shè)置數(shù)組randomdata的長度為4
//并將每個數(shù)組元素初始化為零
setlength(randomdata,4);
for i := 0 to 3 do
randomdata[i]:=0;
end;這里使用一個for循環(huán)語句,i是循環(huán)變量,格式是:for循環(huán)變量:=初值to末值do循環(huán)體。你也可以借助delphi的自動完成功能,在輸入for之后按下ctrl+j鍵,生成如下代碼:
procedure eate(sender: tobject);
begin
for := to do
begin end;
end;在上述代碼中,程序首先利用setlength函數(shù)設(shè)定可變數(shù)組randomdata的數(shù)組長度為4,然后,將數(shù)組的每一個單元都設(shè)置為0。這樣,就完成了數(shù)組的數(shù)據(jù)初始化工作。
2.“開始”按鈕的click事件處理
(?)功能?單擊?開始?按鈕時,系統(tǒng)就隨機地發(fā)出?張紙牌,顯示在?個?????組件中。?
(?)代碼?首先,我們需要一個循環(huán)變量?,一個字符串變量存放隨機選取的圖片的文件名。?創(chuàng)建“開始”按鈕的onclick事件處理程序,在begin前頭添加需要的變量,然后在此事件
中加入如下所示的代碼。
procedure 1click(sender: tobject);
var
i:integer;
filename:string;
begin
randomize;//初始化隨機數(shù)
for i := 0 to 3 do
begin randomdata[i]:=random(13)+1;//產(chǎn)生一個1到13的隨機數(shù)
filename:=inttostr(randomdata[i])+'.bmp';//根據(jù)隨機數(shù),得到文件名
//根據(jù)i的不同為不同的image組件載入圖像文件
case i of 0 : omfile(filename);1 : omfile(filename);2 : omfile(filename);3 : omfile(filename);
end;
:='';
us;
end;
end;在delphi內(nèi)部,隨機數(shù)的產(chǎn)生實際上也是在一套算法的控制之下,randomize函數(shù)用于初始化產(chǎn)生隨機數(shù)的種子,保證兩次產(chǎn)生的隨機數(shù)不同,而random(i:integer)則利用初始化過后的隨機數(shù)種子產(chǎn)生一個1~i之間的隨機數(shù)。這里i設(shè)定為13,以配合撲克牌的張數(shù)13。
???????????????????用來將一個整數(shù)轉(zhuǎn)換成一個字符串,和上一章中的??????????????????的功能恰好相反。?我們已經(jīng)預(yù)先準備了位圖文件,它們都是???形式,文件名則是利用數(shù)字????命名。??????中特殊的字符串運算符???將兩個字符串串聯(lián)起來,產(chǎn)生一個新的字符串,我們需要的位圖文件后綴是???,因此,在產(chǎn)生文件名的時候,在數(shù)字后面加上??????這個字符串。?????語句在上一章中已經(jīng)講過,單擊?開始?按鈕后,準備接受用戶的輸入,然后利用????????方法,把焦點設(shè)置到?????上。????????是??????提供的方法之一,用于設(shè)置輸入
焦點到某個指定的組件。?
3.“計算”按鈕的onclick事件
雙擊“計算”按鈕,創(chuàng)建此組件的onclick事件響應(yīng)句柄,然后在代碼編輯器中加入如下所
示的代碼,用于計算用戶輸入的表達式。
procedure 2click(sender: tobject);
var
result:integer;
answer:string;
begin
result:=totalcompute();
if(result=24)then ebox('您真行,我服了您!','對了',mb_ok)
else
begin answer:='您輸入的表達式的計算結(jié)果為'+inttostr(result)+'!';ebox(pchar(answer),'錯了',mb_ok);
end;
end;這段程序根據(jù)自定義函數(shù)的計算結(jié)果判斷用戶的輸入正確與否,并且輸出相應(yīng)的結(jié)果以提示
用戶。
在語句“result:=totalcompute()”中用到了一個自定義的函數(shù)totalcomp-ute,我們用它來計算用戶輸入的表達式。現(xiàn)在我們還沒編寫這個函數(shù)的代碼,所以,目前這段代碼是無法運行的。沒關(guān)系,可以先把它用“//”注釋掉,然后隨便給 result賦一個值,測試這個事件處理程序的其他部分是否運行正常,例如:
//result:=totalcompute();
result:=24;這樣,運行后,單擊“計算”按鈕后的顯示如圖3.8所示。
圖3.8 成功的提示信息
我們用一個??????類型的??????變量存放出錯信息,但是???????函數(shù)的第一個參數(shù)要求是?????(????????????????字符指針)類型,因此,我們用一個強制類型轉(zhuǎn)換將??????轉(zhuǎn)換
成?????。?4.“退出游戲”按鈕的onclick事件
雙擊“退出游戲”按鈕,創(chuàng)建此組件的onclick事件處理程序,然后在代碼編輯器中加入如
下所示的代碼,用于退出程序。
procedure 3click(sender: tobject);
begin
close;
end;在上一章中我們提到可以用?????????????????????代替?????,但這里使用?????來結(jié)束程序的運行。這樣,可以通過????????????事件來指定在什么條件下窗體可以關(guān)閉。
第3章 “速算24”撲克游戲--單元、異常、邏輯
????生成和建立程序???????????equery事件
當調(diào)用?????方法來關(guān)閉窗體時,????????????事件發(fā)生。利用????????????事件來指定在什么條件下窗體可以關(guān)閉。????????????事件包含一布爾型的????????參量,可以用它來決定窗體是否關(guān)閉。????????的默認值為????。?可以利用????????????事件來詢問用戶是否真的希望馬上關(guān)閉窗體。?我們在這里彈出一個對話框,代碼如下所示:
procedure osequery(sender: tobject;var canclose: boolean);begin if(messagedlg('現(xiàn)在要退出游戲嗎?', mtconfirmation, [mbok, mbcancel], 0)= mrok)then canclose:=true else canclose:=false;end;messagedlg是一種提示對話框,第一個參數(shù)是對話框詢問的訊息,是一個字符串;第二個參數(shù)則代表對話框的類型,mtconfirmation是一個tmsgdlgtype的枚舉類型,表示這個對話框是個確認對話框。tmsgdlgtype類型如下所示:
type tmsgdlgtype =(mtwarning, mterror, mtinformation, mtconfirmation, mtcustom);以上定義的對話框類型分別表示:警告、錯誤、提示、確認和自定義類型。
第三個參數(shù)是tmsgdlgbtn類型的集合,這個集合包含了類型為tmsgdlgbtn的按鈕,tmsgdlgbtn的定義如下:
type tmsgdlgbtn =(mbyes, mbno, mbok, mbcancel, mbabort, mbretry, mbignore, mball, mnnotoall, mbyestoall, mbhelp);在我們的程序中,利用了一個集合[mbok, mbcancle],表示在對話框中顯示兩個按鈕:ok和cancel的組合。
最后一個參數(shù)是用來描述幫助索引的長整型變量,用來獲取提示用戶的幫助信息,這里我們沒有任何幫助信息,先不管它。??????????函數(shù)和用戶交互,返回一個????類型的數(shù)字,??????預(yù)先定義了一套數(shù)字,用來直觀地表示對話框返回信息。如果用戶單擊了??按鈕,這個對話框返回????,效果如圖???所示。?
圖3.9 關(guān)閉窗口時詢問用戶
現(xiàn)在,我們已經(jīng)完成了程序的主體部分。??第3章 “速算24”撲克游戲--單元、異常、邏輯
????單元間的互相引用????????3.3.1 單元引用的概念
在第?章關(guān)于單元的知識里,我們已經(jīng)知道??????可以定義不包含窗體的單元,它集中定義了程序中使用的函數(shù),這一節(jié)里,我們就要實現(xiàn)這樣的一個單元,用來實現(xiàn)上面提到的????????????函數(shù)。?我們可以在任何單元中編寫自己的函數(shù),當然包括與窗體相連的單元。可是我們常常需要用到一些常用的函數(shù),這時最好是創(chuàng)建一個不與窗體相連的獨立單元,用它來容納自己的函數(shù),這稱為獨立的單元文件。當創(chuàng)建了不與窗體相連的獨立單元文件后,項目中的其他單元就能很容易地共享這些函數(shù),其他項目也可以很容易地調(diào)用這些函數(shù)了。?對于單元間的引用,要用到????語句。?3.3.2 uses語句
????語句告訴程序在最終的執(zhí)行代碼中需要用到哪些函數(shù)和過程。??????會自動把一些必須的單元包括進來,例如???????,????????,????????等。對于我們自己編寫的單元,如果程序中使用了該單元的函數(shù)或代碼,也需要包括在????部分中。?????語句具有兩種類型:公有引用和私有引用。?在?????????部分包含的????語句代表的是本單元的公有引用,就是說,這部分的引用可以被其他引用本單元的單元繼承性地引用。在?????????部分的????語句應(yīng)包含在?????????部分中的代碼所需要的單元,去掉那些??????可以自動加入到程序中的單元。?在?????????部分包含的????語句代表的是本單元的私有引用,就是說,這部分的引用只能被本單元內(nèi)部使用。在??????????????部分的????語句應(yīng)只包含在??????????????部分中的代碼所需的單元的名字。?對于單元間的引用,要避免交叉引用。假設(shè)有兩個單元?和?,如果?出現(xiàn)在?的?????????部分的????語句中,那么單元?便不能出現(xiàn)在單元?的?????????的????語句中。因為這樣會產(chǎn)生對單元的循環(huán)訪問,編譯時會出現(xiàn)錯誤信息。?3.3.3 創(chuàng)建另一個單元
創(chuàng)建一個不與窗體相連的單元文件的方法是,首先選擇主菜單的????命令,然后選擇???命令,此時??????彈出一個?????????對話框,如圖????所示。在此圖中選擇???選項卡中的????,然后單擊??按鈕。此時??????自動為我們創(chuàng)建一個名為?????的獨立單元文件,并顯示在代碼編輯器中,我們只需在此加入函數(shù)即可。?
圖3.10 new items對話框
單元創(chuàng)建之后,就需要實現(xiàn)單元之間的互相引用。這里有兩種方法:?(1)直接在unit1中寫入uses unit2,代碼如下所示:
var form1: tform1;implementation uses unit2;(2)選擇主菜單的file | use unit命令,此時delphi彈出use unit對話框,如圖3.11所示,在此窗口中列出當前文件沒有連接的所有文件,只需選擇需要連接的文件即可。當選擇了某一文件并單擊ok按鈕后,當前文件就包含了對所選文件的引用。
圖3.11 use unit對話框
如果當前文件已經(jīng)連接了當前項目中所有其他文件,選擇????????命令后,就會彈出如圖????所示的信息窗口,告訴程序員當前文件已經(jīng)連接了當前項目中所有其他文件。?
圖3.12 information對話框
此時再編譯,程序就沒有任何錯誤了。?現(xiàn)在我們已經(jīng)創(chuàng)建了?????,它將用作我們的數(shù)學(xué)函數(shù)定義單元。在開始定義這個單元之前,需要先了解一下關(guān)于??????的異常處理機制。?第3章 “速算24”撲克游戲--單元、異常、邏輯
3.4 異 常 處 理
3.4.1 異常處理的概念 在應(yīng)用程序開發(fā)中如何檢測、處理程序的運行錯誤是一個很重要的問題。在 delphi 的ide(集成開發(fā)環(huán)境)中提供了一個完善的內(nèi)置調(diào)試器,可以發(fā)現(xiàn)大部分程序錯誤。但并不是所有的錯誤都可以被發(fā)現(xiàn),而且當程序涉及到與外設(shè)的數(shù)據(jù)交換或操作外設(shè),如要求用戶輸入、讀寫磁盤等時,錯誤的發(fā)生是程序無法控制的,如輸入非法字符、磁盤不能讀寫等。這些情況不僅會導(dǎo)致應(yīng)用程序異常中止,而且可能引起系統(tǒng)的崩潰。針對這些問題,delphi提供了一套強大的異常處理機制。巧妙地利用它,可以使程序更為強健,使用更為友好。
delphi異常處理機制建立在protected blocks(保護塊)的概念上。所謂保護塊是指用保留字try和end封裝的一段代碼。保護塊的作用是當應(yīng)用程序發(fā)生錯誤時自動創(chuàng)建一個相應(yīng)的exception(“異常”類)。程序可以捕獲并處理這個“異常”類,以確保程序的正常結(jié)束以及資源的釋放和數(shù)據(jù)不受破壞。如果程序不進行處理,則系統(tǒng)會自動提供一個消息框。“異常”類是delphi異常處理機制的核心,也是delphi異常處理的主要特色。delphi提供的所有“異常”類都是類exception的子類。用戶也可以從類exception派生一個自定義的“異常”類。
3.4.2 資源保護方式
回收分配的資源是確保程序健壯性的一個關(guān)鍵。但默認情況下異常發(fā)生時程序會在出錯點自動退出當前模塊,因此需要一種特殊的機制來確保即使在異常發(fā)生的情況下,釋放資源的語句仍能被執(zhí)行,而delphi的異常處理正提供了這種機制。
delphi提供了一個保留字finally,用于實現(xiàn)資源的保護。
{分配資源}
try {資源使用情況} finally {釋放資源}
end;try?finally?end就形成了一個資源保護塊。finally后面的語句在任何情況下(不論程序是否發(fā)生異常)都會執(zhí)行。
在異常保護的情況下,當異常發(fā)生時,系統(tǒng)會自動彈出一個消息框,在框中顯示異常的消息。退出當前模塊后異常類自動清除。
3.4.3 異常響應(yīng)方式
異常響應(yīng)為開發(fā)者提供了一個按需進行異常處理的機制。try?except?end形成了一個異常響應(yīng)保護塊。與finally不同的是:正常情況下except 后面的語句并不被執(zhí)行,而當異常發(fā)生時程序自動跳到except處,進入異常響應(yīng)處理模塊。當異常被響應(yīng)后異常類自動清除。
下面是異常響應(yīng)方式的一般代碼:
try {程序正常功能} except on esomething do {響應(yīng)特定異常} else {提供默認響應(yīng)} end;保留字on?do用于判斷異常類型。必須注意的是:except后面的語句必須包含在某一個on?do模塊中,而不能單獨存在。這是又一個與finally不同的地方。
3.4.4 提供默認響應(yīng)
在異常響應(yīng)模塊中,一般我們只對希望響應(yīng)的特定異常進行處理。如果一個異常發(fā)生而響應(yīng)模塊并沒有包含對它的處理代碼,則退出當前響應(yīng)模塊,異常類仍被保留。
為了保證任何異常發(fā)生后都能在當前響應(yīng)模塊中被清除,可以定義默認響應(yīng):
try {程序正常功能} except on esomething do {響應(yīng)特定異常} else {提供默認響應(yīng)} end;由于else可以響應(yīng)任何異常,包括我們一無所知的異常,因此在默認響應(yīng)中最好只包括諸如顯示一個消息框之類的處理,而不要改變程序的運行狀態(tài)或數(shù)據(jù)。
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.5 數(shù)學(xué)邏輯單元(1)
此游戲程序最關(guān)鍵的地方是如何將用戶輸入的字符串表達式解析成數(shù)學(xué)表達式。為了使程序結(jié)構(gòu)清晰明了,我們將此解析代碼和程序的主代碼分開,單獨編寫成一個單元。
3.5.1 算法設(shè)計
游戲的難點是如何將一字符串形式的表達式解析成計算機能計算的算術(shù)表達式。例如對于字符串“3^(4*(9+4))”,如何讓計算機解析、計算。
我們的想法是按照數(shù)學(xué)四則運算規(guī)則,先逐層進入最里層的括號,然后在括號內(nèi)部計算乘方,接著進行乘(除)法運算,最后按順序進行加(減)運算,當本層括號內(nèi)部計算完成后,返回結(jié)果,去掉括號內(nèi)部數(shù)據(jù),退出到下一級括號(如果有)內(nèi)進行計算。
這里面涉及的技術(shù)細節(jié)主要有下面幾點:
(1)層層剝離括號,然后從最里層的括號開始計算。(2)對于每一個運算符號,找到符號兩側(cè)的數(shù)字,形成一個計算式。
(3)每一個子計算式完成后,運算結(jié)果返回到原始數(shù)列中,作為子串的一部分,繼續(xù)進行上述計算。
3.5.2 字符串的相關(guān)函數(shù)
在游戲中,用戶輸入的都是字符數(shù)據(jù),我們需要從這些字符中分析得到數(shù)字和運算符號,因此要用到與字符串操作有關(guān)的函數(shù)。
function pos(sub , all:string):integer;這個函數(shù)含有兩個參數(shù):sub表示要查找的字符,all表示原字符串。函數(shù)在字符串a(chǎn)ll中尋找指定的字符sub的位置,如果字符串中不存在sub字符,則函數(shù)結(jié)果為0。
function lastdelimiter(sub,all :string):integer 這個函數(shù)含有兩個參數(shù):sub表示要查找的字符,all表示原字符串。函數(shù)返回在字符串a(chǎn)ll中所有查找到的指定字符sub的最后一個的位置,如果字符串中不存在sub字符,則函數(shù)結(jié)果為0。
function copy(allstring:string;first,length:integer):string 這個函數(shù)的3個參數(shù)的含義分別是:allstring代表原來的字符串,first表示拷貝開始的位置,length表示要拷貝的子串長度。函數(shù)返回拷貝成功的子串。
procedure delete(str:string;ppos,length:integer)這個過程用于刪除字符串中的一段字符。參數(shù)str代表將要操作的字符串,ppos代表開始刪除的位置,length表示將要刪除多少個字符。function length(s): integer;length函數(shù)返回字符串s的長度。
function trim(const s: string): string;overload;function trim(const s: widestring): widestring;overload;trim函數(shù)返回字符串s去掉前面和后面的空格后的字符串。
下面的例子給出一個綜合利用字符串處理函數(shù)編寫的一個處理特定字符串的函數(shù),它的功能是:輸入一個字符串后,可以返回字符串中兩個單括號之間的子字符串,并去掉前面和后面帶著的空格:
function getmystr(const s: string): string;begin result:=trim(copy(s,pos('<',s)+1,pos('>',s)-pos('<',s)-1));end;比如我們在程序中寫到getmystr(‘this is a test < result to output > end of test’);,會得到字符串“result to output”。
3.5.3 算法的代碼編寫
基于上述的考慮和知識基礎(chǔ),我們在聲明部分定義下列幾個主要函數(shù):
(1)anylastpos函數(shù)定位最后一個算術(shù)運算符的位置。
function anylastpos(str:string):integer;(2)anyfirstpos函數(shù)定位最先一個算術(shù)運算符的位置。
function anyfirstpos(str:string):integer;(3)anyfirstf函數(shù)判斷最先出現(xiàn)的符號是+號、-號、*號還是/號。
function anyfirstf(str:string):char;(4)subcompute函數(shù)用于計算不帶()號的加、減、乘、除運算。
function subcompute(str:string):integer;(5)totalcompute函數(shù)用于計算表達式的結(jié)果。
function totalcompute(str:string):integer;1.尋找最后一個算術(shù)運算符
定義4個整數(shù)變量subpos,plupos,mulpos,spanpos,在給定的字符串中尋找+,-,*,/的最后位置,將這些位置存儲在上述的4個變量中,然后比較4個符號出現(xiàn)的位置,得到數(shù)值最大的運算符;在返回的結(jié)果中,返回這個運算符的位置。
程序代碼如下所示:
function anylastpos(str:string):integer;var subpos:integer;plupos:integer;mulpos:integer;spanpos:integer;pos:integer;begin //定位字符串中最后一個運算符的位置
subpos:=lastdelimiter('-',str);plupos:=lastdelimiter('+',str);mulpos:=lastdelimiter('*',str);spanpos:=lastdelimiter('/',str);pos:=subpos;if(pos
分別在給定的字符串中尋找+,-,*,/第一次出現(xiàn)的位置,然后比較4個符號出現(xiàn)的位置,得到數(shù)值最小的運算符。在返回的結(jié)果中,傳遞的是這個運算符的位置。
程序代碼如下所示:
function anyfirstpos(str:string):integer;var subpos:integer;plupos:integer;mulpos:integer;spanpos:integer;forpos:integer;firstpos:integer;begin //定位字符串中最先一個運算符的位置
subpos:=pos('-',str);plupos:=pos('+',str);mulpos:=pos('*',str);spanpos:=pos('/',str);forpos:=pos('^',str);firstpos:=200;if(subpos=0)then //如果沒有-號
subpos:=200;//將subpos設(shè)置成一個不可能的值
if(plupos=0)then //如果沒有+號
plupos:=200;//將plupos設(shè)置成一個不可能的值
if(mulpos=0)then //如果沒有*號
mulpos:=200;//將mulpos設(shè)置成一個不可能的值
if(spanpos=0)then //如果沒有/號
spanpos:=200;//將spanpos設(shè)置成一個不可能的值
if(forpos=0)then //如果沒有^號
forpos:=200;//將forpos設(shè)置成一個不可能的值
if(firstpos>subpos)then firstpos:=subpos;if(firstpos>plupos)then firstpos:=plupos;if(firstpos>mulpos)then firstpos:=mulpos;if(firstpos>spanpos)then firstpos:=spanpos;if(firstpos>forpos)then firstpos:=forpos;
anyfirstpos:=firstpos;//結(jié)束函數(shù),返回位置
end;第3章 “速算24”撲克游戲--單元、異常、邏輯
3.5 數(shù)學(xué)邏輯單元(2)
3.得到最先出現(xiàn)的運算符類型
這個函數(shù)的返回結(jié)果是char類型,代表這是一個字符變量。實際上,它返回的是+、-、*、/ 這4個符號中最早出現(xiàn)的一個。
程序分別尋找4個符號最早出現(xiàn)的位置,然后判斷最先出現(xiàn)的是哪一種符號,再根據(jù)符號類型返回代表運算符的字符。
在具體的實現(xiàn)過程中,因為我們要得到最先出現(xiàn)的運算符,所以判斷的是每次尋找后各個運算符的位置的最小值。如果不存在這個運算符,則將代表這個運算符位置的相應(yīng)變量設(shè)置為200。對于本程序來說,這是一個搜索過程中不可能達到的值,這樣就排除了這個位置的繼續(xù)比較的可能。
程序代碼如下所示:
function anyfirstf(str:string):char;var subpos:integer;plupos:integer;mulpos:integer;spanpos:integer;operator:char;temppos:integer;begin subpos:=pos('-',str);plupos:=pos('+',str);mulpos:=pos('*',str);spanpos:=pos('/',str);
if(subpos=0)then //如果沒有-號
subpos:=200;//將subpos設(shè)置成一個不可能的值
if(plupos=0)then //如果沒有+號
plupos:=200;//將plupos設(shè)置成一個不可能的值
if(mulpos=0)then //如果沒有*號
mulpos:=200;//將mulpos設(shè)置成一個不可能的值
if(spanpos=0)then //如果沒有/號
spanpos:=200;//將spanpos設(shè)置成一個不可能的值
operator:='-';temppos:=subpos;if(temppos>plupos)then begin temppos:=plupos;operator:='+';end;if(temppos>mulpos)then begin temppos:=mulpos;operator:='*';end;if(temppos>spanpos)then begin temppos:=spanpos;operator:='/';end;
anyfirstf:=operator;//結(jié)束函數(shù),返回位置 end;4.計算不帶括號的運算表達式
做完上述工作后,我們可以開始進行一些實際的運算了。
包括加、減、乘、除、乘方運算的表達式的程序算法如下所示:
(1)尋找乘方符號“^”,如果存在,則計算一次乘方,去掉計算過的部分,接著循環(huán)查找和計算子串的乘方。
(2)尋找乘號“*”或者除號“/”,如果存在,則計算一次乘(除)法,去掉計算過的部分,接著循環(huán)計算子串的乘除法。
(3)尋找加號“+”或者減號“-”,如果存在,則計算一次加(減)法,去掉計算過的部分,接著循環(huán)計算子串的加減法。
上述算法是嚴格按照順序進行的,它體現(xiàn)了數(shù)學(xué)運算中的優(yōu)先關(guān)系,經(jīng)過上述的計算,子字符串被分解,計算完畢。
無論是乘方、乘除法還是加減法,內(nèi)部實現(xiàn)的邏輯是基本一致的。下面,我們設(shè)定有一個運算表達式: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;spanpos:integer;fuhao:char;begin middle:='';mul2:='';right:='';
//定位第一個^號位置,計算乘方
first:=pos('^',str);while(first<>0)do //循環(huán)計算乘方
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;
//定位第一個*號或/號的位置
mulpos:=pos('*',str);spanpos:=pos('/',str);first:=mulpos;if(mulpos>spanpos)then first:=spanpos;if((spanpos=0)and(mulpos<>0))then begin first:=mulpos;spanpos:=2000;// 將除號所在位置設(shè)置成一個大于mulpos但又不可能的值
end;if((spanpos<>0)and(mulpos=0))then begin first:=spanpos;mulpos:=2000;// 將乘號所在位置設(shè)置成一個大于spanpos但不可能的值
end;while(first<>0)do //循環(huán)計算乘、除
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>spanpos)then middle:=inttostr(strtoint(mul1)span strtoint(mul2))else middle:=inttostr(strtoint(mul1)*strtoint(mul2));str:=left+middle+right;
mulpos:=pos('*',str);spanpos:=pos('/',str);first:=mulpos;if(mulpos>spanpos)then first:=spanpos;
if((spanpos=0)and(mulpos<>0))then begin first:=mulpos;spanpos:=2000;// 將除號所在位置設(shè)置成一個大于mulpos但又不可能的值
end;if((spanpos<>0)and(mulpos=0))then begin first:=spanpos;mulpos:=2000;// 將乘號所在位置設(shè)置成一個大于spanpos但不可能的值
end;end;//定位+、-號首先出現(xiàn)的位置
first:=anyfirstpos(str);if(first=200)then //如果沒有+、-號,則可以直接返回結(jié)果
begin subcompute:=strtoint(str);exit;end;fuhao:=anyfirstf(str);//確定首先出現(xiàn)的符號是+號還是-號
while(first<>0)do 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(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)定位字符串中第一個乘方符號“^”的位置first。這個式子中的first為4。
(2)如果存在乘方符號,即first不等于0,則繼續(xù)進行計算,否則退出循環(huán)。
(3)進入循環(huán)體內(nèi)部,得到“^”前面的子串tempstr(“3+2”),尋找tempstr中的最后一個運算符temp(這里是“+”),則temp和first之間的字符就是乘方符號的第一個參數(shù)(“2”)。
(4)同樣的邏輯,得到“^”后面的子串tempstr(“5/4”),尋找tempstr中的第一個運算符位置temp(“/”),則temp和first之間的字符就是乘方符號的第二個參數(shù)(“5”)。
(5)去掉乘方符號和兩個參數(shù),得到左側(cè)子串left(“3+”)和右側(cè)子串right(“/4”)。
(6)利用這兩個參數(shù)和乘方符號,計算乘方,將結(jié)果返回,并插入在left和right之間,得到一次計算后的新字符串(“3+32/4”)。
(7)判斷新串內(nèi)部是否包含“^”,如果包含,則返回到步驟(3),不包含則進入下一種運算。
第3章 “速算24”撲克游戲--單元、異常、邏輯
3.5 數(shù)學(xué)邏輯單元(3)5.計算整個表達式的值
totalcompute函數(shù)利用循環(huán),找到最內(nèi)層的一對括號,然后調(diào)用subcompute函數(shù)處理這一對括號中的表達式。subcompute函數(shù)處理的表達式中已經(jīng)沒有括號了,因此subcompute只需處理乘方、加、減、乘、除,返回結(jié)果,形成新的字符串。
當整個字符串縮減至空值時,整個表達式計算完成。
程序代碼如下所示:
function totalcompute(str:string):integer;var first:integer;last:integer;substr:string;leftstr:string;middle:string;right:string;temp:integer;begin first:=lastdelimiter('(',str);//定位最后一個(號位置 while(first<>0)do begin substr:=copy(str,first+1,length(str)-first);last:= pos(')',str);//last:=last+first;//定位最后一個(號以后的最開始的)號位置
leftstr:=copy(str,1,first-1);//(號左邊的字符串
middle:=copy(str,first+1,last-first-1);//()號中間的字符串
right:=copy(str,last+1,length(str)-last);//)號右邊的字符串
temp:=subcompute(middle);//進入下面的計算
middle:=inttostr(temp);
str:=leftstr+middle+right;first:=lastdelimiter('(',str);end;
result:=subcompute(str);end;end.在程序中,“計算”按鈕的onclick事件處理程序中調(diào)用totalcompute函數(shù)。函數(shù)中使用了一些數(shù)學(xué)函數(shù)和定位字符串的函數(shù),這些函數(shù)delphi已經(jīng)在相應(yīng)的系統(tǒng)單元中進行了定義,我們需要把這些系統(tǒng)單元包括到文件里面:
uses sysutils,math;將前面調(diào)用totalcompute的注釋去掉,把代碼改回:
procedure 2click(sender: tobject);var result:integer;answer:string;begin result:=totalcompute();if(result=24)then ebox('您真行,我服了您!','對了',mb_ok)else begin