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
data/bin/Board.rb
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
class Board
|
2
|
+
|
3
|
+
include GladeGUI
|
4
|
+
|
5
|
+
def show()
|
6
|
+
@path = File.dirname(__FILE__) + "/"
|
7
|
+
|
8
|
+
load_glade(__FILE__) #loads file, glade/MyClass.glade into @builder
|
9
|
+
@image1 = @path + "blank.jpg"
|
10
|
+
@image2 = @path + "blank.jpg"
|
11
|
+
@image3 = @path + "blank.jpg"
|
12
|
+
@image4 = @path + "blank.jpg"
|
13
|
+
@image5 = @path + "blank.jpg"
|
14
|
+
@image6 = @path + "blank.jpg"
|
15
|
+
@image7 = @path + "blank.jpg"
|
16
|
+
@image8 = @path + "blank.jpg"
|
17
|
+
@image9 = @path + "blank.jpg"
|
18
|
+
@label1 = "Welcome to Tic Tac Toe"
|
19
|
+
#array to store image names; this will make updating the board easier
|
20
|
+
@images = { 'X' => "x.jpg", 'O' => "o.jpg" }
|
21
|
+
set_glade_all() #populates glade controls with insance variables (i.e. Myclass.label1)
|
22
|
+
|
23
|
+
newmatch()
|
24
|
+
show_window()
|
25
|
+
end
|
26
|
+
|
27
|
+
#Human opponent
|
28
|
+
def radiobutton1__clicked(*argv)
|
29
|
+
if @tictactoe.player2.type != 'human'
|
30
|
+
if @tictactoe.movenum == 0 or @tictactoe.winner != ''
|
31
|
+
@tictactoe.SelectPlayers(2)
|
32
|
+
|
33
|
+
if @tictactoe.winner != '' then newgame() end
|
34
|
+
|
35
|
+
#clear all difficulty selectors
|
36
|
+
@builder["checkbutton1"].active = false
|
37
|
+
@builder["checkbutton2"].active = false
|
38
|
+
@builder["checkbutton3"].active = false
|
39
|
+
|
40
|
+
#update player names and status
|
41
|
+
@builder["label4"].text = @tictactoe.player1.name
|
42
|
+
@builder["label3"].text = @tictactoe.player2.name
|
43
|
+
@builder["label5"].text = 'Now playing human. ' + @tictactoe.PrintInstructions()
|
44
|
+
|
45
|
+
#clear and update scores
|
46
|
+
ResetScore()
|
47
|
+
else
|
48
|
+
#toggle back
|
49
|
+
@builder["radiobutton2"].active = true
|
50
|
+
@builder["label5"].text = 'Cannot change opponent during game'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#Computer opponent
|
56
|
+
def radiobutton2__clicked(*argv)
|
57
|
+
if @tictactoe.player2.type != 'computer'
|
58
|
+
if @tictactoe.movenum == 0 or @tictactoe.winner != ''
|
59
|
+
@tictactoe.SelectPlayers(1)
|
60
|
+
if @tictactoe.winner != '' then newgame() end
|
61
|
+
|
62
|
+
#select easy difficulty by default
|
63
|
+
@builder["checkbutton1"].active = true
|
64
|
+
|
65
|
+
#update player names
|
66
|
+
@builder["label4"].text = @tictactoe.player1.name
|
67
|
+
@builder["label3"].text = @tictactoe.player2.name
|
68
|
+
|
69
|
+
#clear and update scores
|
70
|
+
ResetScore()
|
71
|
+
else
|
72
|
+
#toggle back
|
73
|
+
@builder["radiobutton1"].active = true
|
74
|
+
@builder["label5"].text = 'Cannot change opponent during game'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
#Easy difficulty
|
80
|
+
def checkbutton1__clicked(*argv)
|
81
|
+
if @builder["radiobutton2"].active? == false
|
82
|
+
#Only allow player to select difficulty if opponent is computer
|
83
|
+
@builder["checkbutton1"].active = false
|
84
|
+
elsif @builder["checkbutton1"].active? == true and (@tictactoe.movenum == 0 or @tictactoe.winner != '')
|
85
|
+
@builder["checkbutton2"].active = false
|
86
|
+
@builder["checkbutton3"].active = false
|
87
|
+
@tictactoe.SetDifficulty('easy')
|
88
|
+
@builder["label5"].text = 'Now playing computer on easy. '+ @tictactoe.PrintInstructions()
|
89
|
+
elsif not (@tictactoe.movenum == 0 or @tictactoe.winner != '')
|
90
|
+
#toggle back
|
91
|
+
@builder["checkbutton1"].active = (@tictactoe.difficulty == 'easy')
|
92
|
+
@builder["label5"].text = 'Cannot change difficulty during game'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
#Normal difficulty
|
97
|
+
def checkbutton2__clicked(*argv)
|
98
|
+
if @builder["radiobutton2"].active? == false
|
99
|
+
#Only allow player to select difficulty if opponent is computer
|
100
|
+
@builder["checkbutton2"].active = false
|
101
|
+
elsif @builder["checkbutton2"].active? == true and (@tictactoe.movenum == 0 or @tictactoe.winner != '')
|
102
|
+
@builder["checkbutton1"].active = false
|
103
|
+
@builder["checkbutton3"].active = false
|
104
|
+
@tictactoe.SetDifficulty('normal')
|
105
|
+
@builder["label5"].text = 'Now playing computer on normal. '+ @tictactoe.PrintInstructions()
|
106
|
+
elsif not (@tictactoe.movenum == 0 or @tictactoe.winner != '')
|
107
|
+
#toggle back
|
108
|
+
@builder["checkbutton2"].active = (@tictactoe.difficulty == 'normal')
|
109
|
+
@builder["label5"].text = 'Cannot change difficulty during game'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#Hard difficulty
|
114
|
+
def checkbutton3__clicked(*argv)
|
115
|
+
if @builder["radiobutton2"].active? == false
|
116
|
+
#Only allow player to select difficulty if opponent is computer
|
117
|
+
@builder["checkbutton3"].active = false
|
118
|
+
elsif @builder["checkbutton3"].active? == true and (@tictactoe.movenum == 0 or @tictactoe.winner != '')
|
119
|
+
@builder["checkbutton1"].active = false
|
120
|
+
@builder["checkbutton2"].active = false
|
121
|
+
@tictactoe.SetDifficulty('hard')
|
122
|
+
@builder["label5"].text = 'Now playing computer on hard. '+ @tictactoe.PrintInstructions()
|
123
|
+
elsif not (@tictactoe.movenum == 0 or @tictactoe.winner != '')
|
124
|
+
#toggle back
|
125
|
+
@builder["checkbutton3"].active = (@tictactoe.difficulty == 'hard')
|
126
|
+
@builder["label5"].text = 'Cannot change difficulty during game'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
#Menu options
|
131
|
+
def imagemenuitem1__activate(*argv)
|
132
|
+
#Game -> New
|
133
|
+
newgame()
|
134
|
+
end
|
135
|
+
|
136
|
+
def imagemenuitem2__activate(*argv)
|
137
|
+
#Game -> Reset score
|
138
|
+
ResetScore()
|
139
|
+
end
|
140
|
+
|
141
|
+
def imagemenuitem5__activate(*argv)
|
142
|
+
#Game -> Exit
|
143
|
+
destroy_window()
|
144
|
+
end
|
145
|
+
|
146
|
+
def imagemenuitem6__activate(*argv)
|
147
|
+
#Edit -> Undo
|
148
|
+
if @tictactoe.winner == ''
|
149
|
+
#Cannot undo winning move
|
150
|
+
lastmoveindex = @tictactoe.GetLastMove()
|
151
|
+
penultimatemoveindex = @tictactoe.GetPenultimateMove()
|
152
|
+
status = @tictactoe.UndoMove()
|
153
|
+
@builder["label5"].text = status
|
154
|
+
if status == 'Move undone'
|
155
|
+
@builder["image" + (lastmoveindex+1).to_s].file = @path + "blank.jpg"
|
156
|
+
if @tictactoe.player2.type == 'computer'
|
157
|
+
@builder["image" + (penultimatemoveindex+1).to_s].file = @path + "blank.jpg"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
else
|
161
|
+
@builder["label5"].text = 'Cannot undo winning move'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def imagemenuitem10__activate(*argv)
|
166
|
+
#Help -> About
|
167
|
+
modal_win = ModalWindow.new
|
168
|
+
modal_win.show(self)
|
169
|
+
end
|
170
|
+
|
171
|
+
#Move buttons 1 - 9
|
172
|
+
def button1__clicked(*argv)
|
173
|
+
if makemove(1) and @tictactoe.player2.type == 'computer' then
|
174
|
+
computermove()
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def button2__clicked(*argv)
|
179
|
+
if makemove(2) and @tictactoe.player2.type == 'computer' then
|
180
|
+
computermove()
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def button3__clicked(*argv)
|
185
|
+
if makemove(3) and @tictactoe.player2.type == 'computer' then
|
186
|
+
computermove()
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def button4__clicked(*argv)
|
191
|
+
if makemove(4) and @tictactoe.player2.type == 'computer' then
|
192
|
+
computermove()
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def button5__clicked(*argv)
|
197
|
+
if makemove(5) and @tictactoe.player2.type == 'computer' then
|
198
|
+
computermove()
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def button6__clicked(*argv)
|
203
|
+
if makemove(6) and @tictactoe.player2.type == 'computer' then
|
204
|
+
computermove()
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def button7__clicked(*argv)
|
209
|
+
if makemove(7) and @tictactoe.player2.type == 'computer' then
|
210
|
+
computermove()
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def button8__clicked(*argv)
|
215
|
+
if makemove(8) and @tictactoe.player2.type == 'computer' then
|
216
|
+
computermove()
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def button9__clicked(*argv)
|
221
|
+
if makemove(9) and @tictactoe.player2.type == 'computer' then
|
222
|
+
computermove()
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
private
|
228
|
+
|
229
|
+
def newmatch()
|
230
|
+
@tictactoe = TicTacToe.new()
|
231
|
+
@tictactoe.SelectPlayers(2)
|
232
|
+
@builder["label4"].text = @tictactoe.player1.name
|
233
|
+
@builder["label8"].text = @tictactoe.player1.score.to_s
|
234
|
+
|
235
|
+
@builder["label3"].text = @tictactoe.player2.name
|
236
|
+
@builder["label7"].text = @tictactoe.player2.score.to_s
|
237
|
+
|
238
|
+
@builder["label2"].text = @tictactoe.cat.name
|
239
|
+
@builder["label6"].text = @tictactoe.cat.score.to_s
|
240
|
+
|
241
|
+
@builder["label5"].text = 'New game - ' + @tictactoe.PrintInstructions()
|
242
|
+
end
|
243
|
+
|
244
|
+
def newgame()
|
245
|
+
@tictactoe.Reset()
|
246
|
+
@builder["label5"].text = 'New game - ' + @tictactoe.PrintInstructions()
|
247
|
+
@builder["image1"].file = @path + "blank.jpg"
|
248
|
+
@builder["image2"].file = @path + "blank.jpg"
|
249
|
+
@builder["image3"].file = @path + "blank.jpg"
|
250
|
+
@builder["image4"].file = @path + "blank.jpg"
|
251
|
+
@builder["image5"].file = @path + "blank.jpg"
|
252
|
+
@builder["image6"].file = @path + "blank.jpg"
|
253
|
+
@builder["image7"].file = @path + "blank.jpg"
|
254
|
+
@builder["image8"].file = @path + "blank.jpg"
|
255
|
+
@builder["image9"].file = @path + "blank.jpg"
|
256
|
+
if @tictactoe.player2.type == 'computer' and @tictactoe.player2.mark == 'X' then computermove() end
|
257
|
+
end
|
258
|
+
|
259
|
+
def ResetScore()
|
260
|
+
@tictactoe.ClearScore()
|
261
|
+
@builder["label8"].text = @tictactoe.player1.score.to_s
|
262
|
+
@builder["label7"].text = @tictactoe.player2.score.to_s
|
263
|
+
@builder["label6"].text = @tictactoe.cat.score.to_s
|
264
|
+
end
|
265
|
+
|
266
|
+
def makemove(space)
|
267
|
+
if @tictactoe.SpaceAvailable(space)
|
268
|
+
@builder["image"+space.to_s].file = @path + @images[@tictactoe.currentturn]
|
269
|
+
@tictactoe.MakeMove(space)
|
270
|
+
winner = @tictactoe.CheckWinner(space)
|
271
|
+
if winner == ''
|
272
|
+
@tictactoe.SwapTurn()
|
273
|
+
else
|
274
|
+
gameover(winner)
|
275
|
+
end
|
276
|
+
return true
|
277
|
+
else
|
278
|
+
return false
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def computermove()
|
283
|
+
if @tictactoe.winner == ''
|
284
|
+
space = @tictactoe.ComputerMove()
|
285
|
+
@builder["label5"].text = 'Computer chooses ' + space.to_s
|
286
|
+
makemove(space)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def gameover(winner)
|
291
|
+
@tictactoe.UpdateScore(winner)
|
292
|
+
|
293
|
+
@builder["label5"].text = @tictactoe.PrintWinner()
|
294
|
+
@builder["label8"].text = @tictactoe.player1.score.to_s
|
295
|
+
@builder["label7"].text = @tictactoe.player2.score.to_s
|
296
|
+
@builder["label6"].text = @tictactoe.cat.score.to_s
|
297
|
+
|
298
|
+
#After each game, alternate who goes first
|
299
|
+
@tictactoe.SwapPlayers()
|
300
|
+
|
301
|
+
end
|
302
|
+
|
303
|
+
|
304
|
+
end
|
305
|
+
|
data/bin/ModalWindow.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
##
|
3
|
+
# This is a modal window. In glade, you'll see that the "Modal"
|
4
|
+
# setting is true (default in VR). This means that everything
|
5
|
+
# will halt until it finishes.
|
6
|
+
#
|
7
|
+
# Notice that this window doesn't need to set a parent window
|
8
|
+
# because having it close with its parent isn't an issue--the user is
|
9
|
+
# forced to terminate this window first.
|
10
|
+
#
|
11
|
+
# Note: The "Cancel" button on this window is directly linked to the
|
12
|
+
# destroy_window method (in GladeGUI), so you don't need to write your own method to
|
13
|
+
# handle when the Cancel button is clicked.
|
14
|
+
#
|
15
|
+
|
16
|
+
class ModalWindow #(change name)
|
17
|
+
|
18
|
+
include GladeGUI
|
19
|
+
|
20
|
+
def show(parent)
|
21
|
+
load_glade(__FILE__, parent)
|
22
|
+
show_window()
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/bin/blank.jpg
ADDED
Binary file
|