local backg = gui.background local grid = backg.U...

Creato il: 8 febbraio 2025

Risposto usando O1 da Chat01

Domanda

local backg = gui.background

local grid = backg.UIGridLayout
grid.CellPadding = UDim2.new(.02,0,.02,0)
grid.CellSize = UDim2.new(1/3.3,0,1/3.3,0)
grid.HorizontalAlignment = Enum.HorizontalAlignment.Center
grid.VerticalAlignment = Enum.VerticalAlignment.Center
grid.FillDirectionMaxCells = 3

local hash = {
Cells = {},
CurrentPlayer = 0 -- 1 - O, 2 - X
}

local makeMove = function() return end
local checkWin = function() return end
local aiMeko

makeMove = function(cell)
if cell.Text ~= "" then return end -- Нельзя ходить в занятые клетки

text
if hash.CurrentPlayer == 1 then cell.Text = "O" cell.TextColor3 = Color3.new(0.666667, 0.333333, 0.498039) hash.CurrentPlayer = 0 elseif hash.CurrentPlayer == 0 then cell.Text = "X" cell.TextColor3 = Color3.new(0.666667, 1, 0.498039) hash.CurrentPlayer = 1 end local winner = checkWin() if winner then print("Победитель: " .. winner) for i,v in hash.Cells do v.Text = "" hash.CurrentPlayer = 0 end -- Здесь можно добавить логику для завершения игры end

end

checkWin = function()
local winPatterns = {
{1, 2, 3}, -- Верхняя строка
{4, 5, 6}, -- Средняя строка
{7, 8, 9}, -- Нижняя строка
{1, 4, 7}, -- Первый столбец
{2, 5, 8}, -- Второй столбец
{3, 6, 9}, -- Третий столбец
{1, 5, 9}, -- Диагональ слева направо
{3, 5, 7}, -- Диагональ справа налево
}

text
for _, pattern in ipairs(winPatterns) do local a, b, c = pattern[1], pattern[2], pattern[3] if hash.Cells[a].Text ~= "" and hash.Cells[a].Text == hash.Cells[b].Text and hash.Cells[b].Text == hash.Cells[c].Text then return hash.Cells[a].Text -- Возвращает "X" или "O" end end return nil -- Победителя нет

end

for i=1, 3*3 do
local cell = Instance.new("TextButton")
cell.Text = ""
cell.TextSize = 60
cell.BackgroundColor3 = Color3.fromRGB(0, 65, 47)
cell.Parent = backg
cell.Name = "C"..i
hash.Cells[i] = cell

text
local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(.1,0) corner.Parent = cell cell.MouseButton1Click:Connect(function() makeMove(cell) end)

end

это игра крестики нолики для roblox studio. можешь пожалуйста сделать так, чтобы крестики играл игрок, и за нолики играл игрок и у них подсвечивались лучшие ходы для выигрыша от ии минимакс

Pensiero

Clarifying the issue

The code seems to have inconsistent player indexing, using both "0" and "1" for players, which mismatches with the accompanying comment. This discrepancy needs addressing to ensure consistency.

Observing gameplay flow

I'm noticing that "X" always starts first, which aligns with "hash.CurrentPlayer = 0" by default. The sequence of moves, switching between players, seems clear and consistent.

Figuring out the nuances

OK, let's break this down: both 'X' and 'O' are human players. The minimax AI will highlight the best moves for the current O player.

Highlighting optimal moves

The task involves a function to use the minimax algorithm to pinpoint the best moves for each player, ensuring the AI's strategy is clear to the human players.

Perfecting the process

OK, let me see. Implementing the minimax algorithm will specify the top moves, which are then highlighted for each player to visualize winning options. This guides the gameplay effectively.

Assessing future actions

I'm digging into a function to pinpoint optimal moves for the next player, ensuring "hash.CurrentPlayer" is updated post-move. This involves toggling "CurrentPlayer" and adjusting highlights for each player.

Breaking down the strategy

I'm starting with a function to rate board outcomes, assigning values to X and O. The minimax function then identifies and highlights the best moves for the current player.

Piecing together the function

I’m working on the minimax function, assigning roles to X and O, assessing the board state, and highlighting optimal moves. This ensures a consistent and effective strategy.

Strategizing optimal moves

I’m assembling functions to refine the minimax approach, including tracking game states, evaluating board results, and pinpointing best moves for each player to streamline the process.

Integrating functionalities

I’m combining game mechanics, including resetting the board, dynamically highlighting moves, and using a simplified minimax approach. This streamlines the process, making it more efficient and organized.

Forming the strategy

I’m planning to use a simple minimax approach, focusing on a 3x3 board. It involves checking for winners, evaluating moves, and highlighting the optimal ones.

