面向對象思想在VB游戲開發中的運用
接觸過計算機高級語言的人都聽說過面向對象編程(即OOP),但究竟什么是面向對象編程呢?這個問題就不是剛剛接觸計算機的初學者所能完全理解的了.為了幫助大家理解面向對象的編程,我們這里用VB作為開發工具,以一個相對較小的例子來看一看VB中怎樣使用面向對象的編程方法。
什么是面向對象的編程方法呢?
總的說來面向對象的編程方法的核心就是:封裝性、繼承性和多態性。下面我們作一個簡單的介紹:
封裝性也就是說要將對象的信息(也就是對象的屬性)和對象所能執行的動作(也就是對象的方法)包裝起來,這樣就可以讓使用者可以用深入不了解內部的運作原理,就可以對其進行操作。舉個簡單的例子,在VB中我們要使用的一個控件,我們不必了解其中給一個屬性是怎樣傳給對象的,也不要知道當我們調用一個對象控件的方法時,對象在其中為我們作了些什么,我們所要作的僅僅是要符合它的使用規范對其進行簡單的使用即可。
繼承性則是說,一個對象可以在一個或多個已有對象的基礎上,通過繼承這些對象具有的屬性,方法和事件,并添加自己的屬性方法和事件,使其功能更加強大。而其中對已有對象的屬性,方法和事件的擁有,就是繼承性的精髓所在。比如在V B中有一個TEXTBOX控件可以處理簡單的文本信息,同時還有一個RICH TEXTBOX控件,很明顯后一個控件是在前一個的基礎上建立起來的,但在功能上后一個除了具備前一個控件的功能外,還具有遠遠強于前者的更加豐富的功能。
多態性,簡單的說,就是在許多種不同的對象中,可以使用相同的方法,但是同樣的方法能為各個對象執行不同的任務.也就是說程序能在運行時根據不同的對象,運行是用于當前對象的方法.例如,幾乎所有的控件都包含一個move方法.當一個控件調用這個方法時,程序能夠準確的知道是那一個控件在使用這個方法,從而執行此控件特定的任務.
可以看到面向對象的編程方法關鍵就是為了提高代碼的可重用性,從而減少代碼的長度,減輕程序員的負擔。
那么在VB中怎樣進行面向對象的編程呢?其實說出來也很簡單。在V B的工具箱中的每一個控件從實質上說都是一個類,其中包含了這個類的所有的屬性,事件和方法。當你將一個控件放置在V B工程的窗體上時,開發工具自動為你創建這個控件類的一個實例,通過這個實例你可以方便的使用它的另一種屬性,事件和方法。另一種,就是不使用可見的控件而是從“工程”中“引用”一個類的,并在代碼中顯示的定義這個類的一個實例,就可以想用控件一樣對其屬性,事件和方法進行靈活的控制了。
我們這篇文章將用類的方法完成一個掃雷游戲的編寫,更主要的是在其中我們可以看到怎樣建立一個自己的類,以及在工程中使用這個類。
一、我們現來看一看怎樣建立一個類
在VB中建立一個類要使用Class Module(類模塊).一個類模塊相當于一個簡單的程序對象.當一個類模塊建立起來后,我們就可以在程序的其他窗體中,定義一個類的實例,然后就像使用一個對象一樣訪問它的屬性,調用它的方法.下面是一個簡單的例子.
對于掃雷游戲來說,每一個地雷都有一個位置,這些地雷按位置緊密排列在窗體上,所以我們可以先建立一個包含地雷x , y軸位置的類.具體過程如下:
1、創建一個類模塊。首先在v b的[工程]菜單上選擇[添加類模塊]。這樣就在工作區中顯示了一個新的類模塊,其默認的名字為Class1,如下圖所示:


