Tic tac Toe Game not working as intended?

  1. i’m trying to make a tic tac toe game and it’s not working

  2. the issue is when i click on the Click Detectors aka the places to place the X and O, it does not Place the X or even O to where i’m clicking on basically. when it should.

  3. i tried changing to where it’s being positioned to and nothing… changed the position values still nothing i don’t understand what’s wrong i even tried Not cloning the X and O and instead just move the pieces and it still doesn’t work. i wanna use Clone() method instead so i don’t have to keep making the pieces.

i just need to understand what is wrong or what i need to do. i don’t know what else to do to even fix it. it’s a tic tac toe game (Suppose to) and yes i did make it run when 1 player is sitting for testing purposes.

local X = game.ReplicatedStorage.TicTacToe.X
local O = game.ReplicatedStorage.TicTacToe.O
local ClickHereButtons = script.Parent.ClickHereButtons
local PlayerSeat1 = script.Parent.Parent.Seat1.Player1
local PlayerSeat2 = script.Parent.Parent.Seat2.Player2

local currentPlayer = nil
local board = {}
local gameActive = false
local gameTimeLimit = 300 -- Set the game time limit in seconds
local gameStartTime = 0

-- Function to initialize the game
local function InitializeGame()
	board = {}
	for i = 1, 3 do
		board[i] = {}
		for j = 1, 3 do
			board[i][j] = ""
		end
	end
	currentPlayer = PlayerSeat1.Occupant
	gameActive = true
	gameStartTime = tick() -- Record the game start time
end

local function MoveModel(player, cell)
	local symbol = (currentPlayer == PlayerSeat1.Occupant) and "X" or "O"
	if board[cell.x][cell.y] == "" then
		board[cell.x][cell.y] = symbol

		-- Calculate the position where the X or O should be placed
		local posX = cell.Position.X
		local posY = cell.Position.Y + 5 -- Adjust the Y position as needed
		local posZ = cell.Position.Z

		local symbolModel = (symbol == "X") and X or O

		-- Move the X or O model to the calculated position
		symbolModel:SetPrimaryPartCFrame(CFrame.new(Vector3.new(posX, posY, posZ)))

		currentPlayer = (currentPlayer == PlayerSeat1.Occupant) and PlayerSeat2.Occupant or PlayerSeat1.Occupant
	end
end


-- Function to check for a win
local function CheckForWin(player)
	local function checkLine(a, b, c)
		return (a == b and b == c and a ~= "")
	end

	for i = 1, 3 do
		if checkLine(board[i][1], board[i][2], board[i][3]) then
			return true
		end
	end

	for j = 1, 3 do
		if checkLine(board[1][j], board[2][j], board[3][j]) then
			return true
		end
	end

	if checkLine(board[1][1], board[2][2], board[3][3]) or
		checkLine(board[1][3], board[2][2], board[3][1]) then
		return true
	end

	return false
end

-- Function to end the game
local function EndGame(winner)
	gameActive = false
	if winner then
		print("Game Over! Winner: " .. winner.Name)
	else
		print("Game Over! It's a draw.")
	end
end

-- Event handlers for player clicks on cells using ClickDetector
for _, cell in pairs(ClickHereButtons:GetChildren()) do
	local clickDetector = cell:FindFirstChild("ClickDetector")
	if clickDetector then
		clickDetector.MouseClick:Connect(function(player)
			print("ClickDetector clicked by " .. player.Name)
			local character = player.Parent
			if character and character:FindFirstChild("Humanoid") then
				local humanoid = character.Humanoid

				if gameActive and humanoid.Sit and PlayerSeat1.Occupant == player then

					-- Calculate i and j based on the button's position
					local cellPos = cell.Position
					local i = math.floor((cellPos.X + 15) / 10 + 0.5)
					local j = math.floor((cellPos.Z + 15) / 10 + 0.5)

					if not board[i] or not board[i][j] then
						MoveModel(player, {x = i, y = j, CFrame = cell.CFrame})
						if CheckForWin(player) then
							EndGame(player)
						else
							-- Check for a draw
							local draw = true
							for row = 1, 3 do
								for col = 1, 3 do
									if board[row][col] == "" then
										draw = false
										break
									end
								end
							end
							if draw then
								EndGame(nil)
							end
						end
					end
				end
			end
		end)
	end
