Обзор
Я пытаюсь построить доску Ti c Ta c (см. на CodePen ), но я хочу, чтобы размер платы был переменным. Я написал базовую c 3x3
сетку, которая следует стандартным правилам как часть пуристской задачи ( создана с использованием чистых HTML, CSS и JS, внешние библиотеки не разрешены ). Но я хочу еще больше испытать себя в веб-сфере, превратив ее в совершенно нового монстра.
Проблема
Доска, которую я создал имеет закругленные границы, и хотя я мог их удалить, я думаю, что это добавляет визуальной привлекательности проекту, поэтому я бы предпочел оставить их, а с определенным количеством квадратов это просто:
.board > div:first-child { border-top-left-radius: 5px; }
.board > div:nth-child(3) { border-top-right-radius: 5px; }
.board > div:nth-child(7) { border-bottom-left-radius: 5px; }
.board > div:last-child { border-bottom-right-radius: 5px; }
Однако изменение размера платы приводит к изгибу квадратов правый верхний и левый нижний .
Попытка решения
Сначала я рассмотрел размер сетки, используя переменную во встроенном стиле платы, например:
.board {
grid-template-columns: repeat(var(--board-size), calc(100% / var(--board-size)));
grid-template-rows: repeat(var(--board-size), calc(100% / var(--board-size)));
}
<div id="board" class="board" style="--board-size: 3;"></div>
Думая, что это просто скромное изящное и удивительное решение проблемы, я затем попытался применить его к :nth-child(An [] B)
, который с треском провалился (и гораздо менее изящно). Я считаю, что невозможно использовать nth-child
так, как я пытался:
.board > div:nth-child(var(--board-size)) { border-top-right-radius: 5px; }
.board > div:nth-child(var(--board-size) * var(--board-size) - var(--board-size)) { border-bottom-left-radius: 5px; }
Я также знаю, что создание дополнительных переменных там не будет работать просто потому, что первая строка не работают, поэтому создание дополнительной переменной для второй строки тоже не сработает.
Мой код
Здесь просто в качестве ориентира это мой код ( раздел радиуса границы находится в строках 59-62 ), хотя он, скорее всего, изменится к тому времени, когда будет опубликован ответ, когда я попробую больше решений.
var gameOver = false;
var whoseTurnIsIt = "x";
var winningIndexCombination = undefined;
const board = document.getElementById("board");
const squares = board.getElementsByTagName("DIV");
const message = document.getElementById("message")
const winningIndexCombinations = {
horizontal: {
top: [0, 1, 2],
middle: [3, 4, 5],
bottom: [6, 7, 8]
},
vertical: {
left: [0, 3, 6],
middle: [1, 4, 7],
right: [2, 5, 8]
},
diagonal: {
topLeftToBottomRight: [0, 4, 8],
topRightToBottomLeft: [2, 4, 6]
},
cat: [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]
};
function tryPlaySquare(sender) {
if (gameOver) {
alert("The game has ended. Please restart the game to play.");
return;
}
if (sender.innerText === "") {
sender.innerText = whoseTurnIsIt.toUpperCase();
if (checkForWin()) {
registerWin();
return;
}
changePlayer();
} else
alert("This square is taken! Please choose another.");
}
function changePlayer() {
whoseTurnIsIt = whoseTurnIsIt == "x" ? "o" : "x";
document.getElementById("message").innerText = whoseTurnIsIt.toUpperCase() + " is currently playing.";
}
function checkForWin() {
let squareValues = [];
for (let i = 0; i < squares.length; i++)
squareValues.push(squares[i].innerText);
if (checkHorizontalCombinationsForWin(squareValues))
return true;
else if (checkVerticalCombinationsForWin(squareValues))
return true;
else if (checkDiagonalCombinationsForWin(squareValues))
return true;
else if (checkForCatWin(squareValues)) {
whoseTurnIsIt = "kat";
return true;
}
return false;
}
function registerWin() {
if (whoseTurnIsIt === "kat") {
for (let i = 0; i < winningIndexCombination.length; i++)
squares[winningIndexCombination[i]].classList.add('kat');
} else {
for (let i = 0; i < winningIndexCombination.length; i++)
squares[winningIndexCombination[i]].classList.add('winner');
}
message.innerText = whoseTurnIsIt.toUpperCase() + ' wins the game!';
winningIndexCombination = undefined;
whoseTurnIsIt = "x";
gameOver = true;
}
function checkHorizontalCombinationsForWin(squareValues) {
if (checkIndiciesForMatch(squareValues, winningIndexCombinations.horizontal.top))
winningIndexCombination = winningIndexCombinations.horizontal.top;
else if (checkIndiciesForMatch(squareValues, winningIndexCombinations.horizontal.middle))
winningIndexCombination = winningIndexCombinations.horizontal.middle;
else if (checkIndiciesForMatch(squareValues, winningIndexCombinations.horizontal.bottom))
winningIndexCombination = winningIndexCombinations.horizontal.bottom;
return winningIndexCombination !== undefined;
}
function checkVerticalCombinationsForWin(squareValues) {
if (checkIndiciesForMatch(squareValues, winningIndexCombinations.vertical.left))
winningIndexCombination = winningIndexCombinations.vertical.left;
else if (checkIndiciesForMatch(squareValues, winningIndexCombinations.vertical.middle))
winningIndexCombination = winningIndexCombinations.vertical.middle;
else if (checkIndiciesForMatch(squareValues, winningIndexCombinations.vertical.right))
winningIndexCombination = winningIndexCombinations.vertical.right;
return winningIndexCombination !== undefined;
}
function checkDiagonalCombinationsForWin(squareValues) {
if (checkIndiciesForMatch(squareValues, winningIndexCombinations.diagonal.topLeftToBottomRight))
winningIndexCombination = winningIndexCombinations.diagonal.topLeftToBottomRight;
else if (checkIndiciesForMatch(squareValues, winningIndexCombinations.diagonal.topRightToBottomLeft))
winningIndexCombination = winningIndexCombinations.diagonal.topRightToBottomLeft;
return winningIndexCombination !== undefined;
}
function checkForCatWin(squareValues) {
for (let i = 0; i < squareValues.length; i++)
if (squareValues[i].length === 0)
return false;
winningIndexCombination = winningIndexCombinations.cat;
return true;
}
function checkIndiciesForMatch(squareValues, indicies) {
for (let i = 0; i < indicies.length; i++)
if (squareValues[indicies[i]].length === 0)
return false;
return (
squareValues[indicies[0]] === squareValues[indicies[1]] &&
squareValues[indicies[1]] === squareValues[indicies[2]]
);
}
@import url('https://fonts.googleapis.com/css2?family=Heebo:wght@900&family=Open+Sans+Condensed:wght@300&display=swap');
* { transition: 0.2s linear all; }
html, body {
margin: 0;
height: 100%;
}
body {
display: flex;
align-items: center;
flex-direction: column;
background: #141E30;
background: -webkit-linear-gradient(to right, #243B55, #141E30);
background: linear-gradient(to right, #243B55, #141E30);
}
.message {
color: #fff;
font-size: 35px;
font-family: 'Open Sans Condensed', sans-serif;
margin-bottom: 10px;
}
span.message {
display: inline-flex;
align-items: center;
font-size: 20px;
}
input[type=number] {
background-color: #fffc;
padding: 10px;
border: none;
border-radius: 3px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
margin-left: 5px;
width: 35px;
}
.board {
width: 500px;
height: 500px;
background-color: #fff5;
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
display: grid;
grid-template-columns: repeat(var(--board-size), calc(100% / var(--board-size)));
grid-template-rows: repeat(var(--board-size), calc(100% / var(--board-size)));
}
.board > div {
position: relative;
display: inherit;
border: 1px solid #0005;
cursor: pointer;
place-items: center;
font-size: 120px;
font-family: 'Heebo', sans-serif;
color: #0008;
}
.board > div:hover {
background-color: #fffa;
}
.board > div:nth-child(1) { border-top-left-radius: 5px; }
.board > div:nth-child(3) { border-top-right-radius: 5px; }
.board > div:nth-child(7) { border-bottom-left-radius: 5px; }
.board > div:nth-child(9) { border-bottom-right-radius: 5px; }
.board > div:nth-child(1),
.board > div:nth-child(4),
.board > div:nth-child(7) {
border-left: none;
}
.board > div:nth-child(1),
.board > div:nth-child(2),
.board > div:nth-child(3) {
border-top: none;
}
.board > div:nth-child(3),
.board > div:nth-child(6),
.board > div:nth-child(9) {
border-right: none;
}
.board > div:nth-child(7),
.board > div:nth-child(8),
.board > div:nth-child(9) {
border-bottom: none;
}
.board > div.winner {
background: #11998e;
background: -webkit-linear-gradient(to right, #11998e, #38ef7d, #11998e);
background: linear-gradient(to right, #11998e, #38ef7d, #11998e);
}
.board > div.kat {
background: #ee0979;
background: -webkit-linear-gradient(to right, #ee0979, #ff6a00, #ee0979);
background: linear-gradient(to right, #ee0979, #ff6a00, #ee0979);
}
.board > div.winner,
.board > div.kat {
background-size: 200% 200%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: gradient-animation 3s ease-in-out infinite;
}
.board > div.winner::after,
.board > div.kat::after {
position: absolute;
}
@keyframes gradient-animation {
0% {
background-position: 15% 0%;
}
50% {
background-position: 85% 100%;
}
100% {
background-position: 15% 0%;
}
}
<p id="message" class="message">X is currently playing.</p>
<div id="board" class="board" style="--board-size: 3;">
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
<div onclick="tryPlaySquare(this);"></div>
</div>
Текущая работа
Поскольку я уже пишу код для динамически построить сетку, я просто назначаю класс CSS для углов правый верхний и левый нижний . Это не то решение, которое я в конечном итоге хочу, но пока оно меня сдерживает. Также есть идея переключиться на большее количество таблиц или создать настройку типа строка / столбец со встроенными div
элементами, против чего я против, поскольку display: grid
позаботится об этом в данном случае.
Вопрос
Использование CSS ( не JavaScript, так как я могу это легко сделать ), возможно ли, чтобы квадраты верхний правый и нижний левый имели соответствующие закругленные границы, независимо от размера сетки?
ПРИМЕЧАНИЕ : пожалуйста, игнорируйте любые ошибки времени выполнения в JavaScript, поскольку они не имеют отношения к этому сообщению.