2、設定類的屬性和事件。當建立一個新的類之后,就需要設定類的三個屬性值。
屬性:
Name屬性:也就是類的名字,可以在程序中區別于其他的類。
Public屬性:用來確定該類在當前的項目之外能否被其他程序使用。只有兩個值:True和False。當該屬性值為True時,其他應用程序可以對該類進行某種類型的訪問。其訪問類型由下面的Instancing決定。當該屬性值被設置為False時,表示該類只能在定義類的程序中使用。
Instancing屬性:用來確定其他的應用程序何時能夠訪問該類。該屬性只有在Public屬性設置為true時才起作用。(不是太重要,我們省略)
事件:類模塊主要有兩個事件:Initialize和Terminate。在創建類的時候,我們可以在這些事件中添加代碼,這樣就可以在類的實例被創建或被析構時使程序采取一些動作。類似于C/C++中的構造函數和析構函數。
在這里我們主要修改了新類的Name屬性:設置為clsCoords,這樣我們就可以用這個名字來作為類的名字,定義它的實例,并訪問它的屬性和事件了.如下圖所示:
3、向類中添加屬性
在設定了類的屬性和事件之后,我們就需要為類添加用戶自己定義的屬性了.要向類中添加屬性有兩種方法:一種是在類中定義public變量.在這里Public關鍵字表明在類中創建的變量是在任何模塊中都可以使用的公共變量,也正因為這一點,所以程序的任何部分無須進行任何數據檢查就能修改變量的值,這樣如果傳給對象的是一個壞數據,那么就可能產生問題(不過也因為使用簡單,所以我們這里就使用這種方法);另一種是使用Property過程.這種方法類似于使用一個過程,通過調用過程時,將參數傳遞的數據,經過驗證後,賦給類中的私有屬性,(或者將私有屬性傳遞給參數).通過使用這種方法,程序為訪問和修改對象屬性提供了接口,這樣程序員就可以編寫代碼來驗證向類傳遞的數據是否正確,使類的函數不會因傳遞了壞數據而崩潰.下面是對可以使用的三種屬性過程及其作用的總結:
下面是具體個實現方法:
要創建類的屬性過程,我們先要進到類的代碼窗口,然后從[工具] ( Tool )菜單中選擇[添加過程] ( Add Procedure ).在顯示的”添加過程”對話框中,輸入過程的名字,以及”類型”中的[屬性]選項,單擊[確定],這樣就在類模塊中創建了Property Let和Property Get過程.如下圖所示:
4、向類中添加方法
任何程序都要實現一定的動作才能體現它的用處,因此,我們也要給類創建一些方法.它實質上也就是通過在類中編寫公共過程實現的.這些過程與為程序的其他部分編寫的過程類似.所有在類模塊中的過程都以聲明語句開始.如果這一語句使用Public關鍵字,那么該過程就是類的方法,并且該過程可以被在任何模塊中創建的該類的實例所調用;如果該過程用Private關鍵字開始,那么該過程只能在定義該類的模塊中調用.(方法同上)
5、向類中添加事件
為了在類中創建事件,需要完成下面兩個步驟:
(1)在類中聲明事件。若要聲明事件,只要提供事件名和在事件中要傳遞的參數,方法和定義屬性類似,只是關鍵字使用Event ,并且開始的關鍵字必須為Public,這樣才能使在不同模塊中定義的類的實例能觸發該方法。
(2)使用Raise Event語句觸發事件。聲明了事件之后,就可以使用Raise Event語句在類的代碼的任何地方觸發該事件。
我們這里不使用對象的事件,所以省略。
二、怎樣在程序中使用定義的類呢?
1、創建類的對象
要使用一個已經定義的類,首先要創建一個該類的對象。有兩種方法可以從用戶開發的類中創建對象:使用聲明語句或使用Set語句。一旦用這兩種方法創建了該類的對象后,就可以在程序中使用該對象,并能通過給對象訪問對象的屬性和方法。
當一個類的對象被創建后,類模塊中的Initialize事件首先運行,為了的屬性方法的訪問做準備,相當于C++語言中的構造函數。
(1)使用聲明語句: 當定義了一個類之后,我們就可以像使用一般的類型一樣使用這個類.形式上唯一不同之處就是,在dim . . . as ..之后,還要加一個New關鍵字,形式變為 Dim . . . As New . . . 使用這種方式時,聲明語句直接創建對象的實例,我們可以通過這個對象的實例在程序中訪問對象的屬性和方法.
(2)使用Set語句:這是創建對象的第二種方法.使用這種方法時,首先要聲明對象變量,然后用Set語句創建對象的實例.如我們在游戲中使用了以下代碼定義了一個clsCoords類型的實例objCoords 。
同樣,在我們用Set語句創建了對象變量之后,我們可以通過這個對象的實例在程序中訪問對象的屬性和方法.與前一種方法的不同之處在于,雖然我們先創建了一個對象的類型,但是我們還是不能使用這個對象,直到使用Set語句時才實際創建了對象的實例,這是我們才可以通過這個對象的實例在程序中訪問對象的屬性和方法.
2、設置和讀取屬性值:
對象的實例創建了,必然要對它的屬性進行訪問.對于這一步其實很簡單,
例如我們在coords.cls類模塊中定義的兩個變量
當我們要訪問它的值時,我們只要使用像下面的方式即可.
這里我們給clsCoords類的新的實例objCoords的兩個屬性mintX和mintY賦予了新值.
3、使用對象的方法
要使用用戶自己創建的對象的方法,與在v b中使用內在對象和控件的方法一樣.只要提供要執行對象的名稱和方法名,以及方法中要傳遞的數據即可.下面是我們在代碼中的使用對象的方法的一個例子.
此段代碼調用clsWinMine類的BeginHitTest過程來確定點擊的方格的位置
三、下面我們一起來分析一下在掃雷游戲中建立的類
在這個例子中,我們可以看到主要有兩個類,一個是用來描述地雷位置的coords類,其中定義了兩個屬性,mintX , mintY .代碼如下:
另一個類是用來控制掃雷游戲的winmine類,其中定義了主要的屬性,方法,代碼如下:
有了這些類的定義,那么在游戲的流程中我們只要用類就可以對游戲進行操作了,可以想象到剩下的工作就比較簡單了,這也就是VC中MFC使用廣泛的緣故。
下載源代碼
什么是面向對象的編程方法呢?
總的說來面向對象的編程方法的核心就是:封裝性、繼承性和多態性。下面我們作一個簡單的介紹:
封裝性也就是說要將對象的信息(也就是對象的屬性)和對象所能執行的動作(也就是對象的方法)包裝起來,這樣就可以讓使用者可以用深入不了解內部的運作原理,就可以對其進行操作。舉個簡單的例子,在VB中我們要使用的一個控件,我們不必了解其中給一個屬性是怎樣傳給對象的,也不要知道當我們調用一個對象控件的方法時,對象在其中為我們作了些什么,我們所要作的僅僅是要符合它的使用規范對其進行簡單的使用即可。
繼承性則是說,一個對象可以在一個或多個已有對象的基礎上,通過繼承這些對象具有的屬性,方法和事件,并添加自己的屬性方法和事件,使其功能更加強大。而其中對已有對象的屬性,方法和事件的擁有,就是繼承性的精髓所在。比如在V B中有一個TEXTBOX控件可以處理簡單的文本信息,同時還有一個RICH TEXTBOX控件,很明顯后一個控件是在前一個的基礎上建立起來的,但在功能上后一個除了具備前一個控件的功能外,還具有遠遠強于前者的更加豐富的功能。
多態性,簡單的說,就是在許多種不同的對象中,可以使用相同的方法,但是同樣的方法能為各個對象執行不同的任務.也就是說程序能在運行時根據不同的對象,運行是用于當前對象的方法.例如,幾乎所有的控件都包含一個move方法.當一個控件調用這個方法時,程序能夠準確的知道是那一個控件在使用這個方法,從而執行此控件特定的任務.
可以看到面向對象的編程方法關鍵就是為了提高代碼的可重用性,從而減少代碼的長度,減輕程序員的負擔。
那么在VB中怎樣進行面向對象的編程呢?其實說出來也很簡單。在V B的工具箱中的每一個控件從實質上說都是一個類,其中包含了這個類的所有的屬性,事件和方法。當你將一個控件放置在V B工程的窗體上時,開發工具自動為你創建這個控件類的一個實例,通過這個實例你可以方便的使用它的另一種屬性,事件和方法。另一種,就是不使用可見的控件而是從“工程”中“引用”一個類的,并在代碼中顯示的定義這個類的一個實例,就可以想用控件一樣對其屬性,事件和方法進行靈活的控制了。
我們這篇文章將用類的方法完成一個掃雷游戲的編寫,更主要的是在其中我們可以看到怎樣建立一個自己的類,以及在工程中使用這個類。
一、我們現來看一看怎樣建立一個類
在VB中建立一個類要使用Class Module(類模塊).一個類模塊相當于一個簡單的程序對象.當一個類模塊建立起來后,我們就可以在程序的其他窗體中,定義一個類的實例,然后就像使用一個對象一樣訪問它的屬性,調用它的方法.下面是一個簡單的例子.
對于掃雷游戲來說,每一個地雷都有一個位置,這些地雷按位置緊密排列在窗體上,所以我們可以先建立一個包含地雷x , y軸位置的類.具體過程如下:
1、創建一個類模塊。首先在v b的[工程]菜單上選擇[添加類模塊]。這樣就在工作區中顯示了一個新的類模塊,其默認的名字為Class1,如下圖所示:


