ruby-tic-tac-toe-crazcalm 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.
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: []