基於VB中WINSOCK控件的網上象棋系統的實現

         本文發表在《微型機與應用》雜誌2001年第3期。





     基於VBWINSOCK控件的網上象棋系統的實現

     馬根峯1   ,  孫豔2  王平1

(1.重慶郵電學院自動化學院,重慶,4000652. 鐵道部第十九工程局四處,內蒙 通遼,028000 )

 

    摘要     本文首先介紹了Visual Basic中的WINSOCK控件的使用方法,然後深入探討了網上象棋系統的設計思想及其實現過程。

    關鍵詞    WINSOCK控件;TCPUDP

    中圖分類號:    文獻標識碼

 

 

1      引言

    MicrosoftVisual Basic 是可視化的、面向對象的、採用事件驅動方式的結構化的高級程序設計語言。它提供了開發Microsoft Windows(R)應用程序的迅速、最簡捷的方法。在網上象棋系統的工作中,筆者利用VB編寫了網上象棋系統,實現了網上下棋的基本功能。

 

 

2 VBWINSOCK控件簡介 

利用 WinSock 控件可以與遠程計算機建立連接,並通過用戶數據文報協議 (UDP)或者傳輸控制協議 (TCP)進行數據交換。這兩種協議都可以用來創建客戶與服務器應用

    程序。

Winsock它提供了訪問 TCP  UDP 網絡服務的方便途徑。Visual BasicVisual C++的開發人員都可使用它。爲編寫客戶或服務器應用程序,不必瞭解 TCP 的細節或調用低級的Winsock APIs。通過設置控件的屬性並調用其方法就可輕易連接到一臺遠程機器上去,並且還可雙向交換數據。

2.1  TCP 基礎

數據傳輸協議允許創建和維護與遠程計算機的連接。連接兩臺計算機就可彼此進行數據傳輸。

如果創建客戶應用程序,就必須知道服務器計算機名或者 IP 地址(RemoteHost 屬性),還要知道服務器進行偵聽的端口(RemotePort 屬性),然後調用 Connect 方法。

如果創建服務器應用程序,就應設置一個收聽端口(LocalPort 屬性)並調用 Listen 方法。當客戶計算機需要連接時就會發生 ConnectionRequest 事件。爲了完成連接,可調用 ConnectionRequest 事件內的 Accept 方法。

建立連接後,任何一方計算機都可以收發數據。爲了發送數據,可調用 SendData 方法。當接收數據時會發生 DataArrival 事件。調用 DataArrival 事件內的 GetData 方法就可獲取數據。

2.2   UDP 基礎

用戶數據報協議 (UDP) 是一個無連接協議。跟 TCP 的操作不同,計算機並不建立連接。另外 UDP 應用程序可以是客戶機,也可以是服務器。 

爲了傳輸數據,首先要設置計算機ARemoteHost爲計算機B的名稱或IP地址,然後將計算機ARemotePort屬性設置爲計算機BLocalPort 屬性,最後調用Bind方法然後,指定用於 UDP 連接的 LocalPort  LocalIP

經過上面的在個步驟之後,計算機AB就可以調用 SendData 方法來着手發送信息,還可以在 DataArrival 事件內的利用 GetData 方法來獲取已發送的信息了。

 

 

3  網上象棋中的幾個關鍵問題  

   3.1   如何將象棋中的棋子和棋盤的信息用計算機來描述出來 

l  象棋中棋盤

           象棋中棋盤共有九列,十行,共有´ 10 個點。我將顯示器的最左下角看成是座標原點,屏幕上方爲Y軸的正方向,單位是1;屏幕的右方向看成是X軸的正方向,單位是1。然後用90個座標(IJ)從(11)到(910)來表示這90個點的位置。

l  確定每個座標點的物理地址。

    首先給出座標原點的物理座標(X0Y0),然後利用公式

      X = X0+ (i1 - 1) * intColToCol

Y = Y0-(j1 - 1) * intRowToRow

         其中intColToColintRowToRow分別表示棋盤列間距、行間距。

l  棋子

兩方棋子共´ 16個,我自定義了記錄類型qiZis ,它用域 index caption blnDeleted xy分別表示棋子的序號、棋子的名稱、是否被吃掉、在棋盤中的邏輯座標的X值、Y值。外觀上用命令按鈕數組(其序號index132)來代表棋子。
 

