智商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 "炸,";
	}
	
}

以上是程序的主体逻辑部分,如果想直接调试,可以到我的资源去下载,那里是一个完整的工程。

下载地址:http://download.csdn.net/download/lhzx1541/5149173

作者xhl:86年生,现身在杭州。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值