1
1
class TTT
2
- def initialize
3
- @three_board = [ [ 1 , 2 , 3 ] , [ 4 , 5 , 6 ] , [ 7 , 8 , 9 ] ]
4
- @flat_3_board = @three_board . flatten
5
-
6
- @four_board = [ [ 1 , 2 , 3 , 4 ] , [ 5 , 6 , 7 , 8 ] ,
7
- [ 9 , 10 , 11 , 12 ] , [ 13 , 14 , 15 , 16 ] ]
8
- @flat_4_board = @four_board . flatten
9
-
10
- @p1 , @p2 , @computer , @human , @turn , @choice = nil
11
- @board = @three_board
2
+ def initialize
3
+ @player_1 , @player_2 , @computer , @human , @turn , @dimension , @board = nil
12
4
end
13
5
14
6
def print_three_board
15
- puts "\n #{ @flat_3_board [ 0 ] } | #{ @flat_3_board [ 1 ] } | #{ @flat_3_board [ 2 ] } " ,
7
+ puts "\n #{ @board [ 0 ] } | #{ @board [ 1 ] } | #{ @board [ 2 ] } " ,
16
8
"----------" ,
17
- " #{ @flat_3_board [ 3 ] } | #{ @flat_3_board [ 4 ] } | #{ @flat_3_board [ 5 ] } " ,
9
+ " #{ @board [ 3 ] } | #{ @board [ 4 ] } | #{ @board [ 5 ] } " ,
18
10
"----------" ,
19
- " #{ @flat_3_board [ 6 ] } | #{ @flat_3_board [ 7 ] } | #{ @flat_3_board [ 8 ] } "
11
+ " #{ @board [ 6 ] } | #{ @board [ 7 ] } | #{ @board [ 8 ] } "
20
12
end
21
13
22
14
def print_four_board
23
- puts "\n #{ @flat_4_board [ 0 ] } | #{ @flat_4_board [ 1 ] } | #{ @flat_4_board [ 2 ] } | #{ @flat_4_board [ 3 ] } " ,
15
+ puts "\n #{ @board [ 0 ] } | #{ @board [ 1 ] } | #{ @board [ 2 ] } | #{ @board [ 3 ] } " ,
24
16
"-------------------" ,
25
- " #{ @flat_4_board [ 4 ] } | #{ @flat_4_board [ 5 ] } | #{ @flat_4_board [ 6 ] } | #{ @flat_4_board [ 7 ] } " ,
17
+ " #{ @board [ 4 ] } | #{ @board [ 5 ] } | #{ @board [ 6 ] } | #{ @board [ 7 ] } " ,
26
18
"-------------------" ,
27
- " #{ @flat_4_board [ 8 ] } | #{ @flat_4_board [ 9 ] } | #{ @flat_4_board [ 10 ] } | #{ @flat_4_board [ 11 ] } " ,
19
+ " #{ @board [ 8 ] } | #{ @board [ 9 ] } | #{ @board [ 10 ] } | #{ @board [ 11 ] } " ,
28
20
"-------------------" ,
29
- " #{ @flat_4_board [ 12 ] } | #{ @flat_4_board [ 13 ] } | #{ @flat_4_board [ 14 ] } | #{ @flat_4_board [ 15 ] } "
21
+ " #{ @board [ 12 ] } | #{ @board [ 13 ] } | #{ @board [ 14 ] } | #{ @board [ 15 ] } "
22
+ end
23
+
24
+ def available? ( box )
25
+ box . class == Fixnum
30
26
end
31
27
32
- update_board = lambda do |flat_board , player , place |
33
- if flat_board [ place - 1 ] . class == Fixnum
34
- flat_board [ place - 1 ] = player
35
- @board = flat_board . each_slice ( @choice ) . to_a
28
+ def update_board ( player , place )
29
+ if available? ( @board [ place - 1 ] )
30
+ @board [ place - 1 ] = player . rjust ( place . to_s . length )
36
31
else
37
32
prompt_new_box ( player )
38
33
end
39
-
40
34
determine_game_over ( player )
41
35
end
42
36
37
+ def yes?
38
+ [ "Y" , "y" ] . include? ( gets . chomp )
39
+ end
40
+
43
41
def display_menu
44
- # choose board size
45
42
print "Would you like to play on a 3 x 3 board or a 4 x 4 board?\n "
46
43
print "Enter '3' for the former or '4' for the latter: "
47
- @choice = gets . chomp . to_i
48
- if @choice == 4
49
- @board = @four_board
50
- elsif @choice != 3 && @choice != 4
51
- @choice == 3
44
+ @dimension = gets . chomp . to_i
45
+ if @dimension == 3
46
+ @board = ( 1 ..9 ) . to_a
47
+ elsif @dimension == 4
48
+ @board = ( 1 ..16 ) . to_a
49
+ else
50
+ @dimension = 3
51
+ @board = ( 1 ..9 ) . to_a
52
52
print "That's not a valid choice, so we'll just default to a 3 x 3 board.\n "
53
53
end
54
54
55
- # choose whether to play against computer
56
55
print "Would you like to play against the computer? (Y/N) "
57
- if [ "Y" , "y" ] . include? ( gets . chomp )
56
+ if yes?
58
57
print "Would you like to play first? (Y/N) "
59
- [ "Y" , "y" ] . include? ( gets . chomp ) ? @computer = 0 : @computer = 1
58
+ yes? ? @computer = 0 : @computer = 1
60
59
relay_computer_human_turns
61
60
else
62
61
print "OK, let's proceed with two human players...\n "
@@ -65,37 +64,37 @@ def display_menu
65
64
end
66
65
67
66
def computer_move
67
+ computer_think
68
68
# sample of all available spaces within @board
69
- @place = @board . flatten . select { |i | i . class == Fixnum } . sample
70
- @choice == 3 ? update_board . call ( @flat_3_board , @computer , @place ) :
71
- update_board . call ( @flat_4_board , @computer , @place )
69
+ @place = @board . flatten . select { |i | available? ( i ) } . sample
70
+ update_board ( @computer , @place )
72
71
end
73
72
74
73
def computer_think
75
74
print "\n THE ALMIGHTY COMPUTER IS CONTEMPLATING ITS MOVE...\n "
76
75
3 . times do
77
- sleep ( 1 ) # sleep for 1 second
76
+ sleep ( 1 )
78
77
print "\n COMPUTING...\n "
79
78
end
80
79
print "\n WHAM!\n "
81
80
sleep ( 1 )
82
81
end
83
82
84
83
def relay_computer_human_turns
85
- @choice == 3 ? print_three_board : print_four_board
84
+ @dimension == 3 ? print_three_board : print_four_board
86
85
87
86
if @computer == 0 && @human . nil? # human plays first move of the game
88
87
print "\n Human, do you want to play an X or an O? "
89
88
confirm_x_or_o
90
89
elsif @computer == 1 # computer plays first move of the game
91
90
@computer = [ "X" , "O" ] . sample
92
91
computer_move
93
- elsif @human . nil? # human plays second (human's first move)
92
+ elsif @human . nil? # human plays second (this is human's first move)
94
93
@computer == "O" ? @human = "X" : @human = "O"
95
94
print "\n Watch out, Human! Computer has made its first move!"
96
95
print "\n In which box would you like to place your #{ @human } ? "
97
96
mark ( @human )
98
- elsif @computer == 0 # computer plays second (computer's first move)
97
+ elsif @computer == 0 # computer plays second (this is computer's first move)
99
98
@human == "O" ? @computer = "X" : @computer = "O"
100
99
computer_move
101
100
elsif @turn == @human # human's subsequent move
@@ -107,28 +106,28 @@ def relay_computer_human_turns
107
106
end
108
107
109
108
def relay_player_turns
110
- @choice == 3 ? print_three_board : print_four_board
109
+ @dimension == 3 ? print_three_board : print_four_board
111
110
112
- if @p1 . nil?
111
+ if @player_1 . nil?
113
112
print "\n Player 1, make your move!\n Do you want to play an X or an O? "
114
113
confirm_x_or_o
115
- elsif @p2 . nil?
116
- @p1 == "O" ? @p2 = "X" : @p2 = "O"
117
- print "\n Player 2, make your move! In which box would you like to place your #{ @p2 } ? "
118
- mark ( @p2 )
119
- elsif @turn == @p1
120
- print "\n Player 1, back to you! In which box would you like to place your #{ @p1 } ? "
121
- mark ( @p1 )
114
+ elsif @player_2 . nil?
115
+ @player_1 == "O" ? @player_2 = "X" : @player_2 = "O"
116
+ print "\n Player 2, make your move! In which box would you like to place your #{ @player_2 } ? "
117
+ mark ( @player_2 )
118
+ elsif @turn == @player_1
119
+ print "\n Player 1, back to you! In which box would you like to place your #{ @player_1 } ? "
120
+ mark ( @player_1 )
122
121
else
123
- print "\n Player 2, back to you! In which box would you like to place your #{ @p2 } ? "
124
- mark ( @p2 )
122
+ print "\n Player 2, back to you! In which box would you like to place your #{ @player_2 } ? "
123
+ mark ( @player_2 )
125
124
end
126
125
end
127
126
128
127
def confirm_x_or_o
129
128
if @computer . nil?
130
- @p1 = gets . chomp
131
- player = @p1
129
+ @player_1 = gets . chomp
130
+ player = @player_1
132
131
else
133
132
@human = gets . chomp
134
133
player = @human
@@ -146,73 +145,67 @@ def confirm_x_or_o
146
145
147
146
def mark ( player )
148
147
@place = gets . chomp . to_i
149
- if ( @choice == 3 && ( 1 ..9 ) . include? ( @place ) ) ||
150
- ( @choice == 4 && ( 1 ..16 ) . include? ( @place ) )
151
- @choice == 3 ? update_board . call ( @flat_3_board , player , @place ) :
152
- update_board . call ( @flat_4_board , player , @place )
148
+ if ( @dimension == 3 && ( 1 ..9 ) . include? ( @place ) ) ||
149
+ ( @dimension == 4 && ( 1 ..16 ) . include? ( @place ) )
150
+ update_board ( player , @place )
153
151
else
154
152
print "Sir / Madam, please choose a valid number: "
155
153
mark ( player )
156
154
end
157
155
end
158
156
159
157
def prompt_new_box ( player )
160
- @choice == 3 ? print_three_board : print_four_board
158
+ @dimension == 3 ? print_three_board : print_four_board
161
159
print "\n STOP in the name of the law! That box is occupied - please choose another one. "
162
160
mark ( player )
163
161
end
164
162
165
163
def determine_game_over ( player )
166
164
if victory?
167
- if @turn == @computer
168
- computer_think
169
- end
170
-
171
- @choice == 3 ? print_three_board : print_four_board
165
+ @dimension == 3 ? print_three_board : print_four_board
172
166
173
- if @turn == @p1 || @turn == @p2 || @turn == @human
167
+ if @turn == @player_1 || @turn == @player_2 || @turn == @human
174
168
puts "\n CONGRATULATIONS! You have vanquished your foe!\n \n (╯°□°)╯︵ ┻━┻\n \n "
175
169
else
176
170
puts "\n PUNY HUMAN, ACCEPT DEFEAT!"
177
171
end
178
172
restart_request
179
- elsif ( @board . all ?{ |row | row . all? { | i | i . class == String } } && !victory? )
173
+ elsif ( @board . none ?{ |box | available? ( box ) } && !victory? )
180
174
puts "Messieurs, mesdames - you have come to a draw."
181
175
restart_request
182
176
else
183
177
if @computer . nil?
184
- player == @p1 ? @turn = @p2 : @turn = @p1
178
+ player == @player_1 ? @turn = @player_2 : @turn = @player_1
185
179
relay_player_turns
186
180
else
187
181
player == @computer ? @turn = @human : @turn = @computer
188
- if @turn == @human
189
- computer_think
190
- end
191
182
relay_computer_human_turns
192
183
end
193
184
end
194
185
end
195
186
196
187
def victory?
197
- reverse_board = @board . map { |a | a . reverse }
198
- @board . any? { |row | row . uniq . size == 1 } ||
199
- @board . transpose . any? { |row | row . uniq . size == 1 } ||
200
- ( @choice == 3 && ( 0 ..2 ) . map { |i | @board [ i ] [ i ] } . uniq . size == 1 ) ||
201
- ( @choice == 3 && ( 0 ..2 ) . map { |i | reverse_board [ i ] [ i ] } . uniq . size == 1 ) ||
202
-
203
- ( @choice == 4 && ( 0 ..3 ) . map { |i | @board [ i ] [ i ] } . uniq . size == 1 ) ||
204
- ( @choice == 4 && ( 0 ..3 ) . map { |i | reverse_board [ i ] [ i ] } . uniq . size == 1 )
188
+ sliced_board = @board . each_slice ( @dimension ) . to_a
189
+ reversed_sliced_board = sliced_board . map { |a | a . reverse }
190
+
191
+ sliced_board . any? { |row | row . uniq . size == 1 } ||
192
+ sliced_board . transpose . any? { |row | row . uniq . size == 1 } ||
193
+ ( @dimension == 3 && ( 0 ..2 ) . map { |i | sliced_board [ i ] [ i ] } . uniq . size == 1 ) ||
194
+ ( @dimension == 3 && ( 0 ..2 ) . map { |i | reversed_sliced_board [ i ] [ i ] } . uniq . size == 1 ) ||
195
+ ( @dimension == 4 && ( 0 ..3 ) . map { |i | sliced_board [ i ] [ i ] } . uniq . size == 1 ) ||
196
+ ( @dimension == 4 && ( 0 ..3 ) . map { |i | reversed_sliced_board [ i ] [ i ] } . uniq . size == 1 )
205
197
end
206
198
207
199
def restart_request
208
200
print "Would you like to play again? (Y/N) "
209
- if [ "Y" , "y" ] . include? ( gets . chomp )
210
- initialize
211
- display_menu
201
+ if [ "N" , "n" ] . include? ( gets . chomp )
202
+ exit ( 0 )
212
203
end
213
204
end
214
205
end
215
206
216
207
if __FILE__ == $0
217
- TTT . new . display_menu
208
+ loop do
209
+ TTT . new . display_menu
210
+ end
218
211
end
0 commit comments