基于VB中WINSOCK控件的网上象棋系统的实现

时间:2022-12-26 16:20:09

本文发表在《微型机与应用》杂志2001年第3期。

基于VB中WINSOCK控件的网上象棋系统的实现

马根峰1   ,  孙艳2  , 王平1

(1.重庆邮电学院自动化学院,重庆,400065;2. 铁道部第十九工程局四处,内蒙 通辽,028000 )

 摘要     本文首先介绍了Visual Basic中的WINSOCK控件的使用方法,然后深入探讨了网上象棋系统的设计思想及其实现过程。

关键词    WINSOCK控件;TCPUDP

中图分类号:    文献标识码

1      引言

    MicrosoftVisual Basic 是可视化的、面向对象的、采用事件驱动方式的结构化的高级程序设计语言。它提供了开发Microsoft Windows(R)应用程序的迅速、最简捷的方法。在网上象棋系统的工作中,笔者利用VB编写了网上象棋系统,实现了网上下棋的基本功能。

2 VBWINSOCK控件简介 

利用 WinSock 控件可以与远程计算机建立连接,并通过用户数据文报协议 (UDP)或者传输控制协议 (TCP)进行数据交换。这两种协议都可以用来创建客户与服务器应用

程序。

Winsock它提供了访问 TCP 和 UDP 网络服务的方便途径。Visual Basic、Visual 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 应用程序可以是客户机,也可以是服务器。

为了传输数据,首先要设置计算机A的RemoteHost为计算机B的名称或IP地址,然后将计算机A的RemotePort属性设置为计算机B的LocalPort 属性,最后调用Bind方法然后,指定用于 UDP 连接的 LocalPort 和 LocalIP。

经过上面的在个步骤之后,计算机A和B就可以调用 SendData 方法来着手发送信息,还可以在 DataArrival 事件内的利用 GetData 方法来获取已发送的信息了。

3  网上象棋中的几个关键问题  

3.1   如何将象棋中的棋子和棋盘的信息用计算机来描述出来 

l  象棋中棋盘

象棋中棋盘共有九列,十行,共有9 ´ 10 个点。我将显示器的最左下角看成是坐标原点,屏幕上方为Y轴的正方向,单位是1;屏幕的右方向看成是X轴的正方向,单位是1。然后用90个坐标(I,J)从(1,1)到(9,10)来表示这90个点的位置。

l  确定每个坐标点的物理地址。

    首先给出坐标原点的物理坐标(X0,Y0),然后利用公式

      X = X0+ (i1 - 1) * intColToCol

Y = Y0-(j1 - 1) * intRowToRow

         其中intColToCol、intRowToRow分别表示棋盘列间距、行间距。

l  棋子

两方棋子共2 ´ 16个,我自定义了记录类型qiZis ,它用域 index 、caption 、blnDeleted 、x、y分别表示棋子的序号、棋子的名称、是否被吃掉、在棋盘中的逻辑坐标的X值、Y值。外观上用命令按钮数组(其序号index从1到32)来代表棋子。

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的棋子是否能从逻辑坐标(oldX,oldY)移动到(newX,newY)。

在这个函数中则集中了每种棋子的走子规则。它主要是通过对两个坐标值进行处理来判断棋子IndexMoved是否能这样走子。

以行车为例,该函数在执行时要经过以下的判断:

每一,目标位置和起始位置是否在一条直线上,即目标位置的逻辑X、

Y坐标值与起始位置的X、Y坐标值是否有一个相等;

第二,目标位置与起始位置之间是否无其它的棋子。只有满足这两个条件,才能行车。

再举一个复杂的例子,能不能走马要经过以下的判断:

第一,目标位置与起始位置是否构成日字,目标位置与起始位置边线的斜率是否为2或1/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 是否能从逻辑坐标(oldX,oldY)移动到(newX,newY)并吃掉这个位置的对方的棋子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则是源棋子,i和j则是目标位置的逻辑坐标。

如果是删除棋子,则必须对被吃掉的棋子采取处理,可采用的方案是将棋子的blnDeleted设为TRUE、属性Visible设为FALSE。

 3.4 如何保证棋手依次走棋

        一名棋手在走棋之后,立即将自己的应用程序中的所有棋子锁定(使各个命令按钮的Enable属性为FALSE),直到对方传送到信息才解除对所有棋子的锁定。

        

4  系统实现简介 

4.1  客户端的TcpForclient_DataArrival事件的处理 

TcpForClient.GetData st

'获得要移动的棋子的INDEX值和目标点的坐标(I,J)

   ………

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 control;TCP;UDP

