ruby-tic-tac-toe-crazcalm 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NDZkYzYwZDJkYjFhNTNmOGRlYzBmY2JlN2U0ZTgwZTljODNkZjZjYw==
5
+ data.tar.gz: !binary |-
6
+ NmQ2OWNiNzEwN2Y4NjUyNzdkZjZjZGIzZDYxYmJhZTJjOTZhYjM0ZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YWQ0YzY2OGU3MzkwN2ZjYWY4MzU5ZmViZWVlZTQzZDdmMDYxOGFjMzk2YzY4
10
+ MGJjOWFmNzk5YWJiYjJiMjBkYWNhZmM4ZGY3ZTk0MDAwMjMxNTk2YmNhZjAx
11
+ YmY5YTUzOWM4MjYzZjgwMTNkMDYzZDY2YjFhZjE5NmJmYmFkYzI=
12
+ data.tar.gz: !binary |-
13
+ OTNhNDc3ZDAyMzU5MzFiNTIxOWJlZDAxMWE1ZDQ5MzVjZmRhNmEyYjc4M2Iy
14
+ NGVhYzdmNzFiZjI2MTk3OWE3OTkxZTEyNjUzZDdlNzcxZWQ3ZGVkNWQyMjU4
15
+ MTNlNDU2MWQ3MDZkODNhYzgxZGJlZGY2M2UxZDgyYWUyN2E3MmM=
data/bin/TicTacToe.rb ADDED
@@ -0,0 +1,364 @@
1
+ require File.join(File.dirname(__FILE__), 'players')
2
+ require File.join(File.dirname(__FILE__), 'stack')
3
+
4
+ class TicTacToe
5
+
6
+ include GladeGUI
7
+
8
+ DEFAULT_VALUE = " "
9
+ PLAYER1 = "Player One"
10
+ PLAYER2 = "Player Two"
11
+ TITLE = "Tic Tac Toe"
12
+ GAME_OVER = "Game Over"
13
+ ABOUT_PAGE = "\t Author: \tMarcus 'crazcalm' Willock\nSource Code: https://github.com/crazcalm/ruby-tic-tac-toe"
14
+
15
+ def before_show()
16
+ @player1 = Player.new("X", "Player1", false)
17
+ @player2 = Player.new("O", "Player2", true)
18
+ @stack = Stack.new
19
+ @builder["window1"].title = TITLE
20
+ @keys = [DEFAULT_VALUE] * 9
21
+ @builder["player_label"].label = @player1.name
22
+ @one_player_mode = true
23
+ @buttons = [
24
+ @builder["TicTacToe.keys[0]"],
25
+ @builder["TicTacToe.keys[1]"],
26
+ @builder["TicTacToe.keys[2]"],
27
+ @builder["TicTacToe.keys[3]"],
28
+ @builder["TicTacToe.keys[4]"],
29
+ @builder["TicTacToe.keys[5]"],
30
+ @builder["TicTacToe.keys[6]"],
31
+ @builder["TicTacToe.keys[7]"],
32
+ @builder["TicTacToe.keys[8]"]
33
+ ]
34
+
35
+ # Methods used to set up the game
36
+ set_game_mode
37
+ initialize_players
38
+ end
39
+
40
+ def set_game_mode
41
+ @one_player_mode = VR::Dialog.ok_box("'OK' == 1 player mode\n'Cancel' == 2 player mode")
42
+ end
43
+
44
+ def file_select_mode_activate(menuitem, data=nil)
45
+ set_game_mode
46
+ reset_board
47
+ initialize_players
48
+ if current_player_is?(@player2)
49
+ next_player
50
+ end
51
+ end
52
+
53
+ def initialize_players
54
+ if @one_player_mode
55
+ @player1, @player2 = players_factory("human", "bot")
56
+ else
57
+ @player1, @player2 = players_factory("human", "human")
58
+ end
59
+ end
60
+
61
+ def keys__clicked(button)
62
+
63
+ # game logic (High level)
64
+ if valid_move?(button) # Checks for valide move
65
+ make_move(button)
66
+ game_play_steps
67
+ else
68
+ try_again
69
+ end
70
+ end
71
+
72
+ def game_play_steps
73
+ if is_over?
74
+ winner_is
75
+ game_over
76
+ elsif tie?
77
+ tie
78
+ else
79
+ next_player
80
+ end
81
+ end
82
+
83
+ def make_move(button)
84
+ button.label = current_player_mark
85
+ @stack.push(button)
86
+ end
87
+
88
+ def _undo
89
+ if @stack.empty?
90
+ #VR::msg "Cannot undo move"
91
+ else
92
+ button = @stack.pop
93
+ button.label = DEFAULT_VALUE
94
+ #VR::msg "Move has been undone"
95
+ end
96
+ end
97
+
98
+ def file_undo_activate(menuitem, data=nil)
99
+ if @one_player_mode
100
+ _undo
101
+ _undo
102
+ else
103
+ _undo
104
+ unless @stack.empty?
105
+ next_player
106
+ end
107
+ end
108
+ end
109
+
110
+ def current_player_is_a_bot?
111
+ @builder["player_label"].label == @player1.name ? @player1.bot : @player2.bot
112
+ end
113
+
114
+ def current_player_mark
115
+ @builder["player_label"].label == @player1.name ? @player1.move : @player2.move
116
+ end
117
+
118
+ def opponent_player_mark
119
+ @builder['player_label'].label == @player1.name ? @player2.move : @player1.move
120
+ end
121
+
122
+ def board_empty?
123
+ result = true
124
+ @buttons.each do |button|
125
+ unless button.label == DEFAULT_VALUE
126
+ result = false
127
+ end
128
+ end
129
+ result
130
+ end
131
+
132
+ def valid_move?(button)
133
+ result = button.label == DEFAULT_VALUE ? true : false
134
+ result
135
+ end
136
+
137
+ def current_player_is?(player)
138
+ @builder['player_label'].label == player.name ? true : false
139
+ end
140
+
141
+ def next_player
142
+ if @builder['player_label'].label == @player1.name
143
+ @builder['player_label'].label = @player2.name
144
+ else
145
+ @builder['player_label'].label = @player1.name
146
+ end
147
+
148
+ if current_player_is_a_bot?
149
+ bot_move
150
+ end
151
+ end
152
+
153
+ def random_move
154
+ # options
155
+ numbers = (0...9).to_a
156
+ rand_num = numbers.sample
157
+
158
+ # Chooses a valid move
159
+ while not valid_move?(@buttons[rand_num]) do
160
+ #VR::msg "Button #{@buttons[rand_num]} num: #{rand_num}"
161
+ rand_num = numbers.sample
162
+ end
163
+ make_move(@buttons[rand_num])
164
+ end
165
+
166
+ def close_to_winning?(marker)
167
+ result = false
168
+ cases = board_cases
169
+
170
+ cases.each do |items|
171
+
172
+ testing = [items[0].label, items[1].label, items[2].label]
173
+
174
+ if testing.count(marker) == 2 && testing.count(DEFAULT_VALUE) == 1
175
+ result = true
176
+ return result
177
+ end
178
+ end
179
+ result
180
+ end
181
+
182
+ def opponent_is_close_to_winning
183
+ opponent_marker = opponent_player_mark
184
+ close_to_winning?(opponent_marker)
185
+ end
186
+
187
+ def winning_move
188
+ cases = board_cases
189
+ marker = current_player_mark
190
+
191
+ cases.each do |_items|
192
+ items = [_items[0].label, _items[1].label, _items[2].label]
193
+ if items.count(marker) == 2 && items.count(DEFAULT_VALUE) == 1
194
+ index = items.index(DEFAULT_VALUE)
195
+ make_move(_items[index])
196
+ break
197
+ end
198
+ end
199
+ end
200
+
201
+ def stop_opponent_from_winning
202
+ # Iterate through the cases and and try to stop him/her from winning!
203
+ cases = board_cases
204
+ my_marker = current_player_mark
205
+ opponent_marker = opponent_player_mark
206
+
207
+ cases.each do |_items|
208
+ items = [_items[0].label, _items[1].label, _items[2].label]
209
+ if items.count(opponent_marker) == 2 && items.count(DEFAULT_VALUE) == 1
210
+ index = items.index(DEFAULT_VALUE)
211
+ make_move(_items[index])
212
+ break
213
+ end
214
+ end
215
+
216
+ end
217
+
218
+ def can_i_win?
219
+ my_marker = current_player_mark
220
+ close_to_winning?(my_marker)
221
+ end
222
+
223
+ def bot_move
224
+
225
+ #case1: Board is empty
226
+ if board_empty?
227
+ #VR::msg "Board is empty"
228
+ random_move
229
+ elsif can_i_win?
230
+ #VR::msg "Can I Win?"
231
+ winning_move
232
+ elsif opponent_is_close_to_winning # opponent has two in a row
233
+ #VR::msg "MY Oppenent is close to winning"
234
+ stop_opponent_from_winning
235
+ else
236
+ #VR::msg "The else case"
237
+ random_move
238
+ end
239
+
240
+ game_play_steps
241
+ end
242
+
243
+ def tie?
244
+ result = true
245
+
246
+ @buttons.each do |button|
247
+ result = false if button.label == DEFAULT_VALUE
248
+ end
249
+
250
+ result
251
+ end
252
+
253
+ def tie
254
+ VR::msg "Game has ended in a tie!"
255
+ game_over
256
+ end
257
+
258
+ def game_over
259
+ @builder["window1"].title = GAME_OVER
260
+ play_again?
261
+ end
262
+
263
+ # This method is needed to determine of the player would
264
+ # like to play again.
265
+ def play_again?
266
+ play_again = VR::Dialog.ok_box("Would you like to play again")
267
+
268
+ if play_again
269
+ reset_board
270
+ if current_player_is_a_bot?
271
+ bot_move
272
+ end
273
+ else
274
+ quit
275
+ end
276
+ end
277
+
278
+ # This method is needed for when invalid moves are made and
279
+ # the same player must go again.
280
+ # I should add a mistake limit...
281
+ def try_again
282
+ VR::msg "That was in invalide move!"
283
+ end
284
+
285
+ def quit
286
+ #VR::msg "Qutting"
287
+ destroy_window
288
+ end
289
+
290
+ # need to add logic
291
+ def reset_board
292
+ @buttons.each do |button|
293
+ button.label = DEFAULT_VALUE
294
+ end
295
+ @builder["window1"].title = TITLE
296
+ end
297
+
298
+ def winner_is
299
+ VR::msg "The winner is #{@builder['player_label'].label}!"
300
+ end
301
+
302
+ def file_quit_activate(menuitem, data=nil)
303
+ quit
304
+ end
305
+
306
+ def file_about_activate(menuitem, data=nil)
307
+ VR::msg "#{ABOUT_PAGE}"
308
+ end
309
+
310
+ def board_cases
311
+ # Horizontal cases
312
+ case1 = @buttons[0..2]
313
+ case2 = @buttons[3..5]
314
+ case3 = @buttons[6..8]
315
+
316
+ # Vertical cases
317
+ case4 = [@buttons[0], @buttons[3], @buttons[6]]
318
+ case5 = [@buttons[1], @buttons[4], @buttons[7]]
319
+ case6 = [@buttons[2], @buttons[5], @buttons[8]]
320
+
321
+ # Diagonal cases
322
+ case7 = [@buttons[0], @buttons[4], @buttons[8]]
323
+ case8 = [@buttons[2], @buttons[4], @buttons[6]]
324
+
325
+ cases = [case1, case2, case3] +
326
+ [case4, case5, case6] +
327
+ [case7, case8]
328
+
329
+ cases
330
+ end
331
+
332
+ def is_over?
333
+
334
+ # This gets returned
335
+ result = false
336
+
337
+ cases = board_cases
338
+
339
+ cases.each do |items|
340
+ if items[0].label != DEFAULT_VALUE
341
+ if items[0].label == items[1].label && items[0].label == items[2].label
342
+ result = true
343
+ return result
344
+ end
345
+ end
346
+ end
347
+ result
348
+ end
349
+
350
+ def board_state
351
+ state = ""
352
+ @buttons.each_with_index do |item, index|
353
+ if (index + 1) % 3 == 0
354
+ state += " #{item.label}\n"
355
+ state += "---------------\n"
356
+ else
357
+ state += " #{item.label} | "
358
+ end
359
+ end
360
+ VR::msg state
361
+ end
362
+
363
+ end
364
+
@@ -0,0 +1,309 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <interface>
3
+ <requires lib="gtk+" version="2.16"/>
4
+ <!-- interface-naming-policy project-wide -->
5
+ <object class="GtkWindow" id="window1">
6
+ <property name="width_request">180</property>
7
+ <property name="height_request">220</property>
8
+ <property name="visible">True</property>
9
+ <property name="can_focus">False</property>
10
+ <property name="modal">True</property>
11
+ <property name="window_position">center-always</property>
12
+ <property name="default_width">300</property>
13
+ <property name="default_height">200</property>
14
+ <signal name="destroy" handler="destroy_window" swapped="no"/>
15
+ <child>
16
+ <object class="GtkVBox" id="vbox1">
17
+ <property name="visible">True</property>
18
+ <property name="can_focus">False</property>
19
+ <child>
20
+ <object class="GtkMenuBar" id="menubar1">
21
+ <property name="visible">True</property>
22
+ <property name="can_focus">False</property>
23
+ <property name="extension_events">cursor</property>
24
+ <child>
25
+ <object class="GtkMenuItem" id="menuitem1">
26
+ <property name="visible">True</property>
27
+ <property name="can_focus">False</property>
28
+ <property name="use_action_appearance">False</property>
29
+ <property name="label" translatable="yes">_File</property>
30
+ <property name="use_underline">True</property>
31
+ <child type="submenu">
32
+ <object class="GtkMenu" id="menu1">
33
+ <property name="visible">True</property>
34
+ <property name="can_focus">False</property>
35
+ <child>
36
+ <object class="GtkImageMenuItem" id="file_quit">
37
+ <property name="label">gtk-quit</property>
38
+ <property name="visible">True</property>
39
+ <property name="can_focus">False</property>
40
+ <property name="use_action_appearance">False</property>
41
+ <property name="use_underline">True</property>
42
+ <property name="use_stock">True</property>
43
+ <signal name="activate" handler="file_quit_activate" swapped="no"/>
44
+ </object>
45
+ </child>
46
+ <child>
47
+ <object class="GtkMenuItem" id="file_select_mode">
48
+ <property name="visible">True</property>
49
+ <property name="can_focus">False</property>
50
+ <property name="use_action_appearance">False</property>
51
+ <property name="label" translatable="yes">Select Mode</property>
52
+ <property name="use_underline">True</property>
53
+ <signal name="activate" handler="file_select_mode_activate" swapped="no"/>
54
+ </object>
55
+ </child>
56
+ </object>
57
+ </child>
58
+ </object>
59
+ </child>
60
+ <child>
61
+ <object class="GtkMenuItem" id="menuitem2">
62
+ <property name="visible">True</property>
63
+ <property name="can_focus">False</property>
64
+ <property name="use_action_appearance">False</property>
65
+ <property name="label" translatable="yes">_Edit</property>
66
+ <property name="use_underline">True</property>
67
+ <child type="submenu">
68
+ <object class="GtkMenu" id="menu2">
69
+ <property name="visible">True</property>
70
+ <property name="can_focus">False</property>
71
+ <child>
72
+ <object class="GtkImageMenuItem" id="file_undo">
73
+ <property name="label">gtk-undo</property>
74
+ <property name="visible">True</property>
75
+ <property name="can_focus">False</property>
76
+ <property name="use_action_appearance">False</property>
77
+ <property name="use_underline">True</property>
78
+ <property name="use_stock">True</property>
79
+ <signal name="activate" handler="file_undo_activate" swapped="no"/>
80
+ </object>
81
+ </child>
82
+ </object>
83
+ </child>
84
+ </object>
85
+ </child>
86
+ <child>
87
+ <object class="GtkMenuItem" id="menuitem4">
88
+ <property name="visible">True</property>
89
+ <property name="can_focus">False</property>
90
+ <property name="use_action_appearance">False</property>
91
+ <property name="label" translatable="yes">_Help</property>
92
+ <property name="use_underline">True</property>
93
+ <child type="submenu">
94
+ <object class="GtkMenu" id="menu3">
95
+ <property name="visible">True</property>
96
+ <property name="can_focus">False</property>
97
+ <child>
98
+ <object class="GtkImageMenuItem" id="file_about">
99
+ <property name="label">gtk-about</property>
100
+ <property name="visible">True</property>
101
+ <property name="can_focus">False</property>
102
+ <property name="use_action_appearance">False</property>
103
+ <property name="use_underline">True</property>
104
+ <property name="use_stock">True</property>
105
+ <signal name="activate" handler="file_about_activate" swapped="no"/>
106
+ </object>
107
+ </child>
108
+ </object>
109
+ </child>
110
+ </object>
111
+ </child>
112
+ </object>
113
+ <packing>
114
+ <property name="expand">False</property>
115
+ <property name="fill">True</property>
116
+ <property name="position">0</property>
117
+ </packing>
118
+ </child>
119
+ <child>
120
+ <object class="GtkTable" id="table1">
121
+ <property name="visible">True</property>
122
+ <property name="can_focus">False</property>
123
+ <property name="n_rows">3</property>
124
+ <property name="n_columns">3</property>
125
+ <child>
126
+ <object class="GtkButton" id="TicTacToe.keys[0]">
127
+ <property name="label" translatable="yes">button</property>
128
+ <property name="width_request">60</property>
129
+ <property name="height_request">60</property>
130
+ <property name="visible">True</property>
131
+ <property name="can_focus">True</property>
132
+ <property name="receives_default">True</property>
133
+ <property name="use_action_appearance">False</property>
134
+ </object>
135
+ </child>
136
+ <child>
137
+ <object class="GtkButton" id="TicTacToe.keys[1]">
138
+ <property name="label" translatable="yes">button</property>
139
+ <property name="width_request">60</property>
140
+ <property name="height_request">60</property>
141
+ <property name="visible">True</property>
142
+ <property name="can_focus">True</property>
143
+ <property name="receives_default">True</property>
144
+ <property name="use_action_appearance">False</property>
145
+ </object>
146
+ <packing>
147
+ <property name="left_attach">1</property>
148
+ <property name="right_attach">2</property>
149
+ </packing>
150
+ </child>
151
+ <child>
152
+ <object class="GtkButton" id="TicTacToe.keys[2]">
153
+ <property name="label" translatable="yes">button</property>
154
+ <property name="width_request">60</property>
155
+ <property name="height_request">60</property>
156
+ <property name="visible">True</property>
157
+ <property name="can_focus">True</property>
158
+ <property name="receives_default">True</property>
159
+ <property name="use_action_appearance">False</property>
160
+ </object>
161
+ <packing>
162
+ <property name="left_attach">2</property>
163
+ <property name="right_attach">3</property>
164
+ </packing>
165
+ </child>
166
+ <child>
167
+ <object class="GtkButton" id="TicTacToe.keys[3]">
168
+ <property name="label" translatable="yes">button</property>
169
+ <property name="width_request">60</property>
170
+ <property name="height_request">60</property>
171
+ <property name="visible">True</property>
172
+ <property name="can_focus">True</property>
173
+ <property name="receives_default">True</property>
174
+ <property name="use_action_appearance">False</property>
175
+ </object>
176
+ <packing>
177
+ <property name="top_attach">1</property>
178
+ <property name="bottom_attach">2</property>
179
+ </packing>
180
+ </child>
181
+ <child>
182
+ <object class="GtkButton" id="TicTacToe.keys[4]">
183
+ <property name="label" translatable="yes">button</property>
184
+ <property name="width_request">60</property>
185
+ <property name="height_request">60</property>
186
+ <property name="visible">True</property>
187
+ <property name="can_focus">True</property>
188
+ <property name="receives_default">True</property>
189
+ <property name="use_action_appearance">False</property>
190
+ </object>
191
+ <packing>
192
+ <property name="left_attach">1</property>
193
+ <property name="right_attach">2</property>
194
+ <property name="top_attach">1</property>
195
+ <property name="bottom_attach">2</property>
196
+ </packing>
197
+ </child>
198
+ <child>
199
+ <object class="GtkButton" id="TicTacToe.keys[5]">
200
+ <property name="label" translatable="yes">button</property>
201
+ <property name="width_request">60</property>
202
+ <property name="height_request">60</property>
203
+ <property name="visible">True</property>
204
+ <property name="can_focus">True</property>
205
+ <property name="receives_default">True</property>
206
+ <property name="use_action_appearance">False</property>
207
+ </object>
208
+ <packing>
209
+ <property name="left_attach">2</property>
210
+ <property name="right_attach">3</property>
211
+ <property name="top_attach">1</property>
212
+ <property name="bottom_attach">2</property>
213
+ </packing>
214
+ </child>
215
+ <child>
216
+ <object class="GtkButton" id="TicTacToe.keys[6]">
217
+ <property name="label" translatable="yes">button</property>
218
+ <property name="width_request">60</property>
219
+ <property name="height_request">60</property>
220
+ <property name="visible">True</property>
221
+ <property name="can_focus">True</property>
222
+ <property name="receives_default">True</property>
223
+ <property name="use_action_appearance">False</property>
224
+ </object>
225
+ <packing>
226
+ <property name="top_attach">2</property>
227
+ <property name="bottom_attach">3</property>
228
+ </packing>
229
+ </child>
230
+ <child>
231
+ <object class="GtkButton" id="TicTacToe.keys[7]">
232
+ <property name="label" translatable="yes">button</property>
233
+ <property name="width_request">60</property>
234
+ <property name="height_request">60</property>
235
+ <property name="visible">True</property>
236
+ <property name="can_focus">True</property>
237
+ <property name="receives_default">True</property>
238
+ <property name="use_action_appearance">False</property>
239
+ </object>
240
+ <packing>
241
+ <property name="left_attach">1</property>
242
+ <property name="right_attach">2</property>
243
+ <property name="top_attach">2</property>
244
+ <property name="bottom_attach">3</property>
245
+ </packing>
246
+ </child>
247
+ <child>
248
+ <object class="GtkButton" id="TicTacToe.keys[8]">
249
+ <property name="label" translatable="yes">button</property>
250
+ <property name="width_request">60</property>
251
+ <property name="height_request">60</property>
252
+ <property name="visible">True</property>
253
+ <property name="can_focus">True</property>
254
+ <property name="receives_default">True</property>
255
+ <property name="use_action_appearance">False</property>
256
+ </object>
257
+ <packing>
258
+ <property name="left_attach">2</property>
259
+ <property name="right_attach">3</property>
260
+ <property name="top_attach">2</property>
261
+ <property name="bottom_attach">3</property>
262
+ </packing>
263
+ </child>
264
+ </object>
265
+ <packing>
266
+ <property name="expand">True</property>
267
+ <property name="fill">True</property>
268
+ <property name="position">1</property>
269
+ </packing>
270
+ </child>
271
+ <child>
272
+ <object class="GtkHBox" id="hbox1">
273
+ <property name="visible">True</property>
274
+ <property name="can_focus">False</property>
275
+ <child>
276
+ <object class="GtkLabel" id="turn_label">
277
+ <property name="visible">True</property>
278
+ <property name="can_focus">False</property>
279
+ <property name="label" translatable="yes">Turn:</property>
280
+ </object>
281
+ <packing>
282
+ <property name="expand">True</property>
283
+ <property name="fill">True</property>
284
+ <property name="position">0</property>
285
+ </packing>
286
+ </child>
287
+ <child>
288
+ <object class="GtkLabel" id="player_label">
289
+ <property name="visible">True</property>
290
+ <property name="can_focus">False</property>
291
+ <property name="label" translatable="yes">Player</property>
292
+ </object>
293
+ <packing>
294
+ <property name="expand">True</property>
295
+ <property name="fill">True</property>
296
+ <property name="position">1</property>
297
+ </packing>
298
+ </child>
299
+ </object>
300
+ <packing>
301
+ <property name="expand">True</property>
302
+ <property name="fill">True</property>
303
+ <property name="position">2</property>
304
+ </packing>
305
+ </child>
306
+ </object>
307
+ </child>
308
+ </object>
309
+ </interface>
data/bin/players.rb ADDED
@@ -0,0 +1,64 @@
1
+ ##Notes
2
+ # I think that if your opponent is a bot, then the
3
+ # board should make the move for the bot.
4
+ # This makes sense because the board knows the
5
+ # the state of the board, whereas the bot
6
+ # Knows nothing about the board.
7
+
8
+ # Need to create a factory for Players
9
+ def players_factory(player1, player2, player1_marker_x=true)
10
+ players = []
11
+
12
+ # Cases of initializing the players
13
+ if player1_marker_x
14
+
15
+ # Case 1
16
+ if player1 == "human"
17
+ players << Player.new("X", "Player1", false)
18
+ else
19
+ players << Player.new("X", "Player1", true)
20
+ end
21
+
22
+ if player2 == "human"
23
+ players << Player.new("O", "Player2", false)
24
+ else
25
+ players << Player.new("O", "Player2", true)
26
+ end
27
+
28
+ else
29
+ # Case2
30
+ if player1 == "human"
31
+ players << Player.new("O", "Player1", false)
32
+ else
33
+ players << Player.new("O", "Player1", true)
34
+ end
35
+
36
+ if player2 == "human"
37
+ players << Player.new("X", "Player2", false)
38
+ else
39
+ players << Player.new("X", "Player2", true)
40
+ end
41
+ end
42
+
43
+ players
44
+ end
45
+
46
+ class Player
47
+ attr_reader :marker, :bot
48
+ attr_accessor :try_limit, :name
49
+
50
+ def initialize(marker, name="Player1", bot=false)
51
+ @marker = marker
52
+ @try_limit = try_limit
53
+ @name = name
54
+ @bot = bot
55
+ end
56
+
57
+ def move
58
+ @marker
59
+ end
60
+
61
+ def invalid_move
62
+ @try_limit -=1
63
+ end
64
+ end
data/bin/stack.rb ADDED
@@ -0,0 +1,11 @@
1
+ # I think is this how you create a one off class in Ruby.
2
+ # Must try out
3
+ #
4
+ #
5
+ #
6
+ #
7
+ #
8
+ #
9
+
10
+
11
+ class Stack < Array; end
data/main.rb ADDED
@@ -0,0 +1,14 @@
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
+ TicTacToe.new.show
14
+
@@ -0,0 +1,40 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'bin', 'players')
2
+
3
+ require 'test/unit'
4
+
5
+ class PlayerTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @limit = 3
9
+ @name = "Marcus"
10
+ @marker = "X"
11
+ @player = Player.new(@marker, @limit, @name)
12
+ end
13
+
14
+ def test_move
15
+ assert_equal(@marker, @player.move)
16
+ end
17
+
18
+ def test_try_limit
19
+ assert_equal(@limit, @player.try_limit)
20
+ end
21
+
22
+ def test_name
23
+ assert_equal(@name, @player.name)
24
+ end
25
+
26
+ def test_invalid_move
27
+ @player.invalid_move
28
+ assert_equal(@limit - 1, @player.try_limit)
29
+ end
30
+ end
31
+
32
+
33
+ class PlayerFactoryTest < Test::Unit::TestCase
34
+
35
+ def setup
36
+ end
37
+
38
+ def teardown
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'bin', 'stack')
2
+
3
+ require 'test/unit'
4
+
5
+ class StackTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @stack = Stack.new
9
+ @stack << 1
10
+ end
11
+
12
+ def test_push
13
+
14
+ @stack.push(2)
15
+ assert_equal(@stack, [1,2])
16
+ end
17
+
18
+ def test_pop
19
+ item = @stack.pop
20
+ assert_equal(item, 1)
21
+ end
22
+
23
+ def teardown
24
+ @stack.clear
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-tic-tac-toe-crazcalm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Marcus Willock
8
+ autorequire:
9
+ bindir:
10
+ - .
11
+ cert_chain: []
12
+ date: 2015-08-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: vrlib
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ! '>='
19
+ - !ruby/object:Gem::Version
20
+ version: 0.0.1
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ! '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 0.0.1
28
+ - !ruby/object:Gem::Dependency
29
+ name: gtk2
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: 0.0.1
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: 0.0.1
42
+ - !ruby/object:Gem::Dependency
43
+ name: require_all
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: 0.0.1
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: 0.0.1
56
+ description: Tic Tac Toe Game that allows for single player mode and 2 player mode.
57
+ email: craazcalm@gmail.com
58
+ executables:
59
+ - main.rb
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ./main.rb
64
+ - bin/TicTacToe.rb
65
+ - bin/glade/TicTacToe.glade
66
+ - bin/players.rb
67
+ - bin/stack.rb
68
+ - main.rb
69
+ - tests/test_players.rb
70
+ - tests/test_stack.rb
71
+ homepage: http://www.yoursite.org/
72
+ licenses: []
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - .
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project: nowarning
90
+ rubygems_version: 2.4.3
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Tic Tac Toe Clone
94
+ test_files: []