Синхронизация случайной величины в ruby - PullRequest
1 голос
/ 19 февраля 2020

Я делаю простую игру «Ti c ta c toe», где строки представлены тремя массивами, а столбцы являются элементами этих массивов. Для выбора компьютера я использую две отдельные функции для получения строки и столбца.

$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

Затем я использую третью функцию, которая продолжает генерировать новое «предположение», пока не найдет пустое место, и в этот момент оно помечает 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

Моя проблема в том, что я не могу вернуть предположение в ту же позицию, что проверяю на достоверность. Есть ли способ синхронизировать c это или мне нужен другой подход?

Ответы [ 3 ]

1 голос
/ 19 февраля 2020

когда есть только одно доступное место, может потребоваться время, чтобы его угадать.
Так что может быть лучше сопоставить имеющиеся места и получить оттуда случайное значение:

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
1 голос
/ 19 февраля 2020

Проблема вашего подхода в том, что get_row[get_col] возвращает элемент random каждый раз, когда он вызывается, поэтому get_row[get_col] = "O" также установит элемент random в "O". Вы проверяете один элемент, а затем устанавливаете другой.

Вы можете быстро это исправить, изменив извлеченный элемент на месте:

if try == "-"
  try.replace("O")
  # ...

Но семантически мне не очень нравится это исправление , Думая о доске ti c -ta c, я бы скорее присвоил "O" свободному месту, чем преобразовал существующий заполнитель из "-" в "O".

Сделал Вы заметили, что ваш метод get_row возвращает массив, тогда как get_col возвращает индекс? Я думаю, что эта комбинация массивов и индексов делает ваш код немного запутанным.

Намного проще (на мой взгляд) получить доступ как к строке, так и к столбцу через индекс.

Для этого, Вы можете поместить три строки в другой массив:

$board = [
  ['-', '-', '-'],
  ['-', '-', '-'],
  ['-', '-', '-']
]

К первой строке можно получить доступ через $board[0], а к ее первому элементу - через $board[0][0]. Чтобы установить элемент, который вы используете: $board[1][2] = 'O' (это устанавливает самый правый элемент средней строки на "O"). Конечно, вы также можете использовать переменные, например, $board[row][col].

. С этим двумерным массивом ваш computer_guess может быть переписан с использованием всего двух случайных индексов: (get_row и get_col aren ' больше не нужно)

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

Обратите внимание, что "слепое" угадывание мест, пока вы не найдете свободное, может быть не лучшим подходом.

Вместо этого вы можете создать список "свободных" "пятна. Это можно сделать, сначала сгенерировав массив всех координат 1 , а затем select с теми парами строк / столбцов, чья точка равна "-":

def free_spots
  coordinates = [0, 1, 2].product([0, 1, 2])
  coordinates.select { |row, col| $board[row][col] == '-' }
end

Теперь вам просто нужно выбрать случайную пару (через sample) и установить соответствующее место на "O":

def computer_guess
  row, col = free_spots.sample
  $board[row][col] = 'O'
end

1 Array#product возвращает декартово произведение указанных массивов. Это простой способ получить все пары:

[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]]
1 голос
/ 19 февраля 2020

Вот другой подход. Этот код имитирует игровой компьютер против самого себя. Вы можете легко заменить движение одного компьютера пользовательским вводом.

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...