智商200以上才能通关的小游戏“智慧翻转”的模拟运算程序

上周末+2个晚上,编写了“智慧翻转”对应的随机、递归、循环共3个版本的模拟程序,然后开通了博客,又等了3天,终于可以发布了。
建议在看以下代码之前,先去了解下这个游戏,至少明白规则,否则很难体会到其中的精妙之处。
package wisdom;

import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import wisdom.data.Composition;
import wisdom.data.Data;
import wisdom.data.Point;

/**
* @author xhl
* add data 2013-3-12
*/
public class Wisdom {//智慧翻转 循环迭代版

private static int clickNum;//点击次数范围
private static int[][] details;//原始数据
private static List<Point> dataPointList=new LinkedList<Point>();//可点集合
private static int compositionsNum=0;//循环中存储的最多棋局数目
private static int failedCount=0;//在规定次数之内未能成功的落子坐标轨迹数目
private static List<List<Point>> trajectoryList=new LinkedList<List<Point>>();//落子坐标轨迹集合
private static Set<Set<Point>> trajectorySet=new HashSet<Set<Point>>();//落子坐标轨迹集合 去重合并

// 数据初始化
private static void initialization() {
List<Point> lockPointList=new LinkedList<Point>();//锁点集合
// 1:2 2-4:3 5-8:4 9-12:5 13-16:6 17-20:7 21-22:8
clickNum=2;//TODO
details=Data.details_3_1;//TODO
arrayIntoCollection(Data.lockPoints_3_1,lockPointList);//TODO
// 非空非锁 可点
for (int i = 0; i < details.length; i++) {
for (int j = 0; j < details.length; j++) {
if(details[i][j]==0) continue;
Point p=new Point(i, j);
if(!lockPointList.contains(p)) dataPointList.add(p);
}
}
// 以上锁点数组 以下可点数组
// arrayIntoCollection(dataPoints_4_1,dataPointList);
}

// 数组转化为集合
private static void arrayIntoCollection(String[] points,List<Point> pointList) {
for (String point : points) {
String[] ij=point.split(",");
int i=Integer.parseInt(ij[0]);
int j=Integer.parseInt(ij[1]);
pointList.add(new Point(i, j));
}
}

public static void main(String[] args) {
initialization();
derivativesOfCompositions();
informationDisplay();
}

// 信息展示
private static void informationDisplay() {
int successNum=trajectoryList.size();
String rate=new DecimalFormat("0.000").format(successNum*100.0/(successNum+failedCount))+"%:";
System.out.println(compositionsNum+"种态势并存,"+successNum+"种成功,"+failedCount+"种失败,几率"+rate);
for (int i = 0; i < successNum && i < 1; i++) {
System.out.println("\n第"+(i+1)+"种:");
for (Point point : trajectoryList.get(i)) {
System.out.println("点击第"+(point.getI()+1)+"行,第"+(point.getJ()+1)+"列。");
}
}
System.out.print("\n合并之后共有"+trajectorySet.size()+"种成功方法。");
}

// 由当前棋局态势推算出下一步的棋局态势 循环中采集目标态势所对应的落子坐标轨迹
private static void derivativesOfCompositions() {
List<Composition> currents=new LinkedList<Composition>();//当前棋局集合
currents.add(new Composition(details, new LinkedList<Point>()));
int num=0;
while (currents.size()!=0) {
if(currents.size()>compositionsNum) compositionsNum=currents.size();
List<Composition> news=new LinkedList<Composition>();
num++;
for (Composition composition : currents) {
clickPoints(composition, news, num);
}
currents=news;
}
}

// 寻找当前棋局尚可以点击的数据点 TODO(没有被炸空 且没有被点击过)
private static List<Point> searchForSurvivors(int[][] details,List<Point> trajectory) {
List<Point> current=new LinkedList<Point>();
for (Point data : dataPointList) {
if(details[data.getI()][data.getJ()]!=0 && !trajectory.contains(data)) current.add(data);
}
return current;
}

// 查看并批次点击 相当于树中的分支点
private static void clickPoints(Composition composition,List<Composition> news,int num) {
int[][] details=composition.getDetails();
List<Point> trajectory=composition.getTrajectory();
List<Point> currentPointList=searchForSurvivors(details,trajectory);
for (Point point : currentPointList) {
List<Point> trajectoryCopy=trajectoryCopy(trajectory);
trajectoryCopy.add(point);//记录于轨迹副本
// 点击
int i=point.getI();
int j=point.getJ();
int[][] detailsCopy=detailsCopy(details);
if(Math.abs(detailsCopy[i][j])==1) turn(detailsCopy,i,j);//翻转
else explosion(detailsCopy,i,j);//爆炸
if(end(detailsCopy)){
trajectoryList.add(trajectoryCopy);
trajectorySet.add(listIntoSet(trajectoryCopy));//Set对Set去重
// return true;//如果只需要找1种解法 这里的返回值被捕捉之后 可以跳出循环
}else if(num<clickNum){
news.add(new Composition(detailsCopy, trajectoryCopy));
}else failedCount++;
}
}

// 集合转化
private static Set<Point> listIntoSet(List<Point> trajectory) {
Set<Point> set=new HashSet<Point>();
for (Point point : trajectory) {
set.add(point);
}
return set;
}

// 轨迹副本
private static List<Point> trajectoryCopy(List<Point> trajectory) {
List<Point> trajectoryCopy=new LinkedList<Point>();
for (Point point : trajectory) {
trajectoryCopy.add(new Point(point.getI(), point.getJ()));
}
return trajectoryCopy;
}

// 棋局副本
private static int[][] detailsCopy(int[][] details) {
int[][] detailsCopy=new int[details.length][details.length];
for (int i = 0; i < details.length; i++) {
for (int j = 0; j < details.length; j++) {
detailsCopy[i][j]=details[i][j];
}
}
return detailsCopy;
}

// 翻转
private static void turn(int[][] details,int i,int j) {
details[i][j]=-details[i][j];
if(i!=0) details[i-1][j]=-details[i-1][j];//左
if(i!=details.length-1) details[i+1][j]=-details[i+1][j];//右
if(j!=0) details[i][j-1]=-details[i][j-1];//下
if(j!=details.length-1) details[i][j+1]=-details[i][j+1];//上
}

// 爆炸:先把自己清零 再判断四周(是数据则清零 也是炸*则递归)
private static void explosion(int[][] details,int i,int j) {
details[i][j]=0;
// 波及四周
sweep(details,i-1,j);
sweep(details,i+1,j);
sweep(details,i,j-1);
sweep(details,i,j+1);
}
// 波及
private static void sweep(int[][] details,int i,int j) {
// 下标越界或无数据
if(i==-1 || i==details.length || j==-1 || j==details.length || details[i][j]==0) return;
if(Math.abs(details[i][j])==1) details[i][j]=0;
else explosion(details,i,j);//递归
}

// 全部一致了
private static boolean end(int[][] details) {
int begin=0;
for (int i = 0; i < details.length; i++) {
for (int j = 0; j < details.length; j++) {
if(details[i][j]==0 || Math.abs(details[i][j])==2) continue;//空、炸*
if(begin==0){
begin=details[i][j];//记录首个颜色值
continue;
}
if(details[i][j]!=begin) return false;
}
}
return true;
}

// 添加调试信息
@SuppressWarnings("unused")
private static String message(int[][] details) {
String s="";
for (int i = 0; i < details.length; i++) {
for (int j = 0; j < details.length; j++) {
s+=transform(details[i][j]);
}
s+="\n";
}
return s+"\n";
}
// 中文转化
private static String transform(int i) {
if(i==-1) return "红,";
if(i==1) return "蓝,";
if(i==0) return "空,";
return "炸,";
}

}

以上是程序的主体逻辑部分,如果想直接调试,可以到CSDN我的资源去下载,那里是一个完整的工程。
原文地址:[url]http://blog.csdn.net/lhzx1541/article/details/8682326[/url]
下载地址:[url]http://download.csdn.net/download/lhzx1541/5149173[/url]
作者xhl:86年生,现身在杭州。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值