ASP Tic Tac Toe
ASPAlliance.com: The #1 ASP.NET Community
The ASPSmith
Search
D: | Domains | Authors.aspalliance.com | Stevesmith | Articles | ASP Tic Tac Toe
ASP Tic Tac Toe

By Steven Smith

[Play]

This application demonstrates the use of Sessions, state, and database calls to create a simple tic-tac-toe game. There are no ActiveX components in use on either the client or the server. The table involved is quite simple, and was created with the following SQL statement:

	CREATE TABLE TicTacToe 
		(game_id int, 
		player_name VARCHAR(50), 
		player_char VARCHAR(1), 
		turn int DEFAULT 0 
		PRIMARY KEY (game_id,turn), 
		location int)

The source code is rather lengthy, as it includes a number of functions for the computer AI to use to determine where to move next. The complete code is listed below:

   <% OPTION EXPLICIT %>
   <!-- #INCLUDE VIRTUAL="/stevesmith/include/articleformat.asp" -->
   <!-- #INCLUDE VIRTUAL="activeserverpageslib.asp" -->
   <!-- #INCLUDE VIRTUAL="/stevesmith/script.asp" -->
   <%
   Call ArticleHeader("ASP Tic Tac Toe Game","","PRE { color : blue; }")
   %>

   <%
    'Declare Variables
