From: daz Date: 2005-10-16T20:12:03+09:00 Subject: Re: Tic-tac-toe checking CBlair1986 wrote: > Hi all! I have a quick (I hope) question about checking for a > tic-tac-toe win. > > I'd like to be able to check for a X-in-a-row win on a Y-by-Y board. > I'd eventually like to be able to check for a 10-in-a-row on a 50-by-50 > board. Are there any easy methods I could use, besides doing a check > for each possible win? Hmm, the question seems quick enough :p You're not ready for this, then: http://www.rubyquiz.com/quiz11.html (Artificially Intelligent Tic-Tac-Toe) ===== The method I use for checking is: 1) Only need to check if the current player has won. ( 'O' can't win on 'X's move - and vice-versa) 2) If the player plays on row 2 - check that row only 3) If the player plays on col 1 - check that col only 4) Check both diagonals after each move 'cos it's probably quicker than deciding whether or not it's necessary (?) Summary - check: 1 row, 1 column, 2 diagonals for 1 player after each move. To do that, I use 4 flags winx, winy, wnd1, wnd2 (ugh!) They're all set to 'true' at the top of 'check_win' and within the loop, they're set to false if any test fails. Once false, they can't become true again before the end of the method. If any remain true, a complete row/column/diagonal must have passed the stringent tests! I know you wanted to do this yourself but I appear to have done it for you -- which is slightly dumb but I can never trust my descriptions unless tested. > > Thanks! > No problem. All the busy people are missing. All the missing people are busy. ~daz * PLEASE SNIP AS MUCH AS POSSIBLE ON ANY FOLLOW-UP REPLY * (e.g. everything) + + + S T O P H E R E + + + #------------------------------------------------------------------- class TTT def initialize(n, ox = :X) @dims = n @grid = Array.new(n) { Array.new(n) } @player = ox end def play(x, y) puts "\n#@player plays: #{x}, #{y}" if @grid[x][y] puts "... square occupied by #@player" return else @grid[x][y] = @player end puts inspect if check_win(x, y) puts "\n #@player is the WINNER" exit end @player = (@player == :O ? :X : :O) end def check_win(x, y) winx, winy = true, true wnd1, wnd2 = true, true @dims.times do |n| winx = false if @grid[x][n] != @player winy = false if @grid[n][y] != @player wnd1 = false if @grid[n][n] != @player wnd2 = false if @grid[@dims-1-n][n] != @player end winx || winy || wnd1 || wnd2 end def inspect # Ignore this garbage - (quick check) grid = "\n" << ((' [%d]' * @dims) % ((0...@dims).to_a)) << "\n" sep = '+---'*@dims << "+\n" grid << sep @grid.each do |row| rw = row.map {|e| e || ' '} grid << '|' << (([' %s '] * @dims).join('|') % rw) << "|\n" grid << sep end grid end end g = TTT.new(4, :O) # select :O as starter g.play(2, 3) g.play(3, 0) g.play(3, 2) g.play(3, 0) g.play(2, 1) g.play(0, 0) g.play(0, 3) g.play(1, 1) #g.play(1, 2) # would WIN for :X g.play(1, 3) g.play(3, 3) g.play(2, 0) g.play(2, 2) # WINs for :O g.play(0, 1) # doesn't get here #------------------------------------------------------------------- O plays: 2, 3 [0] [1] [2] [3] +---+---+---+---+ | | | | | +---+---+---+---+ | | | | | +---+---+---+---+ | | | | O | +---+---+---+---+ | | | | | +---+---+---+---+ X plays: 3, 0 [0] [1] [2] [3] +---+---+---+---+ | | | | | +---+---+---+---+ | | | | | +---+---+---+---+ | | | | O | +---+---+---+---+ | X | | | | +---+---+---+---+ O plays: 3, 2 [0] [1] [2] [3] +---+---+---+---+ | | | | | +---+---+---+---+ | | | | | +---+---+---+---+ | | | | O | +---+---+---+---+ | X | | O | | +---+---+---+---+ X plays: 3, 0 .... square occupied by X X plays: 2, 1 <---snip---> X plays: 2, 0 [0] [1] [2] [3] +---+---+---+---+ | O | | | X | +---+---+---+---+ | | O | | X | +---+---+---+---+ | X | X | | O | +---+---+---+---+ | X | | O | O | +---+---+---+---+ O plays: 2, 2 [0] [1] [2] [3] +---+---+---+---+ | O | | | X | +---+---+---+---+ | | O | | X | +---+---+---+---+ | X | X | O | O | +---+---+---+---+ | X | | O | O | +---+---+---+---+ O is the WINNER