Estoy haciendo un simple juego de tres en raya donde las filas están representadas por tres matrices y las columnas son elementos de esas matrices. Para mi elección de computadora, uso dos funciones separadas para obtener la fila y la columna.
$first = ["-","-","-"]
$secound = ["-","-","-"]
$third = ["-","-","-"]
def get_row
row = nil
case rand(3)
when 0
row = $first
when 1
row = $secound
else
row = $third
end
row
end
def get_col
col = nil
case rand(3)
when 0
col = 0
when 1
col = 1
else
col = 2
end
col
end
Luego uso una tercera función que sigue generando una nueva "suposición" hasta que encuentra un lugar vacío, en cuyo punto marca un 0.
def computer_guess
temp = false
try = get_row[get_col]
while temp == false
if try == "-"
get_row[get_col] = "O"
temp = true
else
try = get_row[get_col]
end
end
end
Mi problema es que no puedo devolver la suposición a la misma posición en la que verifico la validez. ¿Hay alguna forma de sincronizarlos o necesito un enfoque diferente?
3 respuestas
El problema con su enfoque es que get_row[get_col]
devuelve un elemento aleatorio cada vez que se llama, por lo que get_row[get_col] = "O"
también establecerá un elemento aleatorio en { {X2}}. Inspeccionas un elemento y luego configuras otro.
Puede solucionar esto rápidamente modificando el elemento recuperado en el lugar:
if try == "-"
try.replace("O")
# ...
Pero semánticamente, no me gusta mucho esa solución. Pensando en un tablero de tres en raya, prefiero asignar un "O"
al lugar libre que transformar el marcador de posición existente de "-"
en "O"
.
¿Notó que su método get_row
devuelve una matriz mientras que get_col
devuelve un índice? Creo que esta mezcla de matrices e índices hace que su código sea un poco complicado.
Es mucho más fácil (en mi opinión) acceder a ambos, fila y columna a través de un índice.
Para hacerlo, podría colocar sus tres filas en otra matriz:
$board = [
['-', '-', '-'],
['-', '-', '-'],
['-', '-', '-']
]
Se puede acceder a la primera fila a través de $board[0]
y a su primer elemento a través de $board[0][0]
. Para establecer un elemento que usaría: $board[1][2] = 'O'
(esto establece el elemento más a la derecha de la fila del medio en "O"
). Por supuesto, también puede usar variables, p. $board[row][col]
.
Con esta matriz bidimensional, su computer_guess
podría reescribirse usando solo dos índices aleatorios: (get_row
y get_col
ya no son necesarios)
def computer_guess
loop do
row = rand(3) # random row index
col = rand(3) # random column index
if $board[row][col] == '-' # if corresponding spot is "-"
$board[row][col] = 'O' # set that spot to "O"
break # and break out of the loop
end
end
end
Sin embargo, tenga en cuenta que adivinar "a ciegas" los puntos hasta que encuentre uno libre podría no ser el mejor enfoque.
En su lugar, podría generar una lista de espacios "gratuitos". Esto se puede hacer generando primero una matriz de todas las coordenadas 1 y luego select
-ing esos pares de filas / columnas cuyo lugar es "-"
:
def free_spots
coordinates = [0, 1, 2].product([0, 1, 2])
coordinates.select { |row, col| $board[row][col] == '-' }
end
Ahora solo tiene que elegir un par aleatorio (a través de { {X0}}) y establezca el lugar correspondiente en "O"
:
def computer_guess
row, col = free_spots.sample
$board[row][col] = 'O'
end
1 {{X0} } devuelve el Producto cartesiano de las matrices proporcionadas. Es una forma fácil de obtener todos los pares:
[0, 1, 2].product([0, 1, 2])
#=> [[0, 0], [0, 1], [0, 2],
# [1, 0], [1, 1], [1, 2],
# [2, 0], [2, 1], [2, 2]]
Aquí hay otro enfoque. Este código imita la computadora del juego contra sí mismo. Puede reemplazar fácilmente el movimiento de una computadora con la entrada del usuario.
ROWS = 3
COLUMNS = 3
MAX_TURNS = ROWS * COLUMNS
def random_cell
{ row: rand(ROWS), column: rand(COLUMNS) }
end
def empty_random_cell(board)
while true
cell = random_cell
return cell if board_value(board, cell).nil?
end
end
def board_value(board, cell)
board[cell[:row]][cell[:column]]
end
def turn(board, cell, value)
row = cell[:row]
column = cell[:column]
board[row][column] = value
end
def print_board(board)
ROWS.times do |row|
COLUMNS.times do |column|
value = board[row][column]
print value.nil? ? '_' : value
print ' '
end
puts
end
end
board = Array.new(ROWS) { Array.new(COLUMNS) }
print_board(board)
turns_counter = 0
while true
cell = empty_random_cell(board)
turn(board, cell, 'X')
turns_counter += 1
break if turns_counter == MAX_TURNS
cell = empty_random_cell(board)
turn(board, cell, '0')
turns_counter += 1
break if turns_counter == MAX_TURNS
end
print_board(board)
Cuando solo hay un lugar disponible, puede tomar tiempo adivinarlo.
Por lo tanto, podría ser mejor cotejar los puntos disponibles y obtener un valor aleatorio a partir de ahí:
def computer_guess
free_spots=[]
free_spots.concat($first.each_with_index.map{|x,i|x=='-' ? ['$first',i] : nil}.compact)
free_spots.concat($secound.each_with_index.map{|x,i|x=='-' ? ['$secound',i] : nil}.compact)
free_spots.concat($third.each_with_index.map{|x,i|x=='-' ? ['$third',i] : nil}.compact)
try=free_spots.sample
eval"#{try[0]}[#{try[1]}]='O'" unless try.nil?
end
Preguntas relacionadas
Nuevas preguntas
ruby
Ruby es un lenguaje interpretado dinámico orientado a objetos, multiplataforma de código abierto. La etiqueta [ruby] es para preguntas relacionadas con el lenguaje Ruby, incluida su sintaxis y sus bibliotecas. Las preguntas de Ruby on Rails deben etiquetarse con [ruby-on-rails].