10    Dim Turn 'The current turn
11    Dim PlayerName 'Player's Name
12    Dim Location 'Location
13    Dim GameID 'This Game's Identifier
14    Dim sql 'Variable to hold sql string
15    Dim RS 'Default Recordset Object
16    Dim I 'For Loop Counter
17    Dim Board(9) 'Array holding current locations
18    Dim WinLine(3) 'Array holding winning line
19    Dim Winner 'String holding name of winner
20    Dim WinOrBlockLocation 'Location Index of a winning move
21    Dim PlayerChar 'Player's Character
22    Dim CPUChar 'Computer's Character
23   
24    PlayerChar = "X"
25    CPUChar = "O"
26   
27    'Define Subs
28    Sub UpdatePlayerTurn
29    If Request("GameID") = "New Game" Then
30    'If First Turn, Request will say "New Game"; set Game ID to MAX(game_id) + 1
31    sql = " SELECT MAX(game_id) AS maxid FROM TicTacToe "
32    'Response.Write sql & "<BR>"
33    Set RS = DBQuery(sql)
34    GameID = RS("maxid") + 1
35    If GameID&"" = "" Then GameID = 1
36    sql = " INSERT INTO TicTacToe (game_id,player_name,player_char,turn,location) " & _
37    " VALUES (" & GameID & ",'" & PlayerName & "','X'," & Turn & "," & Location & "); "
38    'Response.Write sql & "<BR>"
39    Set RS = DBQuery(sql)
40    Else
41    GameID = Request("GameID")
42    sql = " INSERT INTO TicTacToe (game_id,player_name,player_char,turn,location) " & _
43    " VALUES (" & GameID & ",'" & PlayerName & "','X'," & Turn & "," & Location & "); "
44    'Response.Write sql & "<BR>"
45    Set RS = DBQuery(sql)
46    End If
47    Turn = Turn + 1
48    End Sub
49   
50    Function CheckLine(a,b,c)
51    If IsNull(Board(a)) OR IsNull(Board(b)) OR IsNull(Board(c)) Then
52    CheckLine = "None"
53    Exit Function
54    End If
55    If Board(a) = "" OR Board(b) = "" OR Board(c) = "" Then
56    CheckLine = "None"
57    Exit Function
58    End If
59    If Board(a) = Board(b) And Board(b) = Board(c) Then
60    CheckLine = Board(a)
61    WinLine(1) = a
62    WinLine(2) = b
63    WinLine(3) = c
64    Exit Function
65    Else
66    CheckLine = "None"
67    Exit Function
68    End If
69    Response.Write "Should not be here."
70    End Function
71   
72    Function Check2of3 (a,b,c,p)
73    'a,b,c are indexes to board locations
74    'p is a character ("X" or "O")
75    If Board(a) = Board(b) And Board(c) = "" And Board(a) = p Then
76    Check2of3 = c
77    Exit Function
78    End If
79    If Board(a) = Board(c) And Board(b) = "" And Board(a) = p Then
80    Check2of3 = b
81    Exit Function
82    End If
83    If Board(b) = Board(c) And Board(a) = "" And Board(b) = p Then
84    Check2of3 = a
85    Exit Function
86    End If
87    Check2of3 = 0
88    End Function
89   
90    Function CheckWin
91    Dim Winner
92    Winner = "None"
93    sql = "SELECT * FROM TicTacToe WHERE game_id = " & GameID & " ORDER BY location "
94    'Response.Write sql & "<BR>"
95    Set RS = DBQuery(sql)
96   
97    'Fill the Board Array
98    While Not RS.EOF
99    'Response.Write RS("location") & " " & RS("player_char") & "<BR>"
100    I = RS("location")
101    Board(I) = RS("player_char")
102    RS.MoveNext
103    Wend
104   
105    'Cannot have a winner before turn 5
106    If Turn < 5 Then
107    CheckWin = Winner
108    Exit Function
109    End If
110   
111    'Check all 8 possible win combos
112    Winner = CheckLine(1,2,3)
113    If Winner <> "None" Then
114    CheckWin = Winner
115    Exit Function
116    End If
117    Winner = CheckLine(4,5,6)
118    If Winner <> "None" Then
119    CheckWin = Winner
120    Exit Function
121    End If
122    Winner = CheckLine(7,8,9)
123    If Winner <> "None" Then
124    CheckWin = Winner
125    Exit Function
126    End If
127    Winner = CheckLine(1,5,9)
128    If Winner <> "None" Then
129    CheckWin = Winner
130    Exit Function
131    End If
132    Winner = CheckLine(3,5,7)
133    If Winner <> "None" Then
134    CheckWin = Winner
135    Exit Function
136    End If
137    Winner = CheckLine(1,4,7)
138    If Winner <> "None" Then
139    CheckWin = Winner
140    Exit Function
141    End If
142    Winner = CheckLine(2,5,8)
143    If Winner <> "None" Then
144    CheckWin = Winner
145    Exit Function
146    End If
147    Winner = CheckLine(3,6,9)
148    If Winner <> "None" Then
149    CheckWin = Winner
150    Exit Function
151    End If
152    CheckWin =Winner
153    End Function
154   
155    Function CanWinOrBlock(character)
156    'Character is either "X" or "O"
157    WinOrBlockLocation = Check2of3(1,2,3,character)
158    If WinOrBlockLocation > 0 Then
159    CanWinOrBlock = True
160    Exit Function
161    End If
162    WinOrBlockLocation = Check2of3(4,5,6,character)
163    If WinOrBlockLocation > 0 Then
164    CanWinOrBlock = True
165    Exit Function
166    End If
167    WinOrBlockLocation = Check2of3(7,8,9,character)
168    If WinOrBlockLocation > 0 Then
169    CanWinOrBlock = True
170    Exit Function
171    End If
172    WinOrBlockLocation = Check2of3(1,5,9,character)
173    If WinOrBlockLocation > 0 Then
174    CanWinOrBlock = True
175    Exit Function
176    End If
177    WinOrBlockLocation = Check2of3(3,5,7,character)
178    If WinOrBlockLocation > 0 Then
179    CanWinOrBlock = True
180    Exit Function
181    End If
182    WinOrBlockLocation = Check2of3(1,4,7,character)
183    If WinOrBlockLocation > 0 Then
184    CanWinOrBlock = True
185    Exit Function
186    End If
187    WinOrBlockLocation = Check2of3(2,5,8,character)
188    If WinOrBlockLocation > 0 Then
189    CanWinOrBlock = True
190    Exit Function
191    End If
192    WinOrBlockLocation = Check2of3(3,6,9,character)
193    If WinOrBlockLocation > 0 Then
194    CanWinOrBlock = True
195    Exit Function
196    End If
197    CanWinOrBlock = False
198    End Function
199   
200    Sub UpdateComputerTurn
201    If CanWinOrBlock(CPUChar) Then
202    Location = WinOrBlockLocation
203    ElseIf CanWinOrBlock(PlayerChar) Then
204    Location = WinOrBlockLocation
205    ElseIf Board(6) = PlayerChar AND Board(8) = PlayerChar AND Board(9) = "" Then
206    Location = 9
207    ElseIf Board(1) = PlayerChar AND Board(9) = PlayerChar AND Board(2) = "" Then
208    Location = 2
209    ElseIf Board(3) = PlayerChar AND Board(7) = PlayerChar AND Board(2) = "" Then
210    Location = 2
211    ElseIf Board(1) = PlayerChar AND Board(8) = PlayerChar AND Board(7) = "" Then
212    Location = 7
213    ElseIf Board(3) = PlayerChar AND Board(8) = PlayerChar AND Board(6) = "" Then
214    Location = 6
215    ElseIf Board(5) = "" Then
216    Location = 5
217    ElseIf Board(1) = "" Then
218    Location = 1
219    ElseIf Board(3) = "" Then
220    Location = 3
221    ElseIf Board(7) = "" Then
222    Location = 7
223    ElseIf Board(9) = "" Then
224    Location = 9
225    ElseIf Board(2) = "" Then
226    Location = 2
227    ElseIf Board(4) = "" Then
228    Location = 4
229    ElseIf Board(6) = "" Then
230    Location = 6
231    ElseIf Board(8) = "" Then
232    Location = 8
233    End If
234    sql = " INSERT INTO TicTacToe (game_id,player_name,player_char,turn,location) " & _
235    " VALUES (" & GameID & ",'Computer','O'," & Turn & "," & Location & "); "
236    'Response.Write sql & "<BR>"
237    Set RS = DBQuery(sql)
238    Turn = Turn + 1
239    End Sub
240   
241   ' InArray takes a value and an array and returns true if the array contains the value
242    Function InArray(element,array)
243    Dim I 'Local
244    For I = 1 To UBound(array)
245    If array(I) = element Then
246    InArray = True
247    Exit Function
248    End If
249    Next
250    InArray = False
251    End Function
252   
253   ' rndcolor returns a random HTML color
254    Function rndcolor()
255    Dim LightDarkRange
256    Dim forered
257    Dim foregreen
258    Dim foreblue
259    Dim color
260    LightDarkRange = 150
261    forered = Int(Rnd * LightDarkRange)
262    foregreen = Int(Rnd * LightDarkRange)
263    foreblue = Int(Rnd * LightDarkRange)
264    color = "#" & cstr(Hex(RGB(forered, foregreen, foreblue)))
265    rndcolor=color
266    End Function
267   
268   
269   %>