end

local function CheckStartGame()
	if PlayerSeat1 and PlayerSeat1:IsA("Seat") and PlayerSeat1.Occupant then
		print("Game Started")
		InitializeGame()
	end
end

PlayerSeat1:GetPropertyChangedSignal("Occupant"):Connect(CheckStartGame)
PlayerSeat2:GetPropertyChangedSignal("Occupant"):Connect(CheckStartGame)

-- Player leaving handling using PlayerRemoving events
game.Players.PlayerRemoving:Connect(function(player)
	if gameActive and (player == PlayerSeat1.Occupant or player == PlayerSeat2.Occupant) then
		gameActive = false
		print(player.Name .. " left the game. The game is over.")
		-- Reset the game board (clear models from cells)
		for _, cell in pairs(ClickHereButtons:GetChildren()) do
			for _, child in pairs(cell:GetChildren()) do
				if child:IsA("Model") then
					child:Destroy()
				end
			end
		end
	end
end)

-- Check if the game has reached the time limit
game:GetService("RunService").Heartbeat:Connect(function()
	if gameActive and (tick() - gameStartTime) >= gameTimeLimit then
		gameActive = false
		print("Game Over! The game has reached the time limit.")
		EndGame(nil)
	end
end)

2 Likes

You could try this function.

local function MoveModel(player, cell)
	local symbol = (currentPlayer == PlayerSeat1.Occupant) and "X" or "O"
	if board[cell.x][cell.y] == "" then
		board[cell.x][cell.y] = symbol
		local symbolModel = (symbol == "X") and X:Clone() or O:Clone()
		
		local posX = cell.Position.X
		local posY = cell.Position.Y + 5
		local posZ = cell.Position.Z
		symbolModel:SetPrimaryPartCFrame(CFrame.new(Vector3.new(posX, posY, posZ)))

		symbolModel.Parent = cell

		currentPlayer = (currentPlayer == PlayerSeat1.Occupant) and PlayerSeat2.Occupant or PlayerSeat1.Occupant
	end
end
1 Like

didn’t even work still same issue

1 Like

The clickdetector.mouseclick event passes the player as the parameter.

--In the loop setting up the clickdetect events change this line
local character = player.Parent
--to this one
local character = player.Character
1 Like

Well A. it’s in replicated storage, so its not in the workspace.
So parent it to the workspace.

B. You’re not cloning a new symbol, so you’re just going to keep moving the same symbol to a different position.

1 Like

One thing I’d recommend is to use print() like on the start of movemodel() you can put print(“successfully received call : Movemodel”)use it in spots u think the code wouldn’t work properly. It will help you find the error.

1 Like

nah that was just a mistake in the code lol it’s suppose to be in replicated storage and i tried changing to workspace to fix it still same issue so i gave up. it was originally suppose to be in ServerStorage and i thought maybe changing where it is could fix it and nothing.

1 Like

Just in case, have a look at the code again and the placement of the objects (scripts, meshes, etc…) also see if it’s the right script (local or module or normal). and check if objects are spawning in.

1 Like

Does this line print when clicking the click detector? If it does, check my previous post.

1 Like

i don’t think it is spawning where i click to place the X and O every time i click on the places where i want it to be, it shows no error no issue it’s just not placing at all. would it be because it’s a server script and it can’t use clone() method for server scripts? or is there a better way i can do it instead of using clone() method?

1 Like

thank you for that. i’ll try to use that method then i’ll let you know if it worked

1 Like

just now tried that and it didn’t work. the x and o are still not being placed where i clicked

Can I see the contents of the symbol? Is the primary part anchored while the rest is unanchored? Are the parts welded together?

mm you right. i did forget to weld them i’ll try to rn real quick

just now weld them and it still didn’t work. the symbol x and O are just simply Part’s sized and shaped as the X and O within a “Model”

Can you show the explorer?

charsss

Are the primarypart properties set correctly?

No but i just now did trying it out rn

yea just did it and still same issue