Я создал своего рода игру-головоломку, цель которой - избавиться от всех белых плиток. Вы можете попробовать это в конце вопроса.
Каждый раз доска генерируется случайным образом с белыми тайлами в случайных местах на сетке 5 * 5. Вы можете щелкнуть любую плитку в этой сетке, и она будет переключать цвет ее и всех плиток, касающихся ее по бокам. Моя дилемма в том, что я не знаю, приведет ли это к невозможной доске. Каков наилучший способ проверить такие вещи?
function newgame() {
moves = 0;
document.getElementById("moves").innerHTML = "Moves: "+moves;
for (var i = 0; i < 25; i++) {
if (Math.random() >= 0.5) {
$(document.getElementsByClassName('block')[i]).toggleClass("b1 b2")
}
}
}
newgame();
function toggle(a,b) {
moves += 1;
document.getElementById("moves").innerHTML = "Moves: "+moves;
$(document.getElementsByClassName('block')[a+(b*5)]).toggleClass("b1 b2");
if (a<4) {$(document.getElementsByClassName('block')[(a+1)+(b*5)]).toggleClass("b1 b2")}
if (a>0) {$(document.getElementsByClassName('block')[(a-1)+(b*5)]).toggleClass("b1 b2")}
if (b<4) {$(document.getElementsByClassName('block')[a+((b+1)*5)]).toggleClass("b1 b2")}
if (b>0) {$(document.getElementsByClassName('block')[a+((b-1)*5)]).toggleClass("b1 b2")}
}
body {
background-color: #000000;
}
.game {
float: left;
background-color: #000000;
width: 300px;
height: 300px;
overflow: hidden;
overflow-x: hidden;
user-select: none;
display: inline-block;
}
.container {
border-color: #ffffff;
border-width: 5px;
border-style: solid;
border-radius: 5px;
width: 600px;
height: 300px;
text-align: center;
}
.side {
float: left;
background-color: #000000;
width: 300px;
height: 300px;
overflow: hidden;
overflow-x: hidden;
user-select: none;
display: inline-block;
}
.block {
transition: background-color 0.2s;
float: left;
}
.b1:hover {
background-color: #444444;
cursor: pointer;
}
.b2:hover {
background-color: #bbbbbb;
cursor: pointer;
}
.row {
width: 300px;
overflow: auto;
overflow-x: hidden;
}
.b1 {
display: inline-block;
height: 50px;
width: 50px;
background-color: #000000;
border-color: #000000;
border-width: 5px;
border-style: solid;
}
.b2 {
display: inline-block;
height: 50px;
width: 50px;
background-color: #ffffff;
border-color: #000000;
border-width: 5px;
border-style: solid;
}
.title {
width: 200px;
height: 50px;
color: #ffffff;
font-size: 55px;
font-weight: bold;
font-family: Arial;
display: table-cell;
vertical-align: middle;
}
.button {
cursor: pointer;
width: 200px;
height: 50px;
background-color: #000000;
border-color: #ffffff;
border-style: solid;
border-width: 5px;
color: #ffffff;
font-size: 25px;
font-weight: bold;
font-family: Arial;
display: table-cell;
vertical-align: middle;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
.button:hover {
background-color: #ffffff;
color: #000000;
}
.sidetable {
padding: 30px 0px;
height: 200px;
}
#moves {
width: 200px;
height: 50px;
color: #aaaaaa;
font-size: 30px;
font-weight: bold;
font-family: Arial;
display: table-cell;
vertical-align: middle;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<center>
<div class="container">
<div class="game"><div class="row"><div onclick="toggle(0,0);" class="block b1"></div><div onclick="toggle(1,0);" class="block b1"></div><div onclick="toggle(2,0);" class="block b1"></div><div onclick="toggle(3,0);" class="block b1"></div><div onclick="toggle(4,0);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,1);" class="block b1"></div><div onclick="toggle(1,1);" class="block b1"></div><div onclick="toggle(2,1);" class="block b1"></div><div onclick="toggle(3,1);" class="block b1"></div><div onclick="toggle(4,1);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,2);" class="block b1"></div><div onclick="toggle(1,2);" class="block b1"></div><div onclick="toggle(2,2);" class="block b1"></div><div onclick="toggle(3,2);" class="block b1"></div><div onclick="toggle(4,2);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,3);" class="block b1"></div><div onclick="toggle(1,3);" class="block b1"></div><div onclick="toggle(2,3);" class="block b1"></div><div onclick="toggle(3,3);" class="block b1"></div><div onclick="toggle(4,3);" class="block b1"></div></div><div class="row"><div onclick="toggle(0,4);" class="block b1"></div><div onclick="toggle(1,4);" class="block b1"></div><div onclick="toggle(2,4);" class="block b1"></div><div onclick="toggle(3,4);" class="block b1"></div><div onclick="toggle(4,4);" class="block b1"></div></div></div>
<div class="side">
<center class="sidetable">
<div class="title">Tiles</div>
<br>
<div class="button" onclick="newgame()">New Game</div>
<br><br>
<div id="moves">Moves: 0</div>
</center>
</div>
</div>
</center>
game-design
logic
puzzle
playtesting
Qwerty
источник
источник
Ответы:
Это тип игры, в которой один и тот же ход, выполненный дважды, возвращает доску к ее предыдущему состоянию. Таким образом, чтобы убедиться, что доска разрешима, генерируйте ее, играя в обратном порядке. Начните с решенной (пустой) доски, затем начните программным способом «щелкать» случайным образом либо определенное количество раз, либо до тех пор, пока на доске не появится желаемое количество белых квадратов. Одно из решений состоит в том, чтобы просто выполнить те же шаги в обратном порядке. Могут существовать другие более короткие решения, но у вас гарантированно будет хотя бы одно.
Другое, гораздо более сложное решение, состоит в том, чтобы определить алгоритм решения, который проходит через все возможные состояния игры с вашей начальной позиции, чтобы попытаться найти решение. Это займет намного больше времени для реализации и запуска, но позволит доскам генерироваться действительно случайным образом. Я не буду вдаваться в подробности этого решения, потому что это просто не очень хорошая идея.
источник
Хотя приведенные выше ответы являются умными (и, вероятно, как бы я это сделал в любом случае), эта конкретная игра очень хорошо известна. Она называется Lights Out и была математически решена. Решение существует тогда и только тогда, когда две суммы различных элементов (приведенные на странице википедии) добавляют к нулю mod 2 (то есть четное число). В общем, небольшая линейная алгебра должна дать аналогичные условия решения для игр на любой доске.
источник
При создании вашей головоломки идите наоборот.
Вместо того, чтобы случайным образом выбирать плитки и поворачивать их с белого на черный, начните с чистого листа, затем выберите плитки, но вместо того, чтобы превратить эту плитку в черную, сделайте так, как если бы пользователь выбрал ее, в результате чего все другие плитки перевернутся вокруг него.
Таким образом, вы гарантированно получите хотя бы одно решение: пользователю придется отменить то, что сделал ваш «AI» игрок, чтобы создать уровень.
источник
Эд и Александр имеют право на это.
Но если вы действительно хотите знать , если каждое решение возможно, есть способы.
Есть конечное число возможных головоломок
Двойной щелчок по одному и тому же квадрату приводит к тому же результату, что и к щелчку по нему вообще, независимо от того, сколько кликов было сделано между ними. Это означает, что каждое решение можно описать, задав каждому квадрату двоичное значение «нажал» или «не нажал». Точно так же, каждая головоломка может быть описана, давая каждому квадрату двоичное значение «переключено» или «не переключено». Это означает, что есть 2 ^ 25 возможных загадок и 2 ^ 25 возможных решений. Если вы можете доказать, что каждое решение решает уникальную головоломку, то должно быть решение для каждой головоломки. Точно так же, если вы найдете два решения, которые решают одну и ту же головоломку, тогда не может быть решения для каждой головоломки.
Кроме того, 2 ^ 25 составляет 33 554 432. Это довольно много, но это не неуправляемое число. Хороший алгоритм и приличный компьютер, вероятно, могут перебить это через пару часов, особенно если учесть, что половина головоломок является противоположностью другой половины.
источник
Обобщенный ответ:
источник
Другие уже упоминали способы выяснить, разрешима ли ваша случайно сгенерированная головоломка. вопрос, который вы также должны задать, заключается в том, хотите ли вы на самом деле генерировать случайные головоломки.
Все случайно созданные головоломки имеют один и тот же основной недостаток: их сложность в значительной степени непредсказуема. Возможные головоломки, которые вы можете получить, могут варьироваться от уже решенных, до тривиальных (решение очевидно), до сложных (решение не очевидно), до невозможных (головоломка вообще не разрешима). Поскольку сложность непредсказуема, она создает для игрока неудовлетворительный опыт, особенно если он делает несколько головоломок подряд. Они вряд ли получат плавную кривую сложности, которая может заставить их скучать или разочаровываться в зависимости от того, какие головоломки они получают.
Другая проблема генерации случайных чисел заключается в том, что время, необходимое для инициализации головоломки, непредсказуемо. Вообще говоря, вы сразу получите (почти) решаемую головоломку, но, если повезет, ваши случайно сгенерированные головоломки могут закончиться серией неразрешимых головоломок.
Один из способов решения обоих этих вопросов - наличие предопределенных векторов каждой решаемой головоломки, сгруппированных по группам сложности, и затем выбор случайной головоломки из решаемых головоломок в зависимости от сложности. Таким образом, вы будете уверены, что каждая головоломка разрешима, что трудность предсказуема и что генерация будет выполняться в постоянное время.
источник