270   <H1>Tic-Tac-Toe</H1>
271   <FORM NAME="Form1" ACTION="tictactoegame.asp" METHOD="POST">
272   <%
273    If Request("PlayerName") = "" Then
274   %>

275    Enter your name: <INPUT TYPE=TEXT NAME="PlayerName" VALUE="<%=Session("TicTacToePlayer")%>" MAXLENGTH=50
276    onChange='return checkField(this);'>
277   <BR>
278    <INPUT TYPE=SUBMIT VALUE="Submit">
279    <SCRIPT TYPE="text/javascript">
280    <!--
281    function checkField(s){
282    if (s.value.indexOf("<") > 0 || s.value.indexOf(">") > 0) {
283    alert("You may not use HTML tags.");
284    s.focus();
285    return false;
286    }
287    return true;
288    }
289    document.Form1.PlayerName.focus();
290    // -->
291    </SCRIPT>
292   </FORM>
293   <A HREF="http://<%=Request.ServerVariables("SERVER_NAME")%>/stevesmith/articles/tictactoe.asp">
294   See Source</A>
295   <P>
296   (Game AI last updated 20 August 1999)<BR>
297   (Database Reset 21 Jun 2000)
298   <H2>Score Results:</H2>
299   <%
300    sql = "SELECT Count(game_id) As cnt FROM TicTacToe WHERE location=10"
301    set RS = DBQuery(sql)
302   %>

