UQ Students should read the Disclaimer & Warning
Note: This page dates from 2005, and is kept for historical purposes.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>COMP2301 - Assignment 5 - Basic Network Programming in Visual Basic</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
<!--
.wrong {
background: #FF9999;
}
body {
background: url(_img/DSC04989.jpg) fixed center;
font-family: "Arial Unicode MS", Arial, Helvetica, sans-serif;
}
th, td, textarea {
border: 1px solid #000000;
padding: 0 1ex;
background: transparent;
overflow: hidden;
}
table {
border: none;
}
.changing-vars {
color: #0000FF;
}
-->
</style>
</head>
<body>
<h1>COMP2301 – Assignment Five – Basic Network Programming in Visual
Basic</h1>
<p> This assignment is a pass/fail assignment. I achieved a pass.</p>
<p>The goal of this assignment is to gain experience using Visual Basic by implementing
a simple network enabled application. </p>
<p>In this assignment, you should become familiar with: </p>
<ul>
<li>Network programming under Visual Studio 6 </li>
<li>IP addresses, Ports and Sockets </li>
</ul>
<h2>Specification </h2>
<p>Develop a network enabled version of Tick Tack Toe with the following features:</p>
<ul>
<li>Auto Discovery for all active work stations within a set IP range </li>
<li>Display Network Gaming traffic in a text window </li>
<li>Display game local status on screen (Playing, Win, Lose, Draw, Abort) </li>
<li>Display game network status on screen (Off Line, Ready, Busy) </li>
<li>Publish game network status via a network port (Off Line, Ready, Busy) </li>
<li>Randomly select the player who makes the first move </li>
</ul>
<p>Each player must be able to:</p>
<ul>
<li>Invite other players to game by selecting a remote player from the auto
discovery list </li>
<li>Accept or reject an invitation from another player </li>
<li>Perform all functions via mouse clicks </li>
<li>Manually set the games network status at any time. (Off Line, Ready, Busy) </li>
<li>Abort & Reset the game at any time. </li>
<li>Change the Auto Discovery Range to any continuous sub range between 130.102.73.32
and 130.102.73.64 </li>
</ul>
<h2>General operation </h2>
<p>The applications will communicate over a number of fixed ports via simple
text messages to transfer gaming status and commands. </p>
<p>Individual ports are specified for sending and receiving gaming traffic. It
is assumed that a small number of games will be active at any one time and that
all network requests will be services without delay. </p>
<p>Each game will format and display the content of all gaming traffic it has
generated or received in a text window. The gaming commands, auto discovery
requests and any other application specific messages will be presented at the
bottom of the screen in a scrolling window. The last 100 gaming command and
control messages should be buffered and accessible. At the top of the screen
all status information must be displayed with buttons for all the gaming functions. </p>
<p>After launching the application the user will select Auto Discovery to generate
a listing of all the active workstations. </p>
<p>The user may click on any one of the listed active gaming work stations and
invite them to play. On the remote gaming work station a dialog box containing
a detailed invitation will be displayed. The remote user may now accept or reject
the invitation. If the remote user accepts the invitation the inviting system
will randomly assign a player to go first. The first player must select Naught
(green) or Cross (red) and click to indicate where to place their selection.
The other system will automatically assign the remaining token. After this each
player will make a selection in turn until the game is over. (out of turn plays
are illegal) </p>
<p>Each end will maintain error checking and highlight any remote illegal moves
in blue on the local system. If an illegal move is made the originator must
display the move (O=green, X=red) and send the move to the remote player. The
remote player must detect the invalid move, display the move in blue and send
an illegal move message back. The originator of the illegal move must respond
to the illegal move information and automatically change the colour of the illegal
item on their local system. If the originator of an illegal move clicks that
item (now blue) it will be removed from the game. Only after all illegal items
are removed can the game proceed. </p>
<p>When a winning token is placed the remote system must detect the condition
and notify the originator of the win. After this the winning line of X/O will
be identified as a local event by colour change on both systems. The game is
now over. The players will be shown a dialogue box congratulating the winner.
At any time either player may Abort / Reset or Manually change the games network
status. Connected players should react to all events logically. </p>
<h2>Port definitions </h2>
<ul>
<li>All port definitions and functions are symmetric for local and remote systems </li>
<li>No dynamic ports are used by the application. (all fixed) </li>
<li>Port 6000 : Discovery Request. Listening only. This port must be monitored
by the application at all times. All traffic must be processed immediately. </li>
<li>Port 6001 : Discovery Request. Transmit only. This port is used to send
a local system’s Discovery Request to port 6000 of a remote system. </li>
<li>Port 6010 : Discovery Status. Listening only. This port accepts status information
from a remote systems. </li>
<li>Port 6011 : Discovery Status. Transmit only. This port is used to send local
system status information to port 6010 in response to a remote request. </li>
<li>Port 6020 : Game commands. Listening only. This port accepts gaming commands
from the remote system. </li>
<li>Port 6021 : Game commands. Transmit only. This port sends gaming commands
to the remote system. </li>
</ul>
<h2>Commands & Messages</h2>
<p> (examples: Local system John Smith IP 130.102.73.53. Remote system Fred Nirk
IP 130.102.73.33) </p>
<ul>
<li>Port <span class="changing-vars">6000</span>: This port accepts one command
only from a remote system. <Auto Discovery Request, For:<span class="changing-vars">IP</span>> <br />
ie Auto Discovery Request, For:<span class="changing-vars">130.102.73.53</span>. </li>
<li>Port <span class="changing-vars">6001</span>: This port sends one command
only to a remote system. <Auto Discovery Request, For:<span class="changing-vars">IP</span>><br />
ie Auto Discovery Request, For:<span class="changing-vars">130.102.73.32</span> </li>
<li>Port <span class="changing-vars">6010</span>: This port accepts status information
from a remote systems. <br />
ie Auto Discovery Reply, Status: <span class="changing-vars">Off Line</span> From:<span class="changing-vars">130.102.73.33</span> Players
Name: <span class="changing-vars">Fred Nirk </span></li>
<li>Port <span class="changing-vars">6011</span>: This port sends local status
information to a remote systems. <Auto Discovery Reply, Status: <span class="changing-vars">Status</span> From:<span class="changing-vars">IP</span> Players
Name: <span class="changing-vars">name</span>> <br />
Auto Discovery Reply, Status: <span class="changing-vars">Ready</span> From:<span class="changing-vars">130.102.73.53</span> Players
Name: <span class="changing-vars">John Smith</span> <br />
<span class="changing-vars">Status</span> = [Off Line, Ready, Busy] </li>
<li>Port <span class="changing-vars">6020</span>: This port accepts gaming messages
and commands from a remote system </li>
<li>Port <span class="changing-vars">6021</span>: This port sends gaming messages
and commands to a remote system </li>
</ul>
<h2>Gaming Commands</h2>
<p> Port 6020 & Port 6021 </p>
<p><Invitation, From:<span class="changing-vars">IP</span> Players Name: <span class="changing-vars">Inviting
player’s name</span>> <em>Invite a remote player to play the game.<br />
</em><Acceptance, From:<span class="changing-vars">IP</span> Players Name: <span class="changing-vars">Accepting
player’s name</span>> <em>Accept an invitation to play the game. <br />
</em><Assign First Player, From:<span class="changing-vars">IP</span> First
Players Name: <span class="changing-vars">First players name</span>> <em>Inviting
system must select and assign the first player status. <br />
</em><Select, Token: <span class="changing-vars">x</span> From:<span class="changing-vars">IP</span> Players
Name: <span class="changing-vars">name</span>> <em>Each player selects X
or O which is displayed on the remote screen. Token: [<span class="changing-vars">X</span>|<span class="changing-vars">O</span>] <br />
</em><Place , Token: <span class="changing-vars">x</span> Colour: <span class="changing-vars">x</span> Position: <span class="changing-vars">xx</span> From:<span class="changing-vars">IP</span> Players
Name: <span class="changing-vars">name</span> > <em>Player places a token
on the grid A1 to C3 with Colour [R|G|B] <br />
</em><Delete, Token: <span class="changing-vars">x</span> Colour: <span class="changing-vars">x</span> Position: <span class="changing-vars">xx</span> From:<span class="changing-vars">IP</span> Players
Name: <span class="changing-vars">name</span> > <em>Reports the removal of
an illegal token from a system. <br />
</em><Illegal, Token: <span class="changing-vars">x</span> Colour: <span class="changing-vars">x</span> Position: <span class="changing-vars">xx</span> From:IP
Players Name: <span class="changing-vars">name</span> > <em>Identifies an
illegal token to the remote system. <br />
</em><Winner, From:<span class="changing-vars">IP</span> Winners Name: <span class="changing-vars">winner’s
name</span>> <em>Notifies the remote system of game completion. <br />
</em></p>
<h2>Example</h2>
<p> Text from Network Gaming traffic window on the local system </p>
<ul>
<li> This traffic should be presented as a sequence of text strings one per
line in time order. <br />
<em>..................User selects Auto Discovery function from GUI ..................... <br />
</em> Local Port <span class="changing-vars">6001</span> >>> Remote
Port <span class="changing-vars">6000</span> Auto Discovery Request, For: <span class="changing-vars">130.102.73.32</span> <br />
Local Port <span class="changing-vars">6010</span> <<< Remote Port <span class="changing-vars">6011</span> Auto
Discovery Reply, Status: <span class="changing-vars">Ready</span> From: <span class="changing-vars">130.102.73.32</span> Players
Name: <span class="changing-vars">David Jones</span> <br />
Local Port <span class="changing-vars">6001</span> >>> Remote Port <span class="changing-vars">6000</span> Auto
Discovery Request, For: <span class="changing-vars">130.102.73.33</span> <br />
Local Port <span class="changing-vars">6010</span> <<< Remote Port <span class="changing-vars">6011</span> Auto
Discovery Reply, Status: <span class="changing-vars">Ready</span> From: <span class="changing-vars">130.102.73.33</span> Players
Name: <span class="changing-vars">Fred Nirk</span> <br />
Local Port <span class="changing-vars">6001</span> >>> Remote Port <span class="changing-vars">6000</span> Auto
Discovery Request, For: <span class="changing-vars">130.102.73.34</span> <br />
Local Port <span class="changing-vars">6010</span> <<< Remote Port <span class="changing-vars">6011</span> Auto
Discovery Reply, Status: <span class="changing-vars">Busy</span> From: <span class="changing-vars">130.102.73.34</span> Players
Name: <span class="changing-vars">Max Mouse</span> <br />
Local Port <span class="changing-vars">6001</span> >>> Remote Port <span class="changing-vars">6000</span> Auto
Discovery Request, For: <span class="changing-vars">130.102.73.35</span> <em>(No
response from system.........) </em><br />
Local Port <span class="changing-vars">6001</span> >>> Remote Port <span class="changing-vars">6000</span> Auto
Discovery Request, For: <span class="changing-vars">130.102.73.36</span> <em>(No
response from system........) </em><br />
Local Port <span class="changing-vars">6001</span> >>> Remote Port <span class="changing-vars">6000</span> Auto
Discovery Request, For: <span class="changing-vars">130.102.73.37</span> <em>(No
response from system........) </em><br />
Local Port <span class="changing-vars">6001</span> >>> Remote Port <span class="changing-vars">6000</span> Auto
Discovery Request, For: <span class="changing-vars">130.102.73.38</span> <em>(No
response from system........) </em><br />
Local Port <span class="changing-vars">6010</span> <<< Remote Port <span class="changing-vars">6011</span> Auto
Discovery Reply, Status: <span class="changing-vars">Off Line</span> From: <span class="changing-vars">130.102.73.38</span> Players
Name: <span class="changing-vars">Donald Duck</span> <br />
<em>..................Auto Discovery continues.......... <br />
</em> Local Port <span class="changing-vars">6001</span> >>> Remote
Port <span class="changing-vars">6000</span> Auto Discovery Request, For: <span class="changing-vars">130.102.73.64</span> <br />
Local Port <span class="changing-vars">6010</span> <<< Remote Port <span class="changing-vars">6011</span> Auto
Discovery Reply, Status: <span class="changing-vars">Ready</span> From: <span class="changing-vars">130.102.73.64</span> Players
Name: <span class="changing-vars">Another Player</span> <br />
<em>. .................User selects Second Player from list Fred Nirk.......................... </em><br />
Local Port <span class="changing-vars">6021</span> >>> Remote Port <span class="changing-vars">6020</span> Invitation,
From: <span class="changing-vars">130.102.73.53</span> Players Name: <span class="changing-vars">John
Smith</span> <br />
Local Port <span class="changing-vars">6020</span> <<< Remote Port <span class="changing-vars">6021</span> Acceptance,
From: <span class="changing-vars">130.102.73.33</span> Players Name: <span class="changing-vars">Fred
Nirk</span> <br />
Local Port <span class="changing-vars">6021</span> >>> Remote Port <span class="changing-vars">6020</span> Assign
First Player, From: <span class="changing-vars">130.102.73.53</span> First
Players Name: <span class="changing-vars">John Smith</span> <em>(Randomly select
the first player) </em><br />
Local Port <span class="changing-vars">6021</span> >>> Remote Port <span class="changing-vars">6020</span> Select,
Token: <span class="changing-vars">O</span> From: <span class="changing-vars">130.102.73.53</span> Players
Name: <span class="changing-vars">John Smith</span> <em>(Second player’s system
displays remaining token X ) </em><br />
Local Port <span class="changing-vars">6021</span> >>> Remote Port <span class="changing-vars">6020</span> Place
, Token: <span class="changing-vars">O</span> Colour: <span class="changing-vars">G</span> Position: <span class="changing-vars">B2</span> From: <span class="changing-vars">130.102.73.53</span> Players
Name: <span class="changing-vars">John Smith</span> <br />
Local Port <span class="changing-vars">6020</span> <<< Remote Port <span class="changing-vars">6021</span> Place
, Token: <span class="changing-vars">X</span> Colour: <span class="changing-vars">R</span> Position: <span class="changing-vars">B1</span> From: <span class="changing-vars">130.102.73.33</span> Players
Name: <span class="changing-vars">Fred Nirk</span> <br />
Local Port <span class="changing-vars">6021</span> >>> Remote Port <span class="changing-vars">6020</span> Place
, Token: <span class="changing-vars">O</span> Colour: <span class="changing-vars">G</span> Position: <span class="changing-vars">A3</span> From: <span class="changing-vars">130.102.73.53</span> Players
Name: <span class="changing-vars">John Smith</span> <br />
<em>.................Play continues until John’s system detects Fred placing
a token at C2 out of turn......................... </em><br />
Local Port <span class="changing-vars">6021</span> >>> Remote Port <span class="changing-vars">6020</span> Illegal,
Token: <span class="changing-vars">X</span> Colour: <span class="changing-vars">B</span> Position: <span class="changing-vars">C2</span> From: <span class="changing-vars">130.102.73.53</span> Players
Name: <span class="changing-vars">John Smith</span> <em>(Fred’s system must
redisplay C2) <br />
</em>Local Port <span class="changing-vars">6020</span> <<< Remote
Port <span class="changing-vars">6021</span> Delete, Token: <span class="changing-vars">X</span> Colour: <span class="changing-vars">B</span> Position: <span class="changing-vars">C2</span> From: <span class="changing-vars">130.102.73.33</span> Players
Name: <span class="changing-vars">Fred Nirk</span> ( <em>Fred removed the illegal
token) </em><br />
<em>.................Play continues until Fred’s system detects the last token
placed by John was the winning move......................... </em><br />
Local Port <span class="changing-vars">6020</span> <<< Remote Port <span class="changing-vars">6021</span> Winner,
From: <span class="changing-vars">130.102.73.33</span> Winners Name: <span class="changing-vars">John
Smith</span> <br />
</li>
</ul>
<h2>General </h2>
<ul>
<li>Auto Discovery IP range must be displayed on screen and show both upper
and lower values. Maximum range must be hard coded. </li>
<li>Players may place X or O at any time and in any order. All plays must be
displayed on the local system in Red and Green. </li>
<li>Reasonable error detection and handling is required. </li>
<li>The application must be well behaved and terminate gracefully. </li>
<li>Care must be taken during the development and testing of this application
to avoid excessive network traffic. </li>
</ul>
<p>No IP traffic should be generated outside of the specified IP / Port range. </p>
<p><em>Note: This application was coded as fast as possible, and as such does
not conform exactly to the specification, and may not be stable or fit for
use. The IP range is hard-coded, so without modification this application will
only work in environments with a similar IP range.</em></p>
<p><a href=".//COMP2301-assignment-5-TicTacToe.exe" title="Downloadable application - TicTacToe">Compiled
(WIN32) binary</a> (64 KB)</p>
<p>frmTicTacToe.frm<br />
<textarea name="vb" cols="82" rows="1180" readonly="readonly" title="Visual Basic 6 Code">VERSION 5.00
Object = "{248DD890-BB45-11CF-9ABC-0080C7E7B78D}#1.0#0"; "MSWINSCK.OCX"
Begin VB.Form frmTicTacToe
Caption = "Naughts and Crosses"
ClientHeight = 6240
ClientLeft = 165
ClientTop = 735
ClientWidth = 5415
LinkTopic = "Form1"
ScaleHeight = 6240
ScaleWidth = 5415
StartUpPosition = 3 'Windows Default
Begin VB.ListBox lstStatus
Height = 1230
Left = 0
TabIndex = 10
Top = 4920
Width = 5415
End
Begin MSWinsockLib.Winsock udpGameOUT
Left = 7440
Top = 0
_ExtentX = 741
_ExtentY = 741
_Version = 393216
Protocol = 1
End
Begin MSWinsockLib.Winsock udpGameIN
Left = 6840
Top = 0
_ExtentX = 741
_ExtentY = 741
_Version = 393216
Protocol = 1
End
Begin MSWinsockLib.Winsock udpStatusOUT
Left = 6240
Top = 0
_ExtentX = 741
_ExtentY = 741
_Version = 393216
Protocol = 1
End
Begin MSWinsockLib.Winsock udpStatusIN
Left = 5640
Top = 0
_ExtentX = 741
_ExtentY = 741
_Version = 393216
Protocol = 1
End
Begin MSWinsockLib.Winsock udpAutoRecOUT
Left = 5040
Top = 0
_ExtentX = 741
_ExtentY = 741
_Version = 393216
Protocol = 1
End
Begin MSWinsockLib.Winsock udpAutoRecIN
Left = 4440
Top = 0
_ExtentX = 741
_ExtentY = 741
_Version = 393216
Protocol = 1
End
Begin VB.Frame frmAutoFind
Caption = "Naughts and Crosses (Auto Find)"
Height = 4815
Left = 0
TabIndex = 15
Top = 0
Width = 5415
Begin VB.CommandButton btnAutoDiscover
Caption = "&AutoDiscover"
Height = 375
Left = 120
TabIndex = 18
Top = 4320
Width = 2055
End
Begin VB.CommandButton btnInvite
Caption = "&Invite"
Enabled = 0 'False
Height = 375
Left = 2280
TabIndex = 17
Top = 4320
Width = 1095
End
Begin VB.ListBox lstUsers
Height = 3960
Left = 120
TabIndex = 16
Top = 240
Width = 5055
End
End
Begin VB.Frame frmConfig
Caption = "Configuration"
Enabled = 0 'False
Height = 4815
Left = 0
TabIndex = 11
Top = 0
Visible = 0 'False
Width = 5415
Begin VB.ComboBox cmbIPLower
Height = 315
Left = 2160
TabIndex = 21
Text = "Combo2"
Top = 2760
Width = 855
End
Begin VB.ComboBox cmbIPUpper
Height = 315
Left = 480
TabIndex = 20
Text = "Combo1"
Top = 2760
Width = 855
End
Begin VB.CommandButton btnSave
Caption = "&Save Settings"
Height = 375
Left = 3480
TabIndex = 13
Top = 4200
Width = 1575
End
Begin VB.TextBox txtName
Height = 285
Left = 480
TabIndex = 12
Text = "Text1"
Top = 1440
Width = 2175
End
Begin VB.Label lblIPRange
Caption = "(Upper) Select IP Range (Lower)"
Height = 255
Left = 480
TabIndex = 19
Top = 2280
Width = 3135
End
Begin VB.Label lblName
Caption = "Name:"
Height = 255
Left = 480
TabIndex = 14
Top = 1200
Width = 2175
End
End
Begin VB.Frame frmGameFrame
Caption = "Naughts and Crosses (Starting Up...)"
Enabled = 0 'False
Height = 4815
Left = 0
TabIndex = 0
Top = 0
Visible = 0 'False
Width = 5415
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 8
Left = 3600
Style = 1 'Graphical
TabIndex = 9
Top = 3240
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 7
Left = 1920
Style = 1 'Graphical
TabIndex = 8
Top = 3240
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 6
Left = 240
Style = 1 'Graphical
TabIndex = 7
Top = 3240
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 5
Left = 3600
Style = 1 'Graphical
TabIndex = 6
Top = 1800
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 4
Left = 1920
Style = 1 'Graphical
TabIndex = 5
Top = 1800
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 3
Left = 240
Style = 1 'Graphical
TabIndex = 4
Top = 1800
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 2
Left = 3600
Style = 1 'Graphical
TabIndex = 3
Top = 360
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 1
Left = 1920
Style = 1 'Graphical
TabIndex = 2
Top = 360
Width = 1575
End
Begin VB.CommandButton btnXO
Caption = " "
Enabled = 0 'False
Height = 1335
Index = 0
Left = 240
Style = 1 'Graphical
TabIndex = 1
Top = 360
Width = 1575
End
End
Begin VB.Menu mnuGame
Caption = "Game"
Begin VB.Menu mnuStatus
Caption = "Status"
Begin VB.Menu mnuReady
Caption = "&Ready"
End
Begin VB.Menu mnuOffline
Caption = "&Offline"
Checked = -1 'True
End
Begin VB.Menu mnuBusy
Caption = "&Busy"
End
End
Begin VB.Menu mnuConfig
Caption = "&Configure..."
End
Begin VB.Menu mnuReset
Caption = "&Reset/Abort"
End
Begin VB.Menu mnuExit
Caption = "E&xit"
End
End
Begin VB.Menu mnuHelp
Caption = "&Help"
Begin VB.Menu mnuAbout
Caption = "Abo&ut"
End
End
End
Attribute VB_Name = "frmTicTacToe"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
' Naughts and Crosses
' Copyright (C) 2004 Ned Martin www.nedmartin.org
' #40529927
' Coded for a University of Queensland COMP2301 Assignment 5
' global variables
Dim myStatus As String
Dim myName As String
Dim myToken As String
Dim remoteName As String
Dim remoteIP As String
Dim remotePlaysFirst As Boolean
Dim remoteToken As String
Dim myTurn As Boolean
Dim IPUpper As Integer
Dim IPLower As Integer
' holds array of square positions
Dim gamePositions(8) As String
' auto discover
Private Sub btnAutoDiscover_Click()
' 130.102.73.32 and 130.102.73.64
' clear user list
lstUsers.Clear
' send requests to everyone
Dim IP As Integer
For IP = IPLower To IPUpper
sendAutoRecData ("130.102.73." & IP)
Next
End Sub
' save settings
Private Sub btnSave_Click()
' save settings
myName = txtName.Text
' hide the config frame
frmConfig.Visible = False
frmConfig.Enabled = False
' show the autofind frame
frmAutoFind.Enabled = True
frmAutoFind.Visible = True
End Sub
' when user list is clicked
Private Sub lstUsers_Click()
Dim Status As String
Dim pos As Integer
Status = lstUsers.Text
' parse item for IP etc.
'name (status) [IP]
pos = InStrRev(Status, "(")
Status = Mid(Status, pos + 1, 1)
' enable invite button if status R, else disable on O or B
If Status = "R" Then
btnInvite.Enabled = True
Else
btnInvite.Enabled = False
End If
End Sub
' invite a player
Private Sub btnInvite_Click()
' only if player is ready
Dim Item As String
Dim Status As String
Dim remoteIP As String
Dim pos As Integer
Item = lstUsers.Text
' parse item for IP etc.
'name (status) [IP]
pos = InStrRev(Item, "(")
Status = Mid(Item, pos + 1, 1)
pos = InStrRev(Item, "[")
remoteIP = Mid(Item, pos + 1, Len(Item) - pos - 1)
addStatus (Status & "_" & remoteIP)
' invite the user
If Status = "R" Then
Call sendGameData(remoteIP, 0, "X", "R", 0, "")
End If
'Call sendGameData("remoteIP", 0, "X", "R", 0, "None")
End Sub
Private Sub btnXO_Click(Index As Integer)
Dim Colour As String
' if it's my turn
If myTurn Then
' button is unused
If btnXO(Index).Caption = " " Then
' need to only allow clicking valid buttons
' set button to my token (X or O)
btnXO(Index).Caption = myToken
'Call sendGameData("localhost", "Place", "X", "R", Index, "localhost", "ned")
' set colours
If myToken = "X" Then
Colour = "R"
btnXO(Index).BackColor = vbRed
Else
Colour = "G"
btnXO(Index).BackColor = vbGreen
End If
Call addStatus(gamePositions(Index) & " Clicked" & " my token:" & myToken)
Call sendGameData(remoteIP, 4, myToken, Colour, Index, "")
' not my turn anymore
Call disableButtons
' check for win
' we only check for win when receiving place msg
' we also call checkWin if we receive a winning msg
'Call checkWin
Else
addStatus ("Attempt to click used button")
End If
Else
addStatus ("Attempt to click out of turn")
End If
End Sub
' check for win
Private Sub checkWin()
Dim Counter As Integer
Dim Button As Integer
Dim Token As String
Dim Won As String
Token = myToken
' loop twice, first for X, second for O
For Counter = 0 To 1
' check
' 0 1 2
' 3 4 5
' 6 7 8
For Button = 0 To 8 Step 3
If btnXO(Button).Caption = Token And btnXO(Button + 1).Caption = Token And btnXO(Button + 2).Caption = Token Then
btnXO(Button).BackColor = vbYellow
btnXO(Button + 1).BackColor = vbYellow
btnXO(Button + 2).BackColor = vbYellow
' winner
Won = Token
End If
Next
' 0 3 6
' 1 4 7
' 2 5 8
For Button = 0 To 2
If btnXO(Button).Caption = Token And btnXO(Button + 3).Caption = Token And btnXO(Button + 6).Caption = Token Then
btnXO(Button).BackColor = vbYellow
btnXO(Button + 3).BackColor = vbYellow
btnXO(Button + 6).BackColor = vbYellow
Won = Token
End If
Next
' 0 4 8
' 2 4 6
If btnXO(0).Caption = Token And btnXO(4).Caption = Token And btnXO(8).Caption = Token Then
btnXO(0).BackColor = vbYellow
btnXO(4).BackColor = vbYellow
btnXO(8).BackColor = vbYellow
Won = Token
End If
' 2 4 6
If btnXO(2).Caption = Token And btnXO(4).Caption = Token And btnXO(6).Caption = Token Then
btnXO(2).BackColor = vbYellow
btnXO(4).BackColor = vbYellow
btnXO(6).BackColor = vbYellow
Won = Token
End If
Token = remoteToken
Next
If Won = myToken Then
' I have won
' this means remote sent winning msg
' we highlight winning row and pop up msg
If MsgBox("Game Over." & vbCrLf & myName & " was the winner. Click OK to reset", vbOKOnly) = vbOK Then
Call reset
End If
ElseIf Won = remoteToken Then
' remote has won
' send winning msg
'<Winner, From:IP Winners Name: winner's name>
Call sendGameData(remoteIP, 7, "", "", 0, remoteName)
If MsgBox("Game Over." & vbCrLf & remoteName & " was the winner. Click OK to reset", vbOKOnly) = vbOK Then
Call reset
End If
End If
End Sub
' Form Load
' Set inital state here
Private Sub Form_Load()
' init winsocks, bind to ports, etc
'udpAutoRecIN.LocalPort = 6000
udpAutoRecIN.Bind 6000
' note we are not setting local port for this udp?
'udpAutoRecOUT.LocalPort = 6001
udpAutoRecOUT.RemotePort = 6000
'udpStatusIN.LocalPort = 6010
udpStatusIN.Bind 6010
'udpStatusOUT.LocalPort = 6011
udpStatusOUT.RemotePort = 6010
'udpGameIN.LocalPort = 6020
udpGameIN.Bind 6020
'udpGameOUT.LocalPort = 6021
udpGameOUT.LocalPort = 6021
udpGameOUT.RemotePort = 6020
' populate gamePositions
gamePositions(0) = "A1"
gamePositions(1) = "A2"
gamePositions(2) = "A3"
gamePositions(3) = "B1"
gamePositions(4) = "B2"
gamePositions(5) = "B3"
gamePositions(6) = "C1"
gamePositions(7) = "C2"
gamePositions(8) = "C3"
' set status to offline and name to default
myStatus = "Off Line"
myName = "Ned@" & udpAutoRecIN.LocalIP
txtName = myName
Call addGameMsg(myName & " Off Line")
Call reset
' make random number
Randomize
' fill IP boxes
IPUpper = 64
IPLower = 32
Dim IP As Integer
For IP = 32 To 64
cmbIPUpper.AddItem (IP)
cmbIPLower.AddItem (IP)
Next
End Sub
' show about form
Private Sub mnuAbout_Click()
frmAbout.Show
End Sub
' enter config mode
Private Sub mnuConfig_Click()
' hide the gameframe
' cannot call config during a game
'frmGameFrame.Visible = False
'frmGameFrame.Enabled = False
' hide the autofind frame
frmAutoFind.Visible = False
frmAutoFind.Enabled = False
' show the config frame
frmConfig.Enabled = True
frmConfig.Visible = True
End Sub
' set status to Busy
Private Sub mnuBusy_Click()
myStatus = "Busy"
mnuBusy.Checked = True
mnuReady.Checked = False
mnuOffline.Checked = False
addGameMsg (myName & " Busy")
End Sub
' set status to Off Line
Private Sub mnuOffline_Click()
myStatus = "Off Line"
mnuOffline.Checked = True
mnuBusy.Checked = False
mnuReady.Checked = False
addGameMsg (myName & " Off Line")
End Sub
' set status to ready
Private Sub mnuReady_Click()
myStatus = "Ready"
mnuReady.Checked = True
mnuOffline.Checked = False
mnuBusy.Checked = False
addGameMsg (myName & " Ready")
End Sub
' place a token
Private Sub placeToken(Colour As String, Position As String)
' place a token of Colour at position tokenPosition
' must check if move is valid
' if it is not my turn
If Not myTurn Then
' if position is not already taken
If btnXO(convertPosition(Position)).Caption = " " Then
Dim BackColour As ColorConstants
Select Case (Colour)
Case "R"
BackColour = vbRed
Case "G"
BackColour = vbGreen
Case "B"
BackColour = vbBlue
End Select
btnXO(convertPosition(Position)).Caption = remoteToken
btnXO(convertPosition(Position)).BackColor = BackColour
' it is now my turn so enable buttons
Call enableButtons
' check for win
' if won then remote host has won
Call checkWin
Else
' attempt to place token in used position
' set to blue
btnXO(convertPosition(Position)).Caption = " "
btnXO(convertPosition(Position)).BackColor = vbBlue
' send illegal move msg
addStatus ("Attempt to place token in used position")
Call sendGameData(remoteIP, 6, remoteToken, Colour, convertPosition(Position), "")
End If
Else
' it is my turn
' this move is illegal
' set to blue
btnXO(convertPosition(Position)).Caption = " "
btnXO(convertPosition(Position)).BackColor = vbBlue
' sent illegal move msg
'<Illegal, Token: x Colour: x Position: xx From:IP Players Name: name >
Call sendGameData(remoteIP, 6, remoteToken, Colour, convertPosition(Position), "")
addStatus ("Attempt by remote to place token out of turn")
End If
End Sub
' delete a token
Private Sub deleteToken(Position As String)
' delete a token
btnXO(convertPosition(Position)).Caption = " "
btnXO(convertPosition(Position)).BackColor = &H8000000F
addStatus ("Delete:" & Position)
End Sub
' enable buttons
' called when it is my turn
Private Sub enableButtons()
' check what buttons we should enable
' currently enabling all buttons
Dim buttons As Integer
For buttons = 0 To 8
If btnXO(buttons).Caption = " " Then
btnXO(buttons).Enabled = True
End If
Next
myTurn = True
addGameMsg ("Your Turn - Playing " & remoteName)
End Sub
' disable buttons
' called when it is not my turn
Private Sub disableButtons()
Dim buttons As Integer
For buttons = 0 To 8
btnXO(buttons).Enabled = False
Next
myTurn = False
addGameMsg ("Remote Turn - Playing " & remoteName)
End Sub
' reset
Private Sub reset()
' we need to re-enable the finding people stuff etc
' hide gameframe
frmGameFrame.Visible = False
frmGameFrame.Enabled = False
' show autofind frame
frmAutoFind.Enabled = True
frmAutoFind.Visible = True
' enable config
mnuConfig.Enabled = True
Dim Button As Integer
' init remote as default values
remoteIP = "localhost"
remoteName = "remote"
' disable buttons and reset them
For Button = 0 To 8
btnXO(Button).Enabled = False
btnXO(Button).Caption = " "
btnXO(Button).BackColor = &H8000000F
Next
End Sub
' start the game
Private Sub startGame()
' we need to disable stuff here
' hide autofind frame
frmAutoFind.Visible = False
frmAutoFind.Enabled = False
' disable config
mnuConfig.Enabled = False
' show gameframe
frmGameFrame.Enabled = True
frmGameFrame.Visible = True
' set status to busy
Call mnuBusy_Click
' set frame msg
addGameMsg ("Playing " & remoteName)
If remotePlaysFirst Then
' remote player goes first
myTurn = False
Else
' we go
' enable buttons
Call enableButtons
End If
End Sub
' reset the game
Private Sub mnuReset_Click()
Call reset
End Sub
' get data from udpAutoRecIN
Private Sub udpAutoRecIN_DataArrival(ByVal bytesTotal As Long)
' <Auto Discovery Request, For:IP>
Dim msg As String
udpAutoRecIN.GetData msg
' add to status
Call addStatus("AutoRecIN < " & msg)
' reply to auto recovery request
Call sendStatusData(udpAutoRecIN.RemoteHostIP, myStatus, myName)
End Sub
' handle invitation
Private Sub handleInvitation(IP As String, Name As String)
If MsgBox("Invitation from " & Name & " [" & IP & "]", vbYesNo) = vbYes Then
' we have accepted a game
' set IPs
remoteIP = IP
remoteName = Name
' other player assigns a player to go first
' other player assigns O or X
' I assign the other token (in case "As")
' send acceptance
'<Acceptance, From:IP Players Name: Accepting player's name> Accept an invitation to play the game.
Call sendGameData(remoteIP, 1, "", "", 0, "")
End If
End Sub
' select X or O
Private Sub selectXorO()
' must select X or O and send select below
If MsgBox("Yes for X, No for O", vbYesNo) = vbYes Then
' we are X
Call sendGameData(remoteIP, 3, "X", "", 0, "")
Call addStatus("Assign: We are X")
myToken = "X"
remoteToken = "O"
Else
' we are O
Call sendGameData(remoteIP, 3, "O", "", 0, "")
Call addStatus("Assign: We are O")
myToken = "O"
remoteToken = "X"
End If
Call startGame
End Sub
' get data from udpGameIN
Private Sub udpGameIN_DataArrival(ByVal bytesTotal As Long)
Dim msg As String
Dim msgType As String
Dim Colour As String
Dim Position As String
Dim Name As String
Dim IP As String
Dim pos As Integer
' get game data
udpGameIN.GetData msg
' parse commands
' get first two chars
msgType = Left(msg, 2)
Select Case (msgType)
Case "In"
' only listen for invitations if status is ready
If mnuReady.Checked = True Then
'In<Invitation, From:IP Players Name: Inviting player's name> Invite a remote player to play the game.
' accept invitation somehow
' pop up a box asking if I want to accept this or not
' set remoteIP to this IP
IP = udpGameIN.RemoteHostIP
'Call addStatus("In | remIP = " & remoteIP)
' set remote name to this name
pos = InStrRev(msg, ":")
Name = Mid(msg, pos + 1, Len(msg) - pos)
'Call addStatus("In | remName = " & remoteName)
Call handleInvitation(IP, Name)
End If
Case "Ac"
'Ac<Acceptance, From:IP Players Name: Accepting player's name> Accept an invitation to play the game.
' set remoteIP to this IP
remoteIP = udpGameIN.RemoteHostIP
'Call addStatus("Ac | remIP = " & remoteIP)
pos = InStrRev(msg, ":")
remoteName = Mid(msg, pos + 2, Len(msg) - pos)
'Call addStatus("Ac | remName =" & remoteName & "X")
' game is accepted, randomly assign a player to go first
If Rnd < 0.5 Then
' first player is me
Call sendGameData(remoteIP, 2, "", "", 0, "")
addStatus ("first player me")
' must now select X or O
remotePlaysFirst = False
Call selectXorO
Else
' first player is remote
Call sendGameData(remoteIP, 2, "", "", 1, "")
addStatus ("first player remote")
remotePlaysFirst = True
End If
Case "As"
'As<Assign First Player, From:IP First Players Name: First players name> Inviting system must select and assign the first player status.
' if I invited, then do this
' if this name is my name, then I play first otherwise remote plays first
pos = InStrRev(msg, ":")
Name = Mid(msg, pos + 2, Len(msg) - pos)
Call addStatus("Assign called=" & Name & "=" & myName & "=")
' if my name is the assigned name then I play first
If myName = Name Then
' I play first
remotePlaysFirst = False
Call selectXorO
Else
remotePlaysFirst = True
addStatus ("remote plays first")
End If
' we are now playing a game
Case "Se"
'Se<Select, Token: x From:IP Players Name: name> Each player selects X or O which is displayed on the remote screen. Token: [X|O]
If Mid(msg, 16, 1) = "X" Then
remoteToken = "X"
myToken = "O"
Else
remoteToken = "O"
myToken = "X"
End If
Call addStatus("My Token:" & myToken & ", Remote Token:" & remoteToken)
' game begins
Call startGame
Case "Pl"
'Pl<Place , Token: x Colour: x Position: xx From:IP Players Name: name > Player places a token on the grid A1 to C3 with Colour [R|G|B]
' NOTE space after place
pos = InStr(msg, "Colour:")
Colour = Mid(msg, pos + 8, 1)
Position = Mid(msg, pos + 20, 2)
addStatus ("T:" & Colour & "=" & Position)
Call placeToken(Colour, Position)
' Remote has played
Case "De"
'De<Delete, Token: x Colour: x Position: xx From:IP Players Name: name > Reports the removal of an illegal token from a system.
Colour = Mid(msg, 26, 1)
Position = Mid(msg, 38, 2)
addStatus ("T:" & Position & "=" & Colour)
Call deleteToken(Position)
Case "Il"
'Il<Illegal, Token: x Colour: x Position: xx From:IP Players Name: name > Identifies an illegal token to the remote system.
Colour = Mid(msg, 27, 1)
Position = Mid(msg, 39, 2)
' place a blue token in this position
Call placeToken("B", Position)
Case "Wi"
'Wi<Winner, From:IP Winners Name: winner's name> Notifies the remote system of game completion.
pos = InStrRev(msg, ":")
Name = Mid(msg, pos + 2, Len(msg) - pos)
' remote sends win msg, this means I have won
' call checkWin to pop up msg and highlight
' not currently using name here, we determine it ourself
Call checkWin
End Select
' add to status
Call addStatus("GameIN < " & msg)
End Sub
' get data from udpStatusIN
Private Sub udpStatusIN_DataArrival(ByVal bytesTotal As Long)
' Auto Discovery Reply, Status: Off Line From:130.102.73.33 Players Name: Fred Nirk
' <Auto Discovery Reply, Status: Status From:IP Players Name: name>
Dim msg As String
Dim Status As String
Dim remoteIP As String
Dim Name As String
Dim pos As Integer
Dim pos2 As Integer
udpStatusIN.GetData msg
' add to status
addStatus ("StatusIN < " & msg)
' parse msg
'pos = InStr(msg, ":")
Status = Mid(msg, 31, 1)
' Off Line or Ready or Busy
' find IP
pos = InStr(msg, "m:")
pos2 = InStrRev(msg, ":")
remoteIP = Mid(msg, pos + 2, (pos2 - 15) - pos)
Name = Mid(msg, pos2 + 2, Len(msg) - pos2)
' add to users list
Call addUser(Status, remoteIP, Name)
End Sub
' send game data
'remoteIP, 0, "X", "R", 0, ""
Private Sub sendGameData(remoteHost As String, msgType As Integer, Token As String, Colour As String, Position As Integer, Winner As String)
Dim data As String
Dim myIP As String
myIP = udpGameOUT.LocalIP
' <Place , Token: x Colour: x Position: xx From:IP Players Name: name > Player places a token on the grid A1 to C3 with Colour [R|G|B]
' x, from:myIP, playersName, myName
Select Case (msgType)
Case 0
'0<Invitation, From:myIP Players Name: Inviting player's myname> Invite a remote player to play the game.
data = "Invitation, From:" & myIP & " Players Name: " & myName
addStatus (data & " RH:" & remoteHost & " MyIP:" & myIP)
Case 1
'1<Acceptance, From:myIP Players Name: Accepting player's myname> Accept an invitation to play the game.
data = "Acceptance, From:" & myIP & " Players Name: " & myName
Case 2
'2<Assign First Player, From:myIP First Players Name: First players myname?> Inviting system must select and assign the first player status.
If Position = 0 Then
' first player is me
data = "Assign First Player, From:" & myIP & " First Players Name: " & myName
addStatus ("Assign:" & myName)
Else
' first player is remote
data = "Assign First Player, From:" & myIP & " First Players Name: " & remoteName
addStatus ("Assign:" & remoteName)
End If
Case 3
'3<Select, Token: x From:myIP Players Name: name> Each player selects X or O which is displayed on the remote screen. Token: [X|O]
data = "Select, Token: " & Token & " From: " & myIP & " Players Name: " & myName
Case 4
'4<Place , Token: x Colour: x Position: xx From:myIP Players Name: myname > Player places a token on the grid A1 to C3 with Colour [R|G|B]
addStatus ("P:" & Token & "=" & Colour)
data = "Place , Token: " & Token & " Colour: " & Colour & " Position: " & gamePositions(Position) & " From:" & myIP & " Players Name: " & myName
Case 5
'5<Delete, Token: x Colour: x Position: xx From:myIP Players Name: myname > Reports the removal of an illegal token from a system.
data = "Delete, Token: " & Token & " Colour: " & Colour & " Position: " & gamePositions(Position) & " From:" & myIP & " Players Name: " & myName
Case 6
'6<Illegal, Token: x Colour: x Position: xx From:myIP Players Name: myname > Identifies an illegal token to the remote system.
data = "Illegal, Token: " & Token & " Colour: " & Colour & " Position: " & gamePositions(Position) & " From:" & myIP & " Players Name: " & myName
Case 7
'7<Winner, From:IP Winners Name: winner's name> Notifies the remote system of game completion.
data = "Winner, From:" & myIP & " Winners Name: " & Winner
End Select
' add to status
' send data
udpGameOUT.remoteHost = remoteHost
'udpGameOUT.remoteHost = "130.102.73.57"
udpGameOUT.SendData data
Call addStatus("GameOUT > " & data & " RH:" & remoteHost & "RP:" & udpGameOUT.RemotePort)
End Sub
' send autoRec data
Private Sub sendAutoRecData(remoteHost As String)
Dim data As String
' IP range: 130.102.73.32 and 130.102.73.64, ie 32 to 64
data = "Auto Discovery Request, For:" & udpAutoRecOUT.LocalIP
' <Auto Discovery Request, For:IP>
udpAutoRecOUT.remoteHost = remoteHost
'udpAutoRecOUT.RemotePort = 6000
udpAutoRecOUT.SendData data
addStatus ("AutoRecOUT > " & data)
End Sub
' send status data
Private Sub sendStatusData(remoteHost As String, Status As String, Name As String)
Dim data As String
data = "Auto Discovery Reply, Status: " & Status & " From:" & udpStatusOUT.LocalIP & " Players Name: " & Name
' <Auto Discovery Reply, Status: Status From:IP Players Name: name>
'Auto Discovery Reply, Status: Ready From:130.102.73.53 Players Name: John Smith
udpStatusOUT.remoteHost = remoteHost
udpStatusOUT.SendData data
Call addStatus("StatusOUT > " & data)
End Sub
' convert token position to array position
Private Function convertPosition(Position As String) As Integer
Dim Multiple As Integer
Select Case (Left(Position, 1))
Case "A"
Multiple = 0
Case "B"
Multiple = 3
Case "C"
Multiple = 6
End Select
Select Case (Right(Position, 1))
Case "1"
convertPosition = 0 + Multiple
Case "2"
convertPosition = 1 + Multiple
Case "3"
convertPosition = 2 + Multiple
End Select
' A1 A2 A3
' 0 1 2
' B1 B2 B3
' 3 4 5
' C1 C2 C3
' 6 7 8
End Function
' form unload
Private Sub Form_Unload(Cancel As Integer)
' close ports
udpAutoRecIN.Close
udpAutoRecOUT.Close
udpStatusIN.Close
udpStatusOUT.Close
udpGameIN.Close
udpGameOUT.Close
End Sub
' add item to status
Private Sub addStatus(Item As String)
' add item to status list
lstStatus.AddItem Item
' select last item in status list (for scrolling)
lstStatus.Selected(lstStatus.ListCount - 1) = True
End Sub
' add item to users list
Private Sub addUser(Status As String, remoteIP As String, Name As String)
' add item to status list
Dim userStatus As String
Select Case (Status)
Case "R"
userStatus = "Ready"
Case "O"
userStatus = "Off Line"
Case "B"
userStatus = "Busy"
End Select
' this does not currently work
If Name <> myName Then
lstUsers.AddItem Name & " (" & userStatus & ") [" & remoteIP & "]"
End If
' select last item in status list (for scrolling)
'lstStatus.Selected(lstStatus.ListCount - 1) = True
End Sub
' add msg to all frames
Private Sub addGameMsg(Item As String)
frmGameFrame.Caption = "Naughts and Crosses (" & Item & ")"
frmAutoFind.Caption = "Naughts and Crosses (" & Item & ")"
frmConfig.Caption = "Naughts and Crosses (" & Item & ")"
End Sub
' game is won
Private Sub gameWon(Name As String)
MsgBox ("Winner is" & Name)
End Sub
' exit
Private Sub mnuExit_Click()
End
End Sub
</textarea>
<br />
Code © Copyright 2004 Ned Martin</p>
<p>04-Jun-2004</p>
</body>
</html>