можно ли писать функции внутри методов
Можно, но надо понимать, что для читабельности и производительности этого лучше не делать (функция будет создаваться при каждом вызове метода).
два класса: Игрок и Игра
Лучше было бы разделить логику и отображение, сделать класс Game, который отвечает за переход хода и просчет выигрыша, и Field, который отвечает за работу с DOM и отображение.
Класс Player содержит только одно поле и никаких методов, его полезность крайне сомнительна. По факту его можно свести к Game#currentPlayer.
Смысл класса в том, что он является самодостаточной сущностью, а у вас методы постоянно обращаются к глобальным переменным.
ceil[i].addEventListener("click", currentStep);
Почитайте про event delegation — можно и нужно обойтись одним обработчиком на общем родителе.
z === "X"
? dataX.push(num) && this.classList.add("x")
: dataO.push(num) && this.classList.add("o");
Длинные тернарные операторы плохо читаются, и использовать их надо только там, где вам нужно выражение (которое возвращает значение). Сделайте просто if-else ВЕЗДЕ, у вас нет ни одного места, где бы он был нужен:)
this.getAttribute("data-ceil")
— просто
this.dataset.ceil
(кстати, это называется cell)