303   <TABLE BORDER=1>
304   <CAPTION><B><%=RS("cnt")%> Total Games</B></CAPTION>
305   <TR>
306    <TH>Winner</TH>
307    <TH>Total</TH>
308    <TH>Graph</TH>
309   </TR>
310   <%
311    sql = "SELECT player_name,count(player_name) AS cnt FROM TicTacToe WHERE location=10 GROUP BY player_name "
312    set RS = DBQuery(sql)
313    While Not RS.EOF
314    Randomize
315   %>

316    <TR>
317    <TD><%=RS("player_name")%></TD>
318    <TD><%=RS("cnt")%></TD>
319    <TD><table><tr><td width="<%=rs("cnt")%>" height="5" bgcolor="<%= rndcolor() %>"
320    align="bottom"></td></tr></table>
321    </TD>
322    </TR>
323   <%
324    RS.MoveNext
325    Wend
326   %>

327   </TABLE>
328   <%
329    Else
330    Session("TicTacToePlayer") = Request("PlayerName")
331   %>

332   <TABLE WIDTH="100%">
333   <TR>
334    <TD ALIGN=RIGHT>[<A HREF="tictactoegame.asp">New Game</A>]</TD>
335   </TR>
336   </TABLE>
337   <%
338    ' Perform Player Moves(if not first time) and Computer Moves
339    PlayerName = Request("PlayerName")
340    Location = Request("TTT")
341    If Request("TTT") = "" Then
342    'First time, do nothing
343    Turn = 1
344    GameID = "New Game"
345    Winner = "None"
346    Else
347    Turn = Request("Turn")
348    Call UpdatePlayerTurn
349    Winner = CheckWin
350    If Winner <> "None" Then
351    Response.Write "<H2>Game Over</H2><BR>"
352    Response.Write Winner & " has won the game!<BR>"
353    'Store game result(location = 10)
354    sql = " INSERT INTO TicTacToe (game_id,player_name,player_char,turn,location) " & _
355    " VALUES (" & GameID & ",'" & PlayerName & "','X'," & Turn & ",10); "
356    Set RS = DBQuery(sql)
357    End If
358    If Turn < 10 And Winner = "None" Then
359    Call UpdateComputerTurn
360    Winner = CheckWin
361    If Winner <> "None" Then
362    Response.Write "<H2>Game Over</H2><BR>"
363    Response.Write Winner & " has won the game!<BR>"
364    'Store game result(location = 10)
365    sql = " INSERT INTO TicTacToe (game_id,player_name,player_char,turn,location) " & _
366    " VALUES (" & GameID & ",'Computer','X'," & Turn & ",10); "
367    Set RS = DBQuery(sql)
368    End If
369    End If
370    If Turn > 9 And Winner = "None" Then
371    Response.Write "<H2>Game Over</H2><BR>"
372    Response.Write "The game ended in a tie.<BR>"
373    'Store game result(location = 10)
374    sql = " INSERT INTO TicTacToe (game_id,player_name,player_char,turn,location) " & _
375    " VALUES (" & GameID & ",'Tie','X'," & Turn & ",10); "
376    Set RS = DBQuery(sql)
377    End If
378    End If
379   
380   
381   %>

