English 中文(简体)
Compact way of representing all valid "rows" in a tic-tac-toe grid
原标题:

I ve been writing tic-tac-toe in a variety of languages as an exercise, and one pattern that has emerged is that every representation I ve come up with for the defining valid winning rows has been disappointingly hard-coded. They ve generally fallen into two categories:

First, the board is represented as a one- or two-dimensional array, and rows are explicitly defined by triplets of positions (numbers are empty spaces):

board = [1, x, 3, 4, o, 6, 7, 8, x]

def match3(x,y,z)
  board[x] == board[y] && board[y] == board[z]
end

def winner
  match3(1,2,3) || match3(4,5,6) || ...
end

This has the advantage of non-magical explicitness, but it seems verbose.

The other approach is to use an array of arrays and map+reduce the rows. It s slightly better, but doesn t get me all the way:

board = [[nil, 1, nil], [nil, -1, nil], [nil, nil, 1]]

def diag(x,y,z)
  [board[x/3,x%3], board[y/3,y%3], board[z/3,z%3]]
end

def winner
  rows = board + board.transpose << diag(0,4,8) << diag(2,4,6)
  rows.map { |r| r.reduce(:&) }.reduce { |m,c| m || c }
end

Vertical and horizontal matches are great, but I m still hardcoding the diagonals.

Can anyone think of a way to characterize the diagonals (or a wholly different approach) that doesn t rely on explicit addresses?

My pseudocode is Rubyish, but please feel free to post in any language you like. I saw the tic-tac-toe code golf, and while some of those solutions are ingenious (especially the magic squares!) I m looking for something a bit less obfuscating.

问题回答

A system that s a lot faster and more compact is to use one bit for every square. Current position can be kept in two variables: X holding all the "X" marks, and O holding all "O" marks. A possible encoding for the 9 squares is for example

 1   2   4
 8  16  32
64 128 256

With this encoding the first row is 1+2+4=7 and top/left->bottom/right diagonal is 1+16+256=273.

Checking if X won on the first row is just if ((X & 7) == 7), other checks are similar but with different numbers instead of 7. The full victory checking routine becomes...

def winner(p):
    for m in (7, 56, 448, 73, 146, 292, 273, 84):
        if p & m == m: return True
    return False




相关问题
The Fastest DataStructure to Filter with in C#

Currently we are filtering and sorting data with a datatable. /// <summary> /// Filters the data table and returns a new data table with only the filtered rows. /// </summary>...

Efficient queue in Haskell

How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...

Java large datastructure for storing a matrix

I need to store a 2d matrix containing zip codes and the distance in km between each one of them. My client has an application that calculates the distances which are then stored in an Excel file. ...

Holding onto items after a postback

I have an ASP.NET web application and I want to be able to take items from a master list and store them temporarliy into one of four other lists. The other lists need to survive post backs so that ...

negative number in the stack

I am a new student in the compilers world ^_^ and I want to know is legal represent negative number in the stack. For example: infix: 1-5=-4 postfix: 15- The statements are: push(1) push(5) x=...

What type of struct/container would you use in this instance?

I am trying to figure out what type of structure or container I should use for a quick project. I need to have an unknown number of sets that will be entered from the GUI (each one will have a name, ...

热门标签