Сегодня мне пришла в голову внезапная идея сделать умную головоломку для моей девушки.
Эти функции надо реализовать, первое - настроить картинку, второе - настроить сетку. Конечно, то, о чем я думал вначале, было 3*3 4*4 5*5, и я не использовал. сетка типа 3*5.
В-третьих, реализовать функцию автоматической головоломки. Я считаю, что все знают, что женщины не очень хороши в играх, поэтому эта функция автоматической головоломки необходима.
Про другие дисквалификации и рейтинги писать не буду!
Теперь возникает ключевой вопрос. Кажется, требования для реализации функции автоматической головоломки немного высоки! Могут ли компьютеры быть похожими на людей и могут только:
Давайте сначала перейдем к сути
На самом деле головоломка — это всего лишь вопрос составления:
Существует определение перестановки: в расположении 1, 2,...,n, если передняя и задняя позиции пары чисел расположены в обратном порядке, то есть переднее число больше заднего, тогда они называются обратным порядком. Общее количество обратных порядков в перестановке называется обратным порядковым номером этой перестановки. Расположение, в котором обратное число является четным, называется четным расположением; расположение, в котором обратное число является нечетным, называется нечетным расположением. Например, в 2431 числа 21, 43, 41 и 31 расположены в обратном порядке, а обратный порядок равен 4, что является четным расположением.
Вот еще одно определение: при обмене двух чисел в перестановке меняется ее четность.
Все приведенные выше определения взяты из «Высшей алгебры».
Расположение головоломки должно быть четным. Это можно найти в моих ссылках.
Вот так реализован мой пазл!
напишу позже
Ссылка: http://en.wikipedia.org/wiki/Fifteen_puzzle.
Автоматическая головоломка:
Прежде всего, для автоматических головоломок должны быть определенные правила. Согласно моему опыту, для решения головоломки в разных областях используются разные правила головоломки, поэтому:
Моя карта сетки разделена на 4 области (если карта сетки имеет n*n сеток)
Первая область: диапазон координат x от 0 до n-2, диапазон координат y от 0 до n-3.
Вторая область: координата x n-1, диапазон координат y от 0 до n-3.
Третья область: диапазон координат x от 0 до n-3, диапазон координат y от n-2 и n-1.
Четвертая область: диапазон координат x от n-2 до n-1, диапазон координат y от n-2 до n-1, то есть последние четыре ячейки;
Каждую область можно пройти в соответствии с правилами соответствующей области.
Puzzle.java
импорт java.io.FileNotFoundException; импорт java.io.PrintStream; импорт java.io.UnsupportedEncodingException; импорт java.util.Random; головоломка общественного класса {частный длинный шаг = 0; частный int n = 6; // База платформы Private int [][] Puzzle; Private int resetBlock = 0;// //Позиция пустого блока Private int whiteBlockX; whiteBlockY; //Координаты блока сброса, который в данный момент нужно переместить, — это блок сброса. Private int resetBlockY; Private boolean isPrint=false; public Puzzle() { init(); public Puzzle(int n) { this. n = n; init(); } Private void init() {головоломка = новый int[n][n] для (int y = 0; y < n; y++) {for (int x = 0; x < n; x++) {головоломка[y][x] = x + y * n; } } whiteBlockX = n-1; whiteBlockY = int times = 100; // Количество перетасовок должно быть четным. Случайное число = new Random(); while (times > 0) { int x0 = random.nextInt(n); random.nextInt(n); int x1 = random.nextInt(n); int y1 = random.nextInt(n); if (x0 != x1 && y0!=y1) {// Гарантированная четная сортировка if((x0 = =n-1&&y0==n-1)||(x1==n-1&&y1==n-1)){//Последний не заменяетсяпродолжить } times--; int t = головоломка[x0][y0] = головоломка[x1][y1]; головоломка[x1][y1] = t }// int[][] р = {{22,9,1,5,0,25},{// 33,23,20,26,18,21},{// 6 ,16,17,10,34,31},{// 19,28,32,7 ,3 ,2},{// 11,4 ,12,14,27,24},{// 15,29 ,30,8 ,13,35}};//головоломка = p; } public void sort(){ for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (x == n - 1 && y == n - 1) {//Последний пуст, } else { reset(x, y ) } } } } //Сбрасываем блок в целевую позицию. Private void reset(int targetX, int targetY) { //Находим текущую позицию блока сброса initResetBlock(targetX, targetY) /* *); Последовательность сброса — слева направо, сверху вниз* Метод перемещения — сначала вверх, затем влево* Текущий блок сброса, положение, которое он хочет сбросить, можно разделить на четыре ситуации* 1. Не в ни крайняя правая строка, ни две нижние строки * 2. Самая правая строка x=n-1, но не две нижние строки * 3. Две нижние строки y=n-2, но не самая правая строка * 4. Даже самая правая строка; крайняя правая строка также является двумя нижними строками ОК*/ if(targetX < n-1 && targetY < n-2){ if(resetBlockX==targetX&&resetBlockY==targetY){//Позиция правильная без перемещения return;//Выходим из рекурсии} resetBlockToTarget(targetX, targetY }); иначе if( targetX==n-1 && targetY < n-2){//Второй случай if(resetBlockX==targetX&&resetBlockY==targetY){//Позиция правильная без перемещения return; //Выходим из рекурсии} reset2(targetX, targetY }else if(targetX <); n- 2 && targetY == n-2){// isPrint = true; сброс3 (targetX) return; resetBlockToTarget(n-2, n-2); if(whiteBlockX<n-1){ whiteBlockRight(); } if(whiteBlockY<n-1){ whiteBlockDown(); } if(whiteBlockX==n-1&&whiteBlockY==n -1) { return; } } сброс(targetX, targetY);//рекурсия} Private void initResetBlock(int targetX,int targetY){ resetBlock = targetX + targetY * n for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (puzzle[y][x] == resetBlock) {// x, y — позиция блока сброса. if(targetX>=2){// } initResetBlock(targetX, n-1); сбросBlockToTarget(targetX, n-2); initResetBlock(targetX, n-2); сбросBlockToTarget(targetX+1, n-2); : while (!(whiteBlockX==targetX && whiteBlockY==n-1)) { if(whiteBlockY<n-1){ whiteBlockDown(); продолжить l; } if(whiteBlockX>targetX) {whiteBlockLeft(); продолжить l; } whiteBlockUp(); if(puzzle[n-2][targetX]!=resetBlock|| Puzzle[n-1][targetX]!=(resetBlock+n)){//Сброс не удался// isPrint = true; swapWhiteBlockAndCurrentBlock (); сброс3 (targetX); } } частный сброс3_0 () { if (resetBlockX <n-1) { whiteBlockDown (); whiteBlockRight (); swapWhiteBlockAndCurrentBlock (); возврат } частный; void reset2_3(){ if(whiteBlockX==resetBlockX && whiteBlockY==resetBlockY+1){ return;//Если условия выполнены, выходим из рекурсии} //Белый блок может быть слева, внизу слева или внизу сторона блока сброса if(whiteBlockY= =resetBlockY){//left whiteBlockDown() }else if(whiteBlockX <resetBlockX){//нижний левый whiteBlockRight(); }else { whiteBlockUp(); } reset2_3();//recursion} Private void reset2_2(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//2. Переместите блок сброса в целевую позицию. Возврат ниже;//Выходим из рекурсии} //Возможные позиции блока сброса, целевая позиция слева, прямо под, внизу слева if(resetBlockX==targetX){//Переместиться прямо ниже и вверх setBlockUp(targetX, targetY); Двигайтесь вправо, а затем вверх. resetBlockRight(targetX, targetY } reset2_2(targetX, targetY);//recursion} Private void reset2(int targetX, int targetY){ if (resetBlockX == target Нижняя часть не является блоком сброса, переместите белый блок в целевую позицию* 2. Переместите блок сброса непосредственно под целевую позицию* 3. Переместите белый блок ниже блока сброса* 4. Сбросьте в соответствии с к предписанным шагам*/ //Первый шаг if(whiteBlockX==targetX&& whiteBlockY==targetY){ if(whiteBlockX==resetBlockX&&whiteBlockY==resetBlockY+1){//Блок сброса находится ниже swapWhiteBlockAndCurrentBlock(); return }else{ whiteBlockDown(); } } //Второй шаг — переместить блок сброса непосредственно под целевую позицию. reset2_2(targetX, targetY+1); //Третий шаг перемещает белый блок ниже блока сброса reset2_3(); //Четвертый шаг сбрасывает swapWhiteBlockAndCurrentBlock() в соответствии с предписанными шагами; whiteBlockUp(); whiteBlockDown(); ); белыйБлокВверх(); белыйБлокПраво(); белыйБлокВниз(); whiteBlockLeft(); whiteBlockUp(); whiteBlockRight(); swapWhiteBlockAndCurrentBlock(); } Private void resetBlockToTarget(int targetX, int targetY) { if(resetBlockX==targetX&&resetBlockY==targetY){//Исправить позицию без перемещения возврата ;//Выходим из рекурсии} if(resetBlockY==targetY){//положительный левый сбросBlockLeft(targetX, targetY }else{//нижний левый, нижний, нижний правый if(resetBlockX>=targetX){//нижний правый||вниз; (resetBlockX==n-1){//Блок сброса находится справа, сначала переместите его влево, чтобы облегчить движение вверх, белый блок против часовой стрелки. resetBlockLeft(targetX, targetY); }else{resetBlockUp(targetX, targetY); }else{//Lower left; , int targetY){ if (resetBlockX == target ; }// System.out.println("resetBlockRight"); if(whiteBlockY<resetBlockY){//Выше if(whiteBlockY<resetBlockY-1){//Несколько строк выше whiteBlockDown(); }else{//Строка выше if(whiteBlockX<resetBlockX+1){//Вверху слева и прямо над whiteBlockRight (); }else{//верхний правый whiteBlockDown(); } } }else; if(whiteBlockY==resetBlockY){//Та же строка if(whiteBlockX<resetBlockX){//Левая сторона if(whiteBlockY==n-1){//В конце вы можете идти только вверх whiteBlockUp() }else; { whiteBlockDown (); } }else{//right if(whiteBlockX==resetBlockX+1) { swapWhiteBlockAndCurrentBlock(); return;//Выход из рекурсии}else{ whiteBlockLeft(); } }else{//Bottom if(whiteBlockX <= resetBlockX){//Внизу слева, внизу whiteBlockRight(); }else{//Внизу справа whiteBlockUp(); } } resetBlockRight(targetX, targetY);//рекурсия} Private void resetBlockLeft(int targetX, int targetY){ if (resetBlockX == target / System.out.println("resetBlockLeft"); if(whiteBlockY<resetBlockY){//Выше if(whiteBlockY<resetBlockY-1){//Несколько строк выше whiteBlockDown(); }else{//Строка выше if(whiteBlockX==resetBlockX){//Выше if(whiteBlockX); = =n-1){//В крайнем правом углу белый блок нельзя переместить вправо, его можно переместить только влево whiteBlockLeft() }else{; if(resetBlockY==n-1){//Блок сброса находится на самом нижнем конце, белый блок не может перемещаться по часовой стрелке whiteBlockLeft(); }else{ whiteBlockRight(); } }else if(whiteBlockX>resetBlockX){/ /Верхний правый if(resetBlockY==n-1){//Блок сброса находится на самом нижнем конце, белый блок не может перемещаться по часовой стрелке whiteBlockLeft() }else{; whiteBlockDown(); } }else{//верхний левый whiteBlockDown(); } } }else if(whiteBlockY==resetBlockY){//left, right if(whiteBlockX<resetBlockX){//left if(whiteBlockX= =resetBlockX- 1){//Один пробел слева swapWhiteBlockAndCurrentBlock();//Выходим из возврата из рекурсии; }else{ whiteBlockRight(); } }else{//Right if(whiteBlockY==n-1){//Он находится внизу и не может двигаться вниз. Можно переместить только вверх whiteBlockUp(); }else{ whiteBlockDown(); } }else{//нижний левый, нижний, нижний правый if(whiteBlockX<resetBlockX){//нижний левый if(whiteBlockX==resetBlockX-1) { whiteBlockUp( ); }else{ whiteBlockRight() } }else{//Bottom, нижний правый whiteBlockLeft(); } } resetBlockLeft(targetX, targetY);//Recursion} Private void resetBlockUp(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//Позиция правильная без перемещения return;//Выход из рекурсии} if(resetBlockY==0){//Блок сброса достиг вершины и не может быть перемещен вверх return }//; System.out.println("resetBlockUp"); if (whiteBlockY <resetBlockY) {//Above if(whiteBlockY <resetBlockY - 1){//Несколько строк выше whiteBlockDown(); }else{//Строка выше if(whiteBlockX); = = resetBlockX){//Белый блок и блок сброса находятся в одном столбце (вертикальный столбец) Белый блок и блок сброса напрямую меняются местами swapWhiteBlockAndCurrentBlock();//Выходим из рекурсии return }else{ if(whiteBlockX<resetBlockX){//Белый блок находится слева от блока сброса; правый whiteBlockRight(); }else{/ /Белый блок находится справа от блока сброса; белый блок перемещается влево whiteBlockLeft(); } } } else if (whiteBlockY; == resetBlockY) {//Белый блок и блок сброса находятся в одной строке; белый блок перемещается вверх if(whiteBlockX<resetBlockX){//Вперед влево if(whiteBlockX<resetBlockX-1){//Вперед влево multi -cell whiteBlockRight(); } else{//Один квадрат влево if(whiteBlockY==n-1){//Конец whiteBlockUp(); if(resetBlockX==n-1){//Блок сброса находится крайним справа и не может перемещаться против часовой стрелки. По часовой стрелке можно перемещать только белый блок whiteBlockUp(); }else{ whiteBlockDown(); } }else{/; /правый белыйBlockUp (); }else{//Белый блок находится под блоком сброса. Белый блок должен переместиться вверх за блок сброса. Белый блок движется против часовой стрелки к вершине белого блока.//Три ситуации: нижний левый, нижний, нижний. right if(whiteBlockX<=resetBlockX) {//Внизу слева, вниз белый блок перемещается вправо i; f(resetBlockX==n-1){//Блок сброса находится крайне справа и не может перемещаться против часовой стрелки. По часовой стрелке можно перемещать только белый блок if(whiteBlockX==resetBlockX){//Чуть ниже whiteBlockLeft(); }else{//нижний левый whiteBlockUp(); } }else{ whiteBlockRight(); }else{//нижний белый блок перемещается вверх whiteBlockUp(); } } resetBlockUp(targetX, targetY);//Recursion} / /Белый блок и сброс позиций обмена блоками Private void swapWhiteBlockAndCurrentBlock(){step++; int tempX = whiteBlockX,tempY = whiteBlockY; int temp = головоломка[whiteBlockY][whiteBlockX] = головоломка[resetBlockY][resetBlockX]; головоломка[resetBlockY][resetBlockX] = temp; whiteBlockX = сбросBlockX; whiteBlockY = resetBlockX; ; сбросБлокY = TempY; println("своп"); } Private void whiteBlockDown(){ шаг++; int temp = головоломка[whiteBlockY][whiteBlockX]; головоломка[whiteBlockY][whiteBlockX] = головоломка[whiteBlockY+1][whiteBlockX]; ][whiteBlockX] = temp; whiteBlockY++; println("↓"); whiteBlockUp(){ шаг++; int temp = головоломка[whiteBlockY][whiteBlockX]; головоломка[whiteBlockY][whiteBlockX] = головоломка[whiteBlockY-1][whiteBlockX]; головоломка[whiteBlockY-1][whiteBlockX] = temp; ; println("↑"); } Private void whiteBlockLeft(){step++; головоломка[whiteBlockY][whiteBlockX]; головоломка[whiteBlockY][whiteBlockX] = головоломка[whiteBlockY][whiteBlockX-1]; головоломка[whiteBlockY][whiteBlockX-1] = temp; whiteBlockX--; println(" ←"); частный недействительный whiteBlockRight () {шаг ++ int temp = головоломка [whiteBlockY] [whiteBlockX]; головоломка[whiteBlockY][whiteBlockX] = головоломка[whiteBlockY][whiteBlockX+1]; головоломка[whiteBlockY][whiteBlockX+1] = temp; whiteBlockX++; println("→" } @Override public String toString() { StringBuilder sb = новый StringBuilder(); sb.append("resetBlock=("+resetBlock+","+resetBlockX+","+resetBlockY+")/n"); if(puzzle!=null){ int len = String.valueOf(n*2-1) ). length(); for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if(x>0){ sb.append(","); } sb.append(_str(String.valueOf(puzzle[y][x]), len)); } sb.append("/n") ; } sb.append("---------------------------------------"); else { sb.append("головоломка равна нулю" } return sb.toString(); } Private String _str(String str,int len){str=str==null?"":str; if(str.length()<len){ return _str(str+" ", len } return str; частный void println(String str) { if(isPrint) { System.out.println(str); System.out.println(this); } public static void main(String[] args) выдает FileNotFoundException, UnsupportedEncodingException {// System.setOut(new PrintStream("e:/puzzle.txt","UTF-8")); p.sort(); } catch (Исключение е) { e.printStackTrace(); System.out.println("Исключение:"); } наконец { System.out.println(p } }};
Выше приведено все содержание этой статьи, надеюсь, она вам всем понравится.