2、設定類的屬性和事件。當建立一個新的類之后,就需要設定類的三個屬性值。
屬性:
Name屬性:也就是類的名字,可以在程序中區別于其他的類。
Public屬性:用來確定該類在當前的項目之外能否被其他程序使用。只有兩個值:True和False。當該屬性值為True時,其他應用程序可以對該類進行某種類型的訪問。其訪問類型由下面的Instancing決定。當該屬性值被設置為False時,表示該類只能在定義類的程序中使用。
Instancing屬性:用來確定其他的應用程序何時能夠訪問該類。該屬性只有在Public屬性設置為true時才起作用。(不是太重要,我們省略)
事件:類模塊主要有兩個事件:Initialize和Terminate。在創建類的時候,我們可以在這些事件中添加代碼,這樣就可以在類的實例被創建或被析構時使程序采取一些動作。類似于C/C++中的構造函數和析構函數。
在這里我們主要修改了新類的Name屬性:設置為clsCoords,這樣我們就可以用這個名字來作為類的名字,定義它的實例,并訪問它的屬性和事件了.如下圖所示:
![]() |
3、向類中添加屬性
在設定了類的屬性和事件之后,我們就需要為類添加用戶自己定義的屬性了.要向類中添加屬性有兩種方法:一種是在類中定義public變量.在這里Public關鍵字表明在類中創建的變量是在任何模塊中都可以使用的公共變量,也正因為這一點,所以程序的任何部分無須進行任何數據檢查就能修改變量的值,這樣如果傳給對象的是一個壞數據,那么就可能產生問題(不過也因為使用簡單,所以我們這里就使用這種方法);另一種是使用Property過程.這種方法類似于使用一個過程,通過調用過程時,將參數傳遞的數據,經過驗證後,賦給類中的私有屬性,(或者將私有屬性傳遞給參數).通過使用這種方法,程序為訪問和修改對象屬性提供了接口,這樣程序員就可以編寫代碼來驗證向類傳遞的數據是否正確,使類的函數不會因傳遞了壞數據而崩潰.下面是對可以使用的三種屬性過程及其作用的總結:
| 屬性類別 | 作 用 |
| Property Let | 從調用的程序接收屬性值,用來設置屬性值 |
| Property Get | 向調用的程序傳送屬性值,用來獲取屬性值 |
| Property Set | 特殊情況的Let過程,用來設置對象變量的值 |
下面是具體個實現方法:
要創建類的屬性過程,我們先要進到類的代碼窗口,然后從[工具] ( Tool )菜單中選擇[添加過程] ( Add Procedure ).在顯示的”添加過程”對話框中,輸入過程的名字,以及”類型”中的[屬性]選項,單擊[確定],這樣就在類模塊中創建了Property Let和Property Get過程.如下圖所示:
![]() ![]() ![]() |
4、向類中添加方法
任何程序都要實現一定的動作才能體現它的用處,因此,我們也要給類創建一些方法.它實質上也就是通過在類中編寫公共過程實現的.這些過程與為程序的其他部分編寫的過程類似.所有在類模塊中的過程都以聲明語句開始.如果這一語句使用Public關鍵字,那么該過程就是類的方法,并且該過程可以被在任何模塊中創建的該類的實例所調用;如果該過程用Private關鍵字開始,那么該過程只能在定義該類的模塊中調用.(方法同上)
5、向類中添加事件
為了在類中創建事件,需要完成下面兩個步驟:
(1)在類中聲明事件。若要聲明事件,只要提供事件名和在事件中要傳遞的參數,方法和定義屬性類似,只是關鍵字使用Event ,并且開始的關鍵字必須為Public,這樣才能使在不同模塊中定義的類的實例能觸發該方法。
(2)使用Raise Event語句觸發事件。聲明了事件之后,就可以使用Raise Event語句在類的代碼的任何地方觸發該事件。
我們這里不使用對象的事件,所以省略。
二、怎樣在程序中使用定義的類呢?
1、創建類的對象
要使用一個已經定義的類,首先要創建一個該類的對象。有兩種方法可以從用戶開發的類中創建對象:使用聲明語句或使用Set語句。一旦用這兩種方法創建了該類的對象后,就可以在程序中使用該對象,并能通過給對象訪問對象的屬性和方法。
當一個類的對象被創建后,類模塊中的Initialize事件首先運行,為了的屬性方法的訪問做準備,相當于C++語言中的構造函數。
(1)使用聲明語句: 當定義了一個類之后,我們就可以像使用一般的類型一樣使用這個類.形式上唯一不同之處就是,在dim . . . as ..之后,還要加一個New關鍵字,形式變為 Dim . . . As New . . . 使用這種方式時,聲明語句直接創建對象的實例,我們可以通過這個對象的實例在程序中訪問對象的屬性和方法.
(2)使用Set語句:這是創建對象的第二種方法.使用這種方法時,首先要聲明對象變量,然后用Set語句創建對象的實例.如我們在游戲中使用了以下代碼定義了一個clsCoords類型的實例objCoords 。
| Dim objCoords As New clsCoords |
同樣,在我們用Set語句創建了對象變量之后,我們可以通過這個對象的實例在程序中訪問對象的屬性和方法.與前一種方法的不同之處在于,雖然我們先創建了一個對象的類型,但是我們還是不能使用這個對象,直到使用Set語句時才實際創建了對象的實例,這是我們才可以通過這個對象的實例在程序中訪問對象的屬性和方法.
2、設置和讀取屬性值:
對象的實例創建了,必然要對它的屬性進行訪問.對于這一步其實很簡單,
例如我們在coords.cls類模塊中定義的兩個變量
| '定義了一個對象用來保存被錯誤標記的地雷的x , y軸坐標 Public mintX As Integer Public mintY As Integer |
當我們要訪問它的值時,我們只要使用像下面的方式即可.
| Dim objCoords As New clsCoords '在新建的clsCoords類的實例中存儲被標記錯誤的地雷的X , Y坐標位置 objCoords.mintX = intX objCoords.mintY = intY |
這里我們給clsCoords類的新的實例objCoords的兩個屬性mintX和mintY賦予了新值.
3、使用對象的方法
要使用用戶自己創建的對象的方法,與在v b中使用內在對象和控件的方法一樣.只要提供要執行對象的名稱和方法名,以及方法中要傳遞的數據即可.下面是我們在代碼中的使用對象的方法的一個例子.
| Private objMine As New clsWinMine Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single) '當鼠標左鍵被按下時,出發此事件,調用clsWinMine類的BeginHitTest過程來確定點擊的方格的位置 objMine.TrackHitTest Button, x, y End Sub |
此段代碼調用clsWinMine類的BeginHitTest過程來確定點擊的方格的位置
三、下面我們一起來分析一下在掃雷游戲中建立的類
在這個例子中,我們可以看到主要有兩個類,一個是用來描述地雷位置的coords類,其中定義了兩個屬性,mintX , mintY .代碼如下:
| '在coords.cls類模塊中定義的兩個變量 '定義了一個對象用來保存地雷的x , y軸坐標 Public mintX As Integer Public mintY As Integer |
另一個類是用來控制掃雷游戲的winmine類,其中定義了主要的屬性,方法,代碼如下:
| '定義鼠標左鍵,同VB中的定義常數vbKeyLButton ,值都為1 Private Const LEFT_BUTTON As Byte = 1 '標記一個方格是否為空的標志 Private Const NONE As Byte = 0 '標記一個方格是否為一個帶雷的方格 Private Const MINE As Byte = 243 '標記一個方格是否被點開 Private Const BEEN As Byte = 244 '標記一個方格是否已經被標記為一個帶雷的方格 Private Const FLAGGED As Byte = 2 '標記一個方格是否被標記為一個問號,即一個存有疑問,不能確定的方格 Private Const QUESTION As Byte = 1 '定義掃雷游戲中最大和最小的地雷地圖的行數和列數及其地雷個數 Private Const MIN_MINES As Byte = 10 '最小的地雷數 Private Const MIN_ROWS As Integer = 8 Private Const MIN_COLS As Integer = 8 '最小的地圖行數列數 Private Const MAX_MINES As Byte = 99 '最大的地雷數 Private Const MAX_ROWS As Integer = 24 Private Const MAX_COLS As Integer = 36 '最大的地圖行數列數 '設定每個方格的寬度為16個象素 Private Const mintButtonWidth As Byte = 16 '設定每個方格的寬度為16個像素 Private Const mintButtonHeight As Byte = 16 '記錄玩家設定的當前游戲的水平中所包含的地雷的個數 Private mbytNumMines As Byte '記錄在當前游戲中,被玩家正確標志出來的地雷的個數 Private mbytCorrectHits As Byte '記錄在當前游戲中,被玩家標志出來的地雷的個數,包括被錯誤標記的 Private mbytTotalHits As Byte '記錄在當前游戲中,游戲被設定的行數和列數 Private mintRows As Integer Private mintCols As Integer ' 記錄在游戲中由玩家點擊鼠標的位置,而確定的點擊的方塊的行數和列數 Private mintRow As Integer Private mintCol As Integer '是否開始一盤新游戲的標志 Public mblnNewGame As Boolean '在正在進行的游戲中,鼠標點擊事件的標志 Private mblnHitTestBegun As Boolean '定義游戲顯示的主窗體 Private mfrmDisplay As Form '定義一個動態的二維數組,用來保存包含地雷的方格的位置,以及那一個位置的周圍有沒有地雷,有多少地雷,以及那些方格被打開 Private mbytMineStatus() As Byte '其中定義一個動態的二維數組,用來保存被標記過的方格的位置,不管這個標記是否標記正確 Private mbytMarked() As Byte '定義一個動態的二維數組,用來保存在分布的地雷區域所有分布的地雷總數的x,y中的坐標位置 Private mbytMineLocations() As Byte '定義一個集合,用來存放clsCoords類對象的x,y軸坐標位置,他們指示著游戲中被標記錯誤的方格的位置 Private mcolWrongLocations As New Collection |
有了這些類的定義,那么在游戲的流程中我們只要用類就可以對游戲進行操作了,可以想象到剩下的工作就比較簡單了,這也就是VC中MFC使用廣泛的緣故。
下載源代碼