382   <INPUT TYPE="HIDDEN" NAME="PlayerName" VALUE="<%=PlayerName%>">
383   <INPUT TYPE="HIDDEN" NAME="Turn" VALUE="<%=Turn%>">
384   <INPUT TYPE="HIDDEN" NAME="GameID" VALUE="<%=GameID%>">
385   <TABLE BORDER=1 WIDTH="50%">
386   <% If Turn < 10 Then %>
387   <CAPTION>Turn <%=Turn%> - <%=PlayerName%>'s Turn</CAPTION>
388   <% Else %>
389   <CAPTION>Game Over</CAPTION>
390   <%
391    End If
392    If GameID = "New Game" Then GameID = -1
393    sql = "SELECT * FROM TicTacToe WHERE game_id = " & GameID & " ORDER BY location "
394    Set RS = DBQuery(sql)
395    FOR I = 1 To 9
396    If I = 1 Then
397    Response.Write "<TR>"
398    End If
399    If Winner = "None" Then
400    If Not RS.EOF Then
401    If RS("location") = I Then
402   %>

403    <TD ALIGN="CENTER"><B><%=RS("player_char")%></B></TD>
404   <%
405    RS.MoveNext
406    Else
407   %>

408    <TD ALIGN="CENTER"><INPUT TYPE="Radio" NAME="TTT" VALUE="<%=I%>" onClick='document.Form1.submit();'></TD>
409   <%
410    End If 'RS("location") = I
411    Else
412   %>

413    <TD ALIGN="CENTER"><INPUT TYPE="Radio" NAME="TTT" VALUE="<%=I%>" onClick='document.Form1.submit();'></TD>
414   <%
415    End If 'RS.EOF
416    Else 'There is a Winner
417    If Not RS.EOF Then
418    If RS("location") = I Then
419    If InArray(I,WinLine) Then
420   %>

421    <TD ALIGN="CENTER"><FONT COLOR="Red"><B><%=RS("player_char")%></B></FONT></TD>
422   <%
423    Else
424   %>

425    <TD ALIGN="CENTER"><B><%=RS("player_char")%></B></TD>
426   
427   <%
428    End If
429    RS.MoveNext
430    Else
431   %>

432    <TD ALIGN="CENTER">&nbsp;</TD>
433   <%
434    End If 'RS("location") = I
435    Else
436   %>

437    <TD ALIGN="CENTER">&nbsp;</TD>
438   <%
439    End If 'RS.EOF
440    End If 'Winner = None
441    If I = 3 OR I = 6 Then
442    Response.Write "</TR><TR>"
443    End If
444    If I = 9 Then
445    Response.Write "</TR>"
446    End If
447    Next
448   %>

449   </TABLE>
450   </FORM>
451   <%
452    sql = "SELECT * FROM TicTacToe WHERE game_id = " & GameID & " AND location < 10 ORDER BY turn "
453    Set RS = DBQuery(sql)
454    If Not RS.EOF Then
455   %>

456   <TABLE BORDER=1>
457   <CAPTION><B>Game History:</B>
458   <TR>
459    <TH>Player</TH>
460    <TH>Move</TH>
461   </TR>
462   <%
463    While Not RS.EOF
464   %>

465    <TR>
466    <TD><%=RS("player_name")%></TD>
467    <TD><%=RS("location")%></TD>
468    </TR>
469   <%
470    RS.MoveNext
471    Wend
472   %>

473   </TABLE>
474   <% End If 'RS.EOF History Table %>
475   <% End If %>
476   <%
477   Call ArticleFooter()
478   %>

This entire program took me less than a day to write, so there are almost certainly a few bugs or gross inefficiencies in it. If you find any ways to improve the code, please let me know. Also note that DBQuery is a function that is included in my top.asp include file, and its function is rather obvious: it returns a recordset from my default SQL Server database.





ASP.NET Developer's Cookbook, By Steven Smith, Rob Howard, ASPAlliance.com 

ASP.NET By Example, By Steven Smith 




Steven Smith, MCSE + Internet (4.0)
Last Modified: 7/26/2001 9:11:01 PM
History: 1/25/2004 6:10:07 PM