Highlighting optimal moves

I'm iterating through each cell, assigning player marks, and using minimax to score potential moves. Then, I pinpoint and illuminate the best moves for the current player.

Examining minimax strategy

I’m refining the minimax strategy by evaluating board states, scoring potential moves, and highlighting the top moves. This ensures a thorough analysis of all possible moves.

Reasoned for 37 seconds

Risposta

Ниже приведён пример кода, в котором оба игрока (X и O) ходят сами, а при каждом ходе подсвечиваются все лучшие ходы (по версии алгоритма «Минимакс») для текущего игрока.
Обратите внимание:

  1. X и O — оба управляются игроками.
  2. Алгоритм «Минимакс» лишь подсвечивает потенциально выигрышные ходы (или позволяющие избежать проигрыша).
  3. При клике по одной из подсвеченных клеток совершается ход, после чего подсвечиваются лучшие варианты для следующего игрока.

Важно: В Roblox Studio, цвета могут несколько отличаться, если вы используете разные Lighting-технологии или конфигурации ColorSpace. При желании корректируйте значения Color3 на своё усмотрение.

lua
local backg = gui.background local grid = backg.UIGridLayout grid.CellPadding = UDim2.new(.02,0,.02,0) grid.CellSize = UDim2.new(1/3.3,0,1/3.3,0) grid.HorizontalAlignment = Enum.HorizontalAlignment.Center grid.VerticalAlignment = Enum.VerticalAlignment.Center grid.FillDirectionMaxCells = 3 local hash = { Cells = {}, -- хранилище кнопок CurrentPlayer = "X" -- "X" или "O" } -- Минимакс-оценка (возвращает +10, если выиграл X, -10 если выиграл O, 0 при ничьей или если пока неизвестно) local function evaluate(board) -- Проверка всех выигрышных сочетаний local wins = { {1,2,3},{4,5,6},{7,8,9}, -- строки {1,4,7},{2,5,8},{3,6,9}, -- столбцы {1,5,9},{3,5,7} -- диагонали } for _, combo in ipairs(wins) do local a, b, c = combo[1], combo[2], combo[3] if board[a] ~= "" and board[a] == board[b] and board[b] == board[c] then if board[a] == "X" then return 10 else return -10 end end end -- Если никто не выиграл, возвращаем 0 return 0 end -- Проверка, есть ли пустые ячейки local function hasEmptyCells(board) for i=1,9 do if board[i] == "" then return true end end return false end -- Функция &laquo;Минимакс&raquo;: возвращает оценку для текущей конфигурации -- depth — для более тонкой оценки (чем быстрее выигрыш, тем лучше, и наоборот) -- isMaximizing — булево, если ходит X (максимизирующий игрок) local function minimax(board, depth, isMaximizing) local score = evaluate(board) -- Если кто-то выиграл, возвратим оценку с учётом глубины if score == 10 then -- Чем меньше глубина, тем быстрее X выиграл, тем лучше return score - depth elseif score == -10 then -- Чем меньше глубина, тем быстрее O выиграл, тем лучше (для O — хуже для X), -- поэтому depth вычитаем, чтобы "наказать" X за быструю потерю. return score + depth end -- Если не осталось ходов и никто не выиграл, то ничья if not hasEmptyCells(board) then return 0 end if isMaximizing then -- Ходит X — пытается максимально повысить счёт local best = -99999 for i=1,9 do if board[i] == "" then board[i] = "X" best = math.max(best, minimax(board, depth+1, false)) board[i] = "" end end return best else -- Ходит O — пытается минимизировать счёт local best = 99999 for i=1,9 do if board[i] == "" then board[i] = "O" best = math.min(best, minimax(board, depth+1, true)) board[i] = "" end end return best end end -- Получаем одномерный массив текущего состояния (9 ячеек) из Text кнопок local function getBoardState() local board = {} for i=1, 9 do board[i] = hash.Cells[i].Text end return board end -- Возвращает список лучших ходов для текущего игрока (X или O), -- используя Минимакс, чтобы найти максимальный (для X) или минимальный (для O) счёт local function getBestMoves(currentPlayer) local board = getBoardState() local bestMoves = {} local isX = (currentPlayer == "X") local bestScore = isX and -99999 or 99999 for i=1,9 do if board[i] == "" then board[i] = currentPlayer -- Вызываем minimax: если ходит X, то isMaximizing = false для следующего шага local moveScore = minimax(board, 0, not isX) board[i] = "" if isX then -- Максимизируем if moveScore > bestScore then bestScore = moveScore bestMoves = {i} elseif moveScore == bestScore then table.insert(bestMoves, i) end else -- Минимизируем if moveScore < bestScore then bestScore = moveScore bestMoves = {i} elseif moveScore == bestScore then table.insert(bestMoves, i) end end end end return bestMoves end -- Подсвечивает все клетки зелёным цветом, которые входят в bestMoves -- Перед этим убираем подсветку со всех клеток local function highlightBestMoves(bestMoves) -- Сбрасываем цвет у всех клеток на базовый for i=1,9 do hash.Cells[i].BackgroundColor3 = Color3.fromRGB(0, 65, 47) end -- Подсвечиваем рекомендуемые ходы for _, index in ipairs(bestMoves) do hash.Cells[index].BackgroundColor3 = Color3.fromRGB(0, 255, 0) end end -- Проверка победителя (возвращает "X" или "O" при выигрыше, nil — если нет) local function checkWin() local winPatterns = { {1, 2, 3}, -- Верхняя строка {4, 5, 6}, -- Средняя строка {7, 8, 9}, -- Нижняя строка {1, 4, 7}, -- Первый столбец {2, 5, 8}, -- Второй столбец {3, 6, 9}, -- Третий столбец {1, 5, 9}, -- Диагональ слева направо {3, 5, 7}, -- Диагональ справа налево } for _, pattern in ipairs(winPatterns) do local a, b, c = pattern[1], pattern[2], pattern[3] if hash.Cells[a].Text ~= "" and hash.Cells[a].Text == hash.Cells[b].Text and hash.Cells[b].Text == hash.Cells[c].Text then return hash.Cells[a].Text -- "X" или "O" end end return nil end -- Сброс поля при выигрыше local function resetBoard(winner) print("Победитель: " .. winner) -- Сбрасываем все клетки for i=1,9 do hash.Cells[i].Text = "" hash.Cells[i].BackgroundColor3 = Color3.fromRGB(0, 65, 47) end -- Начинаем заново. По традиции, пусть X ходит первым: hash.CurrentPlayer = "X" highlightBestMoves(getBestMoves(hash.CurrentPlayer)) end -- Делаем ход в клетку local function makeMove(cellIndex) -- Если клетка занята, выходим if hash.Cells[cellIndex].Text ~= "" then return end -- Ставим X или O в клетку hash.Cells[cellIndex].Text = hash.CurrentPlayer if hash.CurrentPlayer == "X" then hash.Cells[cellIndex].TextColor3 = Color3.new(0.666667, 1, 0.498039) -- немного зеленоватый hash.CurrentPlayer = "O" else hash.Cells[cellIndex].TextColor3 = Color3.new(0.666667, 0.333333, 0.498039) -- розоватый hash.CurrentPlayer = "X" end -- Проверяем победу local winner = checkWin() if winner then -- Если есть победитель, сбрасываем поле resetBoard(winner) return end -- Если нет победителя, проверяем нет ли ничьей local board = getBoardState() if not hasEmptyCells(board) then print("Ничья!") -- Сброс resetBoard("Ничья") return end -- Подсвечиваем лучшие ходы для следующего игрока local bestMoves = getBestMoves(hash.CurrentPlayer) highlightBestMoves(bestMoves) end -- Создаём 9 кнопок и вешаем на каждую функцию makeMove(i) for i=1, 9 do local cell = Instance.new("TextButton") cell.Text = "" cell.TextSize = 60 cell.BackgroundColor3 = Color3.fromRGB(0, 65, 47) cell.Parent = backg cell.Name = "C"..i hash.Cells[i] = cell local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(.1,0) corner.Parent = cell cell.MouseButton1Click:Connect(function() makeMove(i) end) end -- В самом начале сразу подсветим лучшие ходы для X, так как X ходит первым highlightBestMoves(getBestMoves(hash.CurrentPlayer))

Краткое описание логики

  1. evaluate(board)
    Возвращает +10, если на доске выиграл X, -10 если выиграл O, и 0 если победителя нет.
  2. minimax(board, depth, isMaximizing)
    Рекурсивно перебирает все возможные ходы и возвращает лучшую оценку для текущего игрока (X или O).
  3. getBestMoves(currentPlayer)
    Проходит по всем пустым клеткам, «примеряет» туда ход currentPlayer и считает оценку через minimax. Сравнивает оценки, собирая все клетки, которые дают «лучшую» оценку (макс. для X, мин. для O).
  4. highlightBestMoves(bestMoves)
    Сбрасывает цвет всех клеток и подсвечивает зелёным те клетки, которые входят в список «лучших».
  5. makeMove(cellIndex)
    Действие при клике: проставляет X или O, проверяет победу, иначе — переключает ход и подсвечивает лучшие варианты для нового игрока.
  6. Изначально все клетки пустые, ход начинается с X, а после каждого хода меняется на O, и так далее.

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

Condividi questa Q&A