3.2  如何將象棋的規則如何轉換成計算機算法

    象棋中走子的規則如下:

“馬走日、象走田、車走直路炮翻山 ”等等

      上面的這些規則如何用計算機來描述出來,如何在計算機中來控制棋子的行走和吃子,這成了網上象棋的關鍵。我在實現這個系統的時候是採用下面的方案。

l  對於走子

首先取得用戶點擊鼠標的位置(通過窗體的MouseDown事件),然後找出90個座標點中物理座標最爲相近的一個座標點,記下它的邏輯座標,然後通過函數blnCanMove(ByValIndexMoved As Integer, ByVal oldX As Integer, ByVal oldY As Integer, ByVal newXAs Integer, ByVal newY As Integer)  As Boolean 來判斷序號爲IndexMoved的棋子是否能從邏輯座標(oldXoldY)移動到(newXnewY)。

在這個函數中則集中了每種棋子的走子規則。它主要是通過對兩個座標值進行處理來判斷棋子IndexMoved是否能這樣走子。

以行車爲例,該函數在執行時要經過以下的判斷:

每一,目標位置和起始位置是否在一條直線上,即目標位置的邏輯X

Y座標值與起始位置的XY座標值是否有一個相等;

第二,目標位置與起始位置之間是否無其它的棋子。只有滿足這兩個條件,才能行車。

再舉一個複雜的例子,能不能走馬要經過以下的判斷:

第一,目標位置與起始位置是否構成日字,目標位置與起始位置邊線的斜率是否爲21/2(首先還必須是否會發生除0中斷),以及橫縱座標之差中是否一個爲1另人個爲2

          第二,判斷在有可能發生別馬腿的位置上是否有別的棋子。

l  對於吃子

每一,要判斷兩個棋子是否屬於同一方;

第二,取出目標棋子的邏輯座標,再用函數blnCanEated(ByVal

IndexMoved As Integer, ByVal oldX As Integer, ByVal oldY As Integer,ByVal intdexStable As Integer, ByVal newX As Integer, ByVal newY As Integer) AsBoolean 來判斷源棋子IndexMoved 是否能從邏輯座標(oldXoldY)移動到(newXnewY)並吃掉這個位置的對方的棋子intdexStable

         這個函數同函數blnCanMove大致類似,不同之處在於炮的規則在二個函數中有差別。在走炮的時候,目標位置與起始位置之間不能有別的棋子,而在用炮吃子的時候,目標位置與起始位置中間必須有且只有一個棋子。

 

3.3  如何通知對方自己棋子的變化 

l  對於Winsock控件的協議選擇。

可以用Winsock控件來實現計算機間通信的功能。其關鍵之處在於對於協議的選取。其實對於網上象棋這個應用來說,其實這兩種協議都可以實現數據據傳輸的功能。在這我選取了傳輸控制協議TCP,原因如下:

第一、   數據發送是間歇的,用戶間在下棋的過程中不斷傳輸和接收數據。

第二、   TCP提供的是可靠的傳輸服務。

第三、   UDP提供的是面向無連接的服務,我希望客戶計算機提出下棋  

請求之後,得到服務器的確認信息。 

l  需要傳輸的信息。

        在這裏,通信的一方只需要將它所移動的棋子的索引號、目標位置的邏輯座標、是否刪除棋子以及如果要刪除棋子的話被刪除的棋子的索引號這四類信息傳送給通信的另一方。

        在系統中我通過字符串strSend = CStr(intIndex) & "|" & CStr(i) &"|" & CStr(j) & "d" & "0"strSend = CStr(intIndex) &"|" & CStr(i) & "|" & CStr(j) &"d" & CStr(index) 來分別傳送不刪除棋子、刪除棋子Index的信息,而intIndex則是源棋子,ij則是目標位置的邏輯座標。

                            如果是刪除棋子,則必須對被吃掉的棋子採取處理,可採用的方案是將棋子的blnDeleted設爲TRUE、屬性Visible設爲FALSE

 

 3.4 如何保證棋手依次走棋

        一名棋手在走棋之後,立即將自己的應用程序中的所有棋子鎖定(使各個命令按鈕的Enable屬性爲FALSE),直到對方傳送到信息才解除對所有棋子的鎖定。

        

 

