当前位置:  开发笔记 > 小程序 > 正文

Java制作智能拼图游戏原理及代码

本文给大家分享的是使用Java实现智能拼图游戏的原理,以及实现的源码,推荐给大家,有需要的小伙伴可以参考下。

今天突发奇想,想做一个智能拼图游戏来给哄女友。

需要实现这些功能
第一图片自定义
第二宫格自定义,当然我一开始就想的是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

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Random;
 
public class Puzzle {
 private long step = 0;
 private int n = 6;// 宫格基数
 private int[][] puzzle;
 private int resetBlock = 0;//
 //空白块位置
 private int whiteBlockX;
 private int whiteBlockY;
  
 //当前要准备移动的块的坐标即复位块
 private int resetBlockX;
 private int resetBlockY;
  
 private boolean isPrint=false;
  
 public Puzzle() {
  init();
 }
 
 public Puzzle(int n) {
  this.n = n;
  init();
 }
 
 private void init() {
  puzzle = new int[n][n];
  for (int y = 0; y < n; y++) {
   for (int x = 0; x < n; x++) {
    puzzle[y][x] = x + y * n;
   }
  }
  whiteBlockX = n-1;
  whiteBlockY = n-1;
  int times = 100;// 打乱次数,必须是偶数
  Random random = new Random();
  while (times > 0) {
   int x0 = random.nextInt(n);
   int y0 = 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)){//最后一个不调换
     continue;
    }
    times--;
    int t = puzzle[x0][y0];
    puzzle[x0][y0] = puzzle[x1][y1];
    puzzle[x1][y1] = t;
   }
  }
//  int[][] p = {{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}};
//  puzzle = 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);
  }else 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;
   reset3(targetX);
   return;
  }else{
   initResetBlock(n-2, n-2);
   resetBlockToTarget(n-2, n-2);
   if(whiteBlockX=2){
//  }
  initResetBlock(targetX, n-1);
  resetBlockToTarget(targetX, n-2);
   
  initResetBlock(targetX, n-2);
  resetBlockToTarget(targetX+1, n-2);
  l:
  while (!(whiteBlockX==targetX && whiteBlockY==n-1)) {
   if(whiteBlockYtargetX){
    whiteBlockLeft();
    continue l;
   }
   break;
  }
  whiteBlockUp();
  swapWhiteBlockAndCurrentBlock();
   
  if(puzzle[n-2][targetX]!=resetBlock||puzzle[n-1][targetX]!=(resetBlock+n)){//没有复位成功
//   isPrint=true;
   swapWhiteBlockAndCurrentBlock();
   reset3_0();
   reset3(targetX);
  }
 }
 private void reset3_0(){
  if(resetBlockX=targetX){//右下||下;上移
    if(resetBlockX==n-1){//复位块在最右边,先左移;方便上移时统一的采用白块逆时针方式
     resetBlockLeft(targetX, targetY);
    }else{
     resetBlockUp(targetX, targetY);
    }
   }else{//左下;右移
    resetBlockRight(targetX, targetY);
   }
  }
  resetBlockToTarget(targetX, targetY);//递归
 }
  
 private void resetBlockRight(int targetX, int targetY){
  if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
   return;//退出递归
  }
  if(resetBlockX==n-1){//复位块在最右边了,无法右移,直接退出
   return;
  }
//  System.out.println("resetBlockRight");
  if(whiteBlockYresetBlockX){//右上方
     if(resetBlockY==n-1){//复位块在最低端,白块不能顺时针移动
      whiteBlockLeft();
     }else{
      whiteBlockDown();
     }
    }else{//左上方
     whiteBlockDown();
    }
   }
  }else if(whiteBlockY==resetBlockY){//左方、右方
   if(whiteBlockX0){
      sb.append(",");
     }
     sb.append(_str(String.valueOf(puzzle[y][x]), len));
    }
    sb.append("\n");
   }
   sb.append("---------------------------------------");
  }else{
   sb.append("puzzle is null");
  }
  return sb.toString();
 }
 private String _str(String str,int len){
  str=str==null?"":str;
  if(str.length()

以上所述就是本文的全部内容了,希望大家能够喜欢。

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有