基于VB中WINSOCK控件的网上象棋系统的实现的更多相关文章

  1. VB中WinSock控件的属性、方法、事件及应用

    一.WinSock简介       Socket(套接字)最初是由加利福尼亚大学Berkeley(伯克利)分校为UNIX操作系统开发的网络通信接口,随着UNIX的广泛使用,Socket成为当前最流行的 ...

  2. VB6&period;0中WinSock控件属性和方法详解

    原文链接:http://liweibird.blog.51cto.com/631764/653134 WinSock控件能够通过UDP协议(用户数据报协议)或TCP协议(数据传输协议)连接到远程的机器 ...

  3. VB中PictureBox控件使用教程

    PictureBox对象可以说是任何对象的原始型态,它可以加载图片.显示文字.画图外,它还能与Frame对象一样,在自己本身里头加载其它的对象而自成一个小群组,用PictureBox可以仿真出任何对象 ...

  4. VB 中 NumericUpDown 控件 如何为手动输入设定触发事件

    Private Sub numDuration_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) ...

  5. 模仿win10样式,基于jquery的时间控件

    工作需要,写了一个基于jquery的时间控件,仿win10系统时间控件格式. 目前基本功能都有了,但时间格式只实现少数,但由于结构设计已经充分优化,填充起来非常容易. 这个控件相对网上其他的时间控件, ...

  6. &lbrack;转&rsqb;VB Winsock 控件TCP与UDP连接实例

    [-] 可能的用途 选择通讯协议 协议的设置 确定计算机的名称 TCP 连接初步 接受多个连接请求 UDP 初步 关于 Bind 方法   利用 WinSock 控件可以与远程计算机建立连接,并通过用 ...

  7. 在VBA中调用winsock控件

    如果系统没有Winsock控件的话,可以下载下面的控件MSWINSCK.OCX,然后将该文件复制到C:\Windows\System32目录下. 在VBE窗口中,从菜单"工具"-& ...

  8. vb&period;net中让控件内容为空(Control类)

    在平常的敲系统中大家有没有遇到需要让Textbox控件或者其他的控件的显示内容为空,以前直接的做法是直接等于空值,如果此类控件有很多,都需要空值,难道都要设置一下它的值为空嘛,显然这是一个笨办法,有没 ...

  9. 最全的基于MFC的ActiveX控件开发教程

    浏览器插件之ActiveX开发(一) 一般的Web应用对于浏览器插件能不使用的建议尽量不使用,因为其涉及到安全问题以及影响用户安装(或自动下载注册安装)体验问题.在有特殊需求(如涉及数据安全的金融业务 ...

随机推荐

  1. python time函数

    时间间隔是以秒为单位的浮点小数. 每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示. Python附带的受欢迎的time模块下有很多函数可以转换常见日期格式.如函数time.tim ...

  2. BZOJ2400&colon; Spoj 839 Optimal Marks

    Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. 给你一个有n个结点m条边的无向图.其中的一些点的值是给定的,而其 ...

  3. DLL输入和输出函数—dllinport与dllexport

    Microsoft特殊处 dllimport和dllexport存储类修饰符是C语言的Microsoft特殊处扩充.这些修饰显式定义了DLL的客户界面(可执行的文件或另外的DLL).说明为dllexp ...

  4. swift中的传值

    光阴似箭,日月如梭,转眼间学习的旅途已经过了一大半了,忘着自己所敲过的成批的代码,看着自己付出和努力,默默地为自己这几个月的奋斗感到欣慰,不论学习的路途再怎么的艰辛,但是自己还是坚持过来了,回想着以往 ...

  5. 我所不知道的 Chrome 开发者工具

    http://www.oschina.net/translate/things-i-didnt-know-about-chrome-devtools 自打我开始进行Web开发后,我就一直将Firebu ...

  6. 如何使用JAVA语言抓取某个网页中的邮箱地址

    现实生活中咱们常常在浏览网页时看到自己需要的信息,但由于信息过于庞大而又不能逐个保存下来. 接下来,咱们就以获取邮箱地址为例,使用java语言抓取网页中的邮箱地址 实现思路如下: 1.使用Java.n ...

  7. frame和bounds的区别

    frame:根据父视图坐标系来确定自己的位置 bounds:该视图在自己坐标系的位置和大小 修改bounds并不会引起视图位置的变化,会影响自身子视图的位置:修改frame会引起视图位置的变化 UIV ...

  8. yii2的变量是如何注入到视图中去的?

    我对yii2的控制器中的变量如何渲染到视图中这个问题一直很好奇,另外,我还对yii2如何加载静态资源,如js和css比较好奇,于是趁着周末就看了下yii2的相关源码想把这两个问题都弄明白.变量如何渲染 ...

  9. 解决 CentOS7 安装完成后ifconfig命令不能用

    今天用VMWare安装了CentOS7,选择了最小安装包模式,安装完毕之后想查看一下本机的ip地址,发现报错 # ifconfig -bash: ifconfig: command not found ...

  10. Android Studio 的 build 过程

    如图, 编译器将源代码(包括 Application Module 及其所依赖的所有 Library 源代码)转换成 DEX(Dalvik Executable)文件(其中包括运行在 Android ...