tictactoe-randall 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/Board.rb +305 -0
- data/bin/ModalWindow.rb +25 -0
- data/bin/blank.jpg +0 -0
- data/bin/glade/Board.glade +690 -0
- data/bin/glade/ModalWindow.glade +63 -0
- data/bin/o.jpg +0 -0
- data/bin/player.rb +32 -0
- data/bin/tictactoe.rb +492 -0
- data/bin/x.jpg +0 -0
- data/tictactoe_randall +13 -0
- metadata +104 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<interface>
|
3
|
+
<requires lib="gtk+" version="2.16"/>
|
4
|
+
<!-- interface-naming-policy project-wide -->
|
5
|
+
<object class="GtkWindow" id="window1">
|
6
|
+
<property name="visible">True</property>
|
7
|
+
<property name="title" translatable="yes">About Tic Tac Toe</property>
|
8
|
+
<property name="modal">True</property>
|
9
|
+
<property name="window_position">center</property>
|
10
|
+
<signal name="destroy" handler="destroy_window"/>
|
11
|
+
<child>
|
12
|
+
<object class="GtkHBox" id="hbox1">
|
13
|
+
<property name="visible">True</property>
|
14
|
+
<child>
|
15
|
+
<object class="GtkVBox" id="vbox1">
|
16
|
+
<property name="visible">True</property>
|
17
|
+
<child>
|
18
|
+
<object class="GtkLabel" id="label1">
|
19
|
+
<property name="visible">True</property>
|
20
|
+
<property name="label" translatable="yes"><big><big>Tic Tac Toe 0.0.1</big></big>
|
21
|
+
Created by Randall Reed in 2013 using VisualRuby, a Ruby GUI builder. To create your own Ruby GUIs, visit visualruby.net.
|
22
|
+
</property>
|
23
|
+
<property name="use_markup">True</property>
|
24
|
+
<property name="wrap">True</property>
|
25
|
+
</object>
|
26
|
+
<packing>
|
27
|
+
<property name="padding">20</property>
|
28
|
+
<property name="position">0</property>
|
29
|
+
</packing>
|
30
|
+
</child>
|
31
|
+
<child>
|
32
|
+
<object class="GtkHButtonBox" id="hbuttonbox1">
|
33
|
+
<property name="visible">True</property>
|
34
|
+
<child>
|
35
|
+
<object class="GtkButton" id="cancelButton">
|
36
|
+
<property name="label" translatable="yes">Ok</property>
|
37
|
+
<property name="visible">True</property>
|
38
|
+
<property name="can_focus">True</property>
|
39
|
+
<property name="receives_default">True</property>
|
40
|
+
<signal name="clicked" handler="destroy_window"/>
|
41
|
+
</object>
|
42
|
+
<packing>
|
43
|
+
<property name="expand">False</property>
|
44
|
+
<property name="fill">False</property>
|
45
|
+
<property name="position">0</property>
|
46
|
+
</packing>
|
47
|
+
</child>
|
48
|
+
</object>
|
49
|
+
<packing>
|
50
|
+
<property name="padding">10</property>
|
51
|
+
<property name="position">1</property>
|
52
|
+
</packing>
|
53
|
+
</child>
|
54
|
+
</object>
|
55
|
+
<packing>
|
56
|
+
<property name="padding">20</property>
|
57
|
+
<property name="position">0</property>
|
58
|
+
</packing>
|
59
|
+
</child>
|
60
|
+
</object>
|
61
|
+
</child>
|
62
|
+
</object>
|
63
|
+
</interface>
|
data/bin/o.jpg
ADDED
Binary file
|
data/bin/player.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
class Player
|
2
|
+
attr_reader :score
|
3
|
+
attr_reader :type
|
4
|
+
attr_reader :name
|
5
|
+
attr_reader :mark
|
6
|
+
def initialize(type, name, mark)
|
7
|
+
@name = name
|
8
|
+
@type = type
|
9
|
+
@score = 0
|
10
|
+
@mark = mark
|
11
|
+
end
|
12
|
+
|
13
|
+
def AddScore()
|
14
|
+
@score += 1
|
15
|
+
end
|
16
|
+
|
17
|
+
def ClearScore()
|
18
|
+
@score = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def SwapMark()
|
22
|
+
if @mark == 'X'
|
23
|
+
@mark = 'O'
|
24
|
+
else
|
25
|
+
@mark = 'X'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def Print()
|
30
|
+
print name + ", type: " + type + ", score: " + score.to_s
|
31
|
+
end
|
32
|
+
end
|
data/bin/tictactoe.rb
ADDED
@@ -0,0 +1,492 @@
|
|
1
|
+
class TicTacToe
|
2
|
+
|
3
|
+
#Read access to some class variables
|
4
|
+
attr_reader :winner
|
5
|
+
attr_reader :movenum
|
6
|
+
attr_reader :player1
|
7
|
+
attr_reader :player2
|
8
|
+
attr_reader :cat
|
9
|
+
attr_reader :currentturn
|
10
|
+
attr_reader :difficulty
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
#Set starting values for class variables
|
14
|
+
#@board = ['_','_','_','_','_','_','_','_','_']
|
15
|
+
@board = Array.new(9,'_')
|
16
|
+
#Keep track of current player
|
17
|
+
@currentturn = 'X'
|
18
|
+
@winner = ''
|
19
|
+
@movenum = 0
|
20
|
+
@lastmoveindex = -1
|
21
|
+
@penultimatemoveindex = -1
|
22
|
+
@difficulty = 'easy'
|
23
|
+
@movesuccess = false
|
24
|
+
@alternate = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def Reset
|
28
|
+
#Reset game specific variables
|
29
|
+
@board = Array.new(9,'_')
|
30
|
+
@currentturn = 'X'
|
31
|
+
@winner = ''
|
32
|
+
@movenum = 0
|
33
|
+
@lastmoveindex = -1
|
34
|
+
@playagain = true
|
35
|
+
end
|
36
|
+
|
37
|
+
def PrintInstructions
|
38
|
+
if player1.mark == 'X'
|
39
|
+
return player1.name + ' (X) goes first'
|
40
|
+
else
|
41
|
+
return player2.name + ' (X) goes first'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def SelectPlayers(numplayers)
|
46
|
+
if @movenum == 0 or @winner != '' then
|
47
|
+
if numplayers == 1
|
48
|
+
@player1 = Player.new('human','Player','X')
|
49
|
+
@player2 = Player.new('computer','Computer','O')
|
50
|
+
@cat = Player.new('cat', 'Cat', 'C')
|
51
|
+
elsif numplayers == 2
|
52
|
+
@player1 = Player.new('human', 'Player 1','X')
|
53
|
+
@player2 = Player.new('human', 'Player 2','O')
|
54
|
+
@cat = Player.new('cat', 'Cat', 'C')
|
55
|
+
else
|
56
|
+
raise 'Invalid number of players: ' + numplayers
|
57
|
+
end
|
58
|
+
else
|
59
|
+
raise "Cannot change players during game"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def SwapPlayers
|
64
|
+
@player1.SwapMark()
|
65
|
+
@player2.SwapMark()
|
66
|
+
end
|
67
|
+
|
68
|
+
def UpdateScore(winner)
|
69
|
+
#Add a point to the winning player's score
|
70
|
+
if @player1.mark == winner
|
71
|
+
@player1.AddScore()
|
72
|
+
elsif @player2.mark == winner
|
73
|
+
@player2.AddScore()
|
74
|
+
else
|
75
|
+
@cat.AddScore()
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def ClearScore
|
80
|
+
@player1.ClearScore
|
81
|
+
@player2.ClearScore
|
82
|
+
@cat.ClearScore
|
83
|
+
end
|
84
|
+
|
85
|
+
def SetDifficulty(difficulty)
|
86
|
+
if @movenum == 0 or @winner != ''
|
87
|
+
case difficulty.downcase
|
88
|
+
when 'easy'
|
89
|
+
@difficulty = 'easy'
|
90
|
+
when 'normal'
|
91
|
+
@difficulty = 'normal'
|
92
|
+
when 'hard'
|
93
|
+
@difficulty = 'hard'
|
94
|
+
else
|
95
|
+
raise 'Only valid difficulties are easy, medium, and hard'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
#Print outcome of game to players
|
101
|
+
def PrintWinner
|
102
|
+
if @winner == 'C'
|
103
|
+
return "Sorry, cat game."
|
104
|
+
else
|
105
|
+
if @player1.mark == @winner
|
106
|
+
return "Congratulations! " + @player1.name + " wins!"
|
107
|
+
elsif @player2.mark == @winner and @player2.type == 'human'
|
108
|
+
return "Congratulations! " + @player2.name + " wins!"
|
109
|
+
elsif @player2.mark == @winner and @player2.type == 'computer'
|
110
|
+
#1 player, 'O' won. Do not congratulate player on computer victory.
|
111
|
+
return "Sorry, " + player2.name + " wins."
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def SwapTurn()
|
117
|
+
#Toggle current player
|
118
|
+
if @currentturn == 'X'
|
119
|
+
@currentturn = 'O'
|
120
|
+
else
|
121
|
+
@currentturn = 'X'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def SpaceAvailable(move)
|
126
|
+
if @winner == ''
|
127
|
+
return @board[move-1] == '_'
|
128
|
+
else
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def MakeMove(move)
|
134
|
+
#store up to 2 moves for undo
|
135
|
+
@penultimatemoveindex = @lastmoveindex
|
136
|
+
@lastmoveindex = move-1
|
137
|
+
#Array index is one less than move space
|
138
|
+
if @board[@lastmoveindex] == '_'
|
139
|
+
@board[@lastmoveindex] = @currentturn
|
140
|
+
|
141
|
+
#Increment move counter
|
142
|
+
@movenum += 1
|
143
|
+
@movesuccess = true
|
144
|
+
else
|
145
|
+
#Do not allow player to choose space that has already been played
|
146
|
+
@movesuccess = false
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def ComputerMove()
|
151
|
+
if @player2.type == 'computer' and @player2.mark == 'O'
|
152
|
+
return ComputerMoveO()
|
153
|
+
elsif @player2.type == 'computer' and @player2.mark == 'X'
|
154
|
+
return ComputerMoveX()
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def GetLastMove()
|
159
|
+
return @lastmoveindex
|
160
|
+
end
|
161
|
+
|
162
|
+
def GetPenultimateMove()
|
163
|
+
return @penultimatemoveindex
|
164
|
+
end
|
165
|
+
|
166
|
+
def UndoMove()
|
167
|
+
if @lastmoveindex == -1
|
168
|
+
return "Move cannot be undone"
|
169
|
+
else
|
170
|
+
if @player2.type=='computer'
|
171
|
+
if @player2.mark == 'O' or (@player2.mark == 'X' and @movenum > 1)
|
172
|
+
#Undo computer and player move
|
173
|
+
#Clear 2 moves from board
|
174
|
+
@board[@lastmoveindex] = '_'
|
175
|
+
@board[@penultimatemoveindex] = '_'
|
176
|
+
@lastmoveindex = -1
|
177
|
+
@penultimatemoveindex = -1
|
178
|
+
@movenum -= 2
|
179
|
+
else
|
180
|
+
return "Move cannot be undone"
|
181
|
+
end
|
182
|
+
else
|
183
|
+
#Undo player move only
|
184
|
+
#Clear move
|
185
|
+
@board[@lastmoveindex] = '_'
|
186
|
+
@lastmoveindex = -1
|
187
|
+
#Decrement move counter
|
188
|
+
@movenum -= 1
|
189
|
+
|
190
|
+
#Toggle current player
|
191
|
+
if @currentturn == 'X'
|
192
|
+
@currentturn = 'O'
|
193
|
+
else
|
194
|
+
@currentturn = 'X'
|
195
|
+
end
|
196
|
+
end
|
197
|
+
return "Move undone"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def ShowComputerMove(move)
|
202
|
+
#Need to increment index to match normal layout
|
203
|
+
if @keyboard
|
204
|
+
movestring = @keyboardboard[move]
|
205
|
+
elsif @numpad
|
206
|
+
movestring = @numpadboard[move]
|
207
|
+
else
|
208
|
+
movestring = (move+1).to_s
|
209
|
+
end
|
210
|
+
return "Computer chooses " + movestring
|
211
|
+
end
|
212
|
+
|
213
|
+
def CheckWinner(lastmove)
|
214
|
+
lastmoveindex = lastmove - 1
|
215
|
+
if @movenum < 3
|
216
|
+
#Game cannot end in less than 5 moves
|
217
|
+
#However, computer uses this to check for blocks on move 4
|
218
|
+
return ''
|
219
|
+
else
|
220
|
+
row = lastmoveindex / 3
|
221
|
+
#Determine row to check using integer division
|
222
|
+
if (row == 0 and CheckWinTopRow()) or (row == 1 and CheckWinCenterRow()) or (row == 2 and CheckWinBottomRow())
|
223
|
+
@winner = @currentturn
|
224
|
+
end
|
225
|
+
|
226
|
+
column = lastmoveindex % 3
|
227
|
+
#Determine column to check
|
228
|
+
if (column == 0 and CheckWinLeftColumn()) or (column == 1 and CheckWinMiddleColumn()) or (column == 2 and CheckWinRightColumn())
|
229
|
+
@winner = @currentturn
|
230
|
+
end
|
231
|
+
|
232
|
+
if lastmoveindex % 2 == 0
|
233
|
+
#Determine diagonals to check
|
234
|
+
if lastmoveindex % 4 == 2
|
235
|
+
if CheckWinBottomLeftToTopRight() then @winner = @currentturn end
|
236
|
+
elsif lastmoveindex != 4 and lastmoveindex %4 == 0
|
237
|
+
if CheckWinTopLeftToBottomRight() then @winner = @currentturn end
|
238
|
+
elsif lastmoveindex == 4
|
239
|
+
if CheckWinTopLeftToBottomRight() or CheckWinBottomLeftToTopRight()
|
240
|
+
@winner = @currentturn
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
if @movenum == 9 and @winner == ''
|
247
|
+
#Game over, no winner; cat's game
|
248
|
+
@winner = 'C'
|
249
|
+
end
|
250
|
+
|
251
|
+
return @winner
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
private
|
256
|
+
|
257
|
+
def ComputerMoveX()
|
258
|
+
|
259
|
+
if @difficulty == 'easy'
|
260
|
+
#Easy computer moves randomly
|
261
|
+
move = RandomMove()
|
262
|
+
elsif @difficulty == 'normal'
|
263
|
+
#Normal computer moves randomly early on, but looks for wins or blocks as the game progresses
|
264
|
+
if @movenum < 3
|
265
|
+
move = RandomMove()
|
266
|
+
else
|
267
|
+
#Check for winning move first
|
268
|
+
move = FindWinningMove()
|
269
|
+
if move == -1
|
270
|
+
#No winning move available, try block next
|
271
|
+
move = FindBlockingMove()
|
272
|
+
if move == -1
|
273
|
+
move = RandomMove()
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
elsif @difficulty == 'hard'
|
278
|
+
#Hard computer knows what move to make in every situation, until cat game is guaranteed
|
279
|
+
case movenum
|
280
|
+
when 0
|
281
|
+
move = 0
|
282
|
+
when 2
|
283
|
+
case @lastmoveindex
|
284
|
+
when 1,3,5,7
|
285
|
+
move = 4
|
286
|
+
when 2,4,6
|
287
|
+
move = 8
|
288
|
+
else
|
289
|
+
move = 2
|
290
|
+
end
|
291
|
+
when 4
|
292
|
+
move = FindWinningMove()
|
293
|
+
if move == -1
|
294
|
+
move = FindBlockingMove()
|
295
|
+
if move == -1
|
296
|
+
move = 6
|
297
|
+
end
|
298
|
+
end
|
299
|
+
else
|
300
|
+
move = FindWinningMove()
|
301
|
+
if move == -1
|
302
|
+
move = FindBlockingMove()
|
303
|
+
if move == -1
|
304
|
+
move = RandomMove()
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
return move + 1
|
310
|
+
end
|
311
|
+
|
312
|
+
def ComputerMoveO()
|
313
|
+
if @winner == ''
|
314
|
+
if @difficulty == 'easy'
|
315
|
+
#Easy computer moves randomly
|
316
|
+
move = RandomMove()
|
317
|
+
elsif @difficulty == 'normal'
|
318
|
+
#Normal computer moves randomly early on, but looks for wins or blocks as the game progresses
|
319
|
+
if @movenum < 3
|
320
|
+
move = RandomMove()
|
321
|
+
else
|
322
|
+
#Check for winning move first
|
323
|
+
move = FindWinningMove()
|
324
|
+
if move == -1
|
325
|
+
#No winning move available, try block next
|
326
|
+
move = FindBlockingMove()
|
327
|
+
if move == -1 then
|
328
|
+
move = RandomMove()
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
elsif @difficulty == 'hard'
|
333
|
+
#Hard computer knows what move to make in every situation, until cat game is guaranteed
|
334
|
+
move = -1
|
335
|
+
if @movenum == 1
|
336
|
+
if @board[4] == '_'
|
337
|
+
move = 4
|
338
|
+
else
|
339
|
+
move = 0
|
340
|
+
end
|
341
|
+
elsif @movenum == 3
|
342
|
+
if @board[4] == 'X'
|
343
|
+
if @board[0] != '_' and @board[8] != '_'
|
344
|
+
move = 2
|
345
|
+
elsif @board[2] != '_' and @board[6] != '_'
|
346
|
+
move = 0
|
347
|
+
end
|
348
|
+
else
|
349
|
+
if (@board[1] == 'X' and @board[5] == 'X') or (@board[3] == 'X' and @board[7] == 'X')
|
350
|
+
move = 0
|
351
|
+
elsif (@board[3] == 'X' and @board[8] == 'X') or (@board[5] == 'X' and @board[6] == 'X') or (@board[3] == 'X' and @board[5] == 'X') or (@board[0] == 'X' and @board[8] == 'X') or (@board[2] == 'X' and @board[6] == 'X')
|
352
|
+
move = 1
|
353
|
+
elsif (@board[1] == 'X' and @board[3] == 'X') or (@board[5] == 'X' and @board[7] == 'X')
|
354
|
+
move = 2
|
355
|
+
elsif (@board[2] == 'X' and @board[7] == 'X') or (@board[1] == 'X' and @board[8] == 'X') or (@board[1] == 'X' and @board[7] == 'X')
|
356
|
+
move = 3
|
357
|
+
elsif (@board[1] == 'X' and @board[6] == 'X') or (@board[0] == 'X' and @board[7] == 'X')
|
358
|
+
move = 5
|
359
|
+
elsif (@board[0] == 'X' and @board[5] == 'X') or (@board[2] == 'X' and @board[3] == 'X')
|
360
|
+
move = 7
|
361
|
+
end
|
362
|
+
end
|
363
|
+
elsif @movenum == 5
|
364
|
+
if (@board[4] == 'O' and @board[5] == 'X' and @board[7] == 'X' and @board[1] != '_' and @board[3] != '_')
|
365
|
+
move = 0
|
366
|
+
end
|
367
|
+
end
|
368
|
+
if move == -1
|
369
|
+
#Check for winning move first
|
370
|
+
move = FindWinningMove()
|
371
|
+
if move == -1
|
372
|
+
#No winning move available, try block next
|
373
|
+
move = FindBlockingMove()
|
374
|
+
if move == -1 then
|
375
|
+
#puts "Select side"
|
376
|
+
if @board[1] == '_'
|
377
|
+
move = 1
|
378
|
+
elsif @board[3] == '_'
|
379
|
+
move = 3
|
380
|
+
elsif @board[5] == '_'
|
381
|
+
move = 5
|
382
|
+
elsif @board[7] == '_'
|
383
|
+
move = 7
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
|
390
|
+
end
|
391
|
+
return (move+1)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def FindWinningMove()
|
396
|
+
#Pretend O went in any available square and check for win
|
397
|
+
for i in 0..8
|
398
|
+
if @board[i] == '_'
|
399
|
+
@board[i] = @player2.mark
|
400
|
+
if CheckWinner(i+1) == @player2.mark
|
401
|
+
@board[i] = '_'
|
402
|
+
@winner = ''
|
403
|
+
return i
|
404
|
+
end
|
405
|
+
@board[i] = '_'
|
406
|
+
end
|
407
|
+
end
|
408
|
+
return -1
|
409
|
+
end
|
410
|
+
|
411
|
+
def FindBlockingMove()
|
412
|
+
#Pretend X went in any available square and check for win; that space necessitates a block
|
413
|
+
for i in 0..8
|
414
|
+
if @board[i] == '_'
|
415
|
+
@board[i] = @player1.mark
|
416
|
+
#CheckWinner returns currentturn, so it will still be player2
|
417
|
+
if CheckWinner(i+1) == @player2.mark
|
418
|
+
@board[i] = '_'
|
419
|
+
@winner = ''
|
420
|
+
return i
|
421
|
+
end
|
422
|
+
@board[i] = '_'
|
423
|
+
end
|
424
|
+
end
|
425
|
+
return -1
|
426
|
+
end
|
427
|
+
|
428
|
+
def RandomMove()
|
429
|
+
#Select random number 0-8 inclusive; this will match board index
|
430
|
+
move = rand(9)
|
431
|
+
while @board[move] != '_'
|
432
|
+
move = rand(9)
|
433
|
+
end
|
434
|
+
return move
|
435
|
+
end
|
436
|
+
|
437
|
+
def CheckWinLeftColumn()
|
438
|
+
#[0 _ _]
|
439
|
+
#[3 _ _]
|
440
|
+
#[6 _ _]
|
441
|
+
return ((@board[0] == @board[3]) and (@board[0] == @board[6]))
|
442
|
+
end
|
443
|
+
|
444
|
+
def CheckWinMiddleColumn()
|
445
|
+
#[_ 1 _]
|
446
|
+
#[_ 4 _]
|
447
|
+
#[_ 7 _]
|
448
|
+
return ((@board[4] == @board[1]) and (@board[4] == @board[7]))
|
449
|
+
end
|
450
|
+
|
451
|
+
def CheckWinRightColumn()
|
452
|
+
#[_ _ 2]
|
453
|
+
#[_ _ 5]
|
454
|
+
#[_ _ 8]
|
455
|
+
return ((@board[8] == @board[2]) and (@board[8] == @board[5]))
|
456
|
+
end
|
457
|
+
|
458
|
+
def CheckWinTopRow()
|
459
|
+
#[0 1 2]
|
460
|
+
#[_ _ _]
|
461
|
+
#[_ _ _]
|
462
|
+
return ((@board[0] == @board[1]) and (@board[0] == @board[2]))
|
463
|
+
end
|
464
|
+
|
465
|
+
def CheckWinCenterRow()
|
466
|
+
#[_ _ _]
|
467
|
+
#[3 4 5]
|
468
|
+
#[_ _ _]
|
469
|
+
return ((@board[4] == @board[3]) and (@board[4] == @board[5]))
|
470
|
+
end
|
471
|
+
|
472
|
+
def CheckWinBottomRow()
|
473
|
+
#[_ _ _]
|
474
|
+
#[_ _ _]
|
475
|
+
#[6 7 8]
|
476
|
+
return ((@board[8] == @board[7]) and (@board[8] == @board[6]))
|
477
|
+
end
|
478
|
+
|
479
|
+
def CheckWinTopLeftToBottomRight()
|
480
|
+
#[0 _ _]
|
481
|
+
#[_ 4 _]
|
482
|
+
#[_ _ 8]
|
483
|
+
return ((@board[4] == @board[0]) and (@board[4] == @board[8]))
|
484
|
+
end
|
485
|
+
|
486
|
+
def CheckWinBottomLeftToTopRight()
|
487
|
+
#[_ _ 2]
|
488
|
+
#[_ 4 _]
|
489
|
+
#[6 _ _]
|
490
|
+
return ((@board[4] == @board[2]) and (@board[4] == @board[6]))
|
491
|
+
end
|
492
|
+
end
|
data/bin/x.jpg
ADDED
Binary file
|
data/tictactoe_randall
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vrlib'
|
4
|
+
|
5
|
+
#make program output in real time so errors visible in VR.
|
6
|
+
STDOUT.sync = true
|
7
|
+
STDERR.sync = true
|
8
|
+
|
9
|
+
#everything in these directories will be included
|
10
|
+
my_path = File.expand_path(File.dirname(__FILE__))
|
11
|
+
require_all Dir.glob(my_path + "/bin/**/*.rb")
|
12
|
+
|
13
|
+
board = Board.new.show
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tictactoe-randall
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Randall Reed
|
9
|
+
autorequire:
|
10
|
+
bindir:
|
11
|
+
- .
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-11-19 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: vrlib
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.0.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 0.0.1
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: gtk2
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.0.1
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.0.1
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: require_all
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.0.1
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.0.1
|
63
|
+
description:
|
64
|
+
email:
|
65
|
+
executables:
|
66
|
+
- tictactoe_randall
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- bin/Board.rb
|
71
|
+
- bin/ModalWindow.rb
|
72
|
+
- bin/player.rb
|
73
|
+
- bin/tictactoe.rb
|
74
|
+
- bin/glade/Board.glade
|
75
|
+
- bin/glade/ModalWindow.glade
|
76
|
+
- bin/blank.jpg
|
77
|
+
- bin/o.jpg
|
78
|
+
- bin/x.jpg
|
79
|
+
- ./tictactoe_randall
|
80
|
+
homepage:
|
81
|
+
licenses: []
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- .
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project: nowarning
|
100
|
+
rubygems_version: 1.8.24
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: GUI Tic Tac Toe game.
|
104
|
+
test_files: []
|