4  系統實現簡介 

4.1  客戶端的TcpForclient_DataArrival事件的處理 

TcpForClient.GetData st

'獲得要移動的棋子的INDEX值和目標點的座標(IJ

   ………

qiZi(index).x =i

qiZi(index).y =j

Dim TempPhysicalZBAs ZuoBiao

TempPhysicalZB =transZB_Logic_physical(i, j)

CmdIcon(index).MoveTempPhysicalZB.x - halfCmdWidth,

TempPhysicalZB.y - halfCmdHeight

‘判斷老將是否被吃掉以及對應的操作

   ………

 

對於服務器端的TcpForserver_DataArrival事件的處理類似於客戶端。

 

4.2  函數blnCanMove來判斷棋子的走動是否合法 

Private FunctionblnCanMove (ByVal IndexMoved As Integer, ByVal oldX As Integer, ByVal

oldY As Integer, ByVal newX As Integer, ByVal newY As Integer) AsBoolean

………

Select CaseIndexMoved

    Case 1, 2, 3, 4, 5  '紅兵

        If (oldY < 6) And (oldX = newX AndnewY = oldY + 1) Then

 '沒有過河時只能向前走

            blnCanMove = True

               ElseIf (oldY >= 6) And (Abs(oldX - newX)= 1 And oldY = newY) Or

(oldX = newX AndnewY - oldY = 1) Then '過河後可以左右和向前移動

            blnCanMove = True

       Else

           blnCanMove = False

       End If

    ………

 

4.3  判斷是否別象眼的函數blnElphonentStoped 

Private FunctionblnElphonentStoped(ByVal x1 As Integer, ByVal y1 As Integer,

 ByVal x2 As Integer, ByVal y2As Integer) As Boolean

Dim i, xMid, yMid, iCount As Integer

xMid = (x1 + x2) / 2

yMid = (y1 + y2) / 2

iCount = 0

For i = 1 To 32

        If qiZi(i).blnDeleted = False Then

            If (qiZi(i).x = xMid) And(qiZi(i).y = yMid) Then

                       iCount = iCount + 1

                  End If

        End If

Next i

If iCount = 0 Then

    blnElphonentStoped = False

Else

    blnElphonentStoped = True

End If

End Function

 

4.4  用來移動棋子的事件處理過程Form_MouseDown 

 Form_MouseDown(Button As Integer, Shift AsInteger, x As Single, y As Single)

   For i = 1 To 9

      For j = 1 To 10

          TempPhysicalZB = transZB_Logic_physical(i, j)

          If Abs(x - TempPhysicalZB.x) <= intColToCol / 2 And

Abs(y -TempPhysicalZB.y) <= intRowToRow / 2 Then

IfblnCanMove(intIndex, qiZi(intIndex).x, qiZi(intIndex).y, i, j) = False Then

                  MsgBox "你不能這麼走!", vbCritical +vbOKOnly, "         錯誤"

                  Exit Sub

              End If                  

               strSend = CStr(intIndex) &"|" & CStr(i) & "|" & CStr(j) &"d" & "0"

                    'Call BeforeMove(intIndex,i, j)

               qiZi(intIndex).x = i

qiZi(intIndex).y= j

CmdIcon(intIndex).Move TempPhysicalZB.x - halfCmdWidth,

TempPhysicalZB.y- halfCmdHeight

                TcpForClient.SendData strSend

                Exit Sub

            End If

       Next j

   Next i

End Sub

 


  參考文獻:

  1  希望圖書創作室 · 中文Visual Basic 6.0教程 · 北京 :宇航出版社,1999.5

 2   Microsoft 公司·  Microsoft  Development Network

 

 

Realizationof the system of Chinese chess in network by winsock control of VB

                   MAGen-feng   SUN Yan   Wang  Ping

           

  Abstract    Firstly this paper describes how to uses thewinsock control in Visual Basic.   

Then it deeply analyses the design priciple and completion processof this system

Key words   Winsock controlTCPUDP

 

  

發佈了189 篇原創文章 · 獲贊 38 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章