• 关于DNF金刚Go游戏的决策实践


    最近闲来登上DNF玩了下游戏,发现更新了个玩具,就是金刚Go;

    线面将这个游戏的概念抽象出来。

    游戏规则:

     * 实现猜数字的游戏,每次必须填入两位数字,在数字卡片各个数值都固定的情况下。实现最终将数值都猜完的游戏。
     
    *
    每次猜完数值后,拿出来的两张卡片会消失。没猜正确的话,需要继续猜。

    Java实现。

    为了实现这个需求,我写了个小程序,有三处有待改善,我也实现了,但是传过来一个次品供大家观赏和优化。优化可以用贝叶斯决策。

    1,键盘互动,猜大了,猜小了,用键盘互动实现flag = 1/0让程序自动进行选择,依次填写相应的结果。

    2,在算法上有些细节有些冗余,代码不够简洁,在传入A,B数值上可以看出。

    3,实现A,B待留数组的保留上可以用决策的思想优化,我这里全部是min/10-max/10来处理十位数的保留。

    实际上当个位min%10 = 9 就可以忽视该值min/10,同理max%10 = 0可以忽视 max/10了,那么 = 8/2又该以什么样的权值或者是什么样的集合环境去替换,这就是个值得研究的问题,可以有很大程度的优化了。

    初步基本思想:

     1,实现两位数的填入,首先将最多的卡片先利用,若最多的卡片有多个就实行贴近mid的那张,大多数情况下十位数的试探方法。
      2,接着实现个位数的填补,一定使用那些不会再出现在十位数上的卡片例如,第一手猜了56后,猜大了那么01234中最多的就可以一直当做个位卡片试探。
      3,梯形试探,当进入十位和个位相同的时候,采用梯形试探法,同上,只是结合了广义二分查找。

    主程序

    import java.util.ArrayList;
    
    public class Test2 {
    	static boolean flag = true;
    	static int[] countVal = Data.valueArray; 
    	static int[] countValue = Data.valueArray;
    	static int[] indexArray = Data.indexArray;
    	public static void main(String[] args) {
    		int c = (int ) (100*Math.random());
    		int max = 100;
    		int min = 0;
    		while(max != min && flag){
    			int ab = sureAB(min, max);
    			System.out.println("你猜的值为:"+ ab);
    			if(ab > c){
    				System.out.println("猜大了");
    				max = ab;
    			}else if(ab < c){
    				System.out.println("猜小了");
    				min = ab;
    			}else{
    				min = max;
    				System.out.println("恭喜您猜中了");
    			}
    			
    		}
    	}
    	public static int sureAB(int min, int max) {
    		System.out.println("执行 sureAB()");
    		int mid = (max + min)/2;
    		int A = 0;
    		int B = 0;
    		int x = min/10;//十位
    		int y = max/10;
    		if(y==10) y=9;
    		if(x==10) x=9;
    		if(x == y){
    			return lastLineSetAB(min, max, x); 
    		}else{
    			//h为0或者1对应到A有没有包含到A_max
    			int[] array1_Value = new int[y-x+1];
    			int[] array1_Index = new int[y-x+1];
    			int k1 = 0;
    			for (int i = x ; i <= y; i++) {
    				array1_Index[k1] = i;
    				array1_Value[k1] = countVal[i];
    				k1++;
    			}
    			A = selectA(mid, array1_Value, array1_Index);
    			//确定了A再确定B
    			try {
    				countVal[A] = countVal[A] -1;
    			} catch (Exception e) {
    				System.out.println("游戏结束,您没通关;");
    			}finally{
    				//传递进去备选数组B的两个视图
    				B = selectB(mid, A, array1_Value, array1_Index);
    				countVal[B] = countVal[B] -1;
    			}
    		
    		}
    		return 10*A + B;
    	}
    	
    	public static int lastLineSetAB(int min, int max, int x) {
    		System.out.println("-梯度方法执行中-");
    		int A = x;
    		//只确定B的范围
    		int mid = (max+min)/2;
    		int b_min = min/10;
    		int b_max = max/10;
    		int b_mid = (b_max + b_min)/2;
    		int By = 10;//差值越小越好
    		int in = 0;
    		int f = 0;
    		for(int ii = 0; ii<countVal.length;ii++){
    			if(countVal[ii]>0){
    				if(Math.abs(ii - b_mid)< By){
    					By = Math.abs(indexArray[ii] - mid);
    					in = ii;
    				}
    				f++;
    			}
    		}	
    		if(f == 0){
    			flag = false;
    			System.out.println("没找到匹配的B值");
    		}
    		int B = in;
    		countVal[A] = countVal[A] -1;
    		countVal[B] = countVal[B] -1;
    		return 10*A + B;
    	}
    	
    	
    	public static int selectB(int mid, int A, int[] array1_Value,
    			int[] array1_Index) {
    		int B;
    		int[] array2_Index;
    		int[] array2_Value;
    		if(array1_Value.length == 10){
    			array2_Index = array1_Index;
    			array2_Value = array1_Value;
    		}else{
    			array2_Index = new int[10 - (array1_Value.length)];
    			array2_Value = new int[array2_Index.length];
    			int j=0;
    			for (int i = 0; i < 10; i++) {
    				if (!arraycontainElements(array1_Index,i)) {
    					array2_Index[j] = i;
    					array2_Value[j] = countVal[i];
    					j++;
    					}
    				}
    		}
    		Data.arraySort(array2_Value, array2_Index, 0);
    		printArr(array2_Value);
    		printArr(array2_Index);
    		if(array2_Value[0] == 0){
    			System.out.println("没有B可抽,来抽A当B");
    			B = selectA(mid, array1_Value, array1_Index);
    		}else{
    			ArrayList<Integer> maxMat2 = Data.maxMat(array2_Value, array2_Index);
    			if(maxMat2.size() == 1){
    				B = array2_Index[0];
    			}else{
    				int[] jl = new int[maxMat2.size()];
    				int index = 0;
    				int min_jl = 100;
    				for (int i = 0; i < maxMat2.size(); i++) {
    					jl[i] = Math.abs(10*A+maxMat2.get(i) - mid);
    					if(jl[i] < min_jl){
    						min_jl = jl[i];
    						index = maxMat2.get(i);
    					}
    				}
    				B  = index;
    			}
    		}
    		
    		System.out.println("执行selectB(),打印出B: "+B);
    		return B;
    	}
    	
    	
    	public static int selectA(int mid, int[] array1_Value, int[] array1_Index) {
    		int A = 5;
    		int A_ = mid/10;//期望的十位
    		Data.arraySort(array1_Value, array1_Index, 0);
    		printArr(array1_Value);
    		printArr(array1_Index);
    		ArrayList<Integer> maxMat = Data.maxMat(array1_Value, array1_Index);
    		if(array1_Value[0] == 0){
    			System.out.println("没有A可抽");
    			flag = false;
    			return 100;
    		}
    		if(maxMat.size() == 1){
    			A = array1_Index[0];
    		}else{
    			int[] jl = new int[maxMat.size()];
    			int index = 0;
    			int min_jl = 10;
    			for (int i = 0; i < maxMat.size(); i++) {
    				jl[i] = Math.abs(maxMat.get(i) - A_);
    				if(jl[i] < min_jl){
    					min_jl = jl[i];
    					index = maxMat.get(i);
    				}
    			}
    			A  = index;
    		}
    		System.out.println("执行 selectA(),打印 A:"+ A);
    		return A;
    	}
    	
    	public static boolean arraycontainElements(int[] arr, int k){
    		for (int i = 0; i < arr.length; i++) {
    			if(k == arr[i]){
    				return true;
    			}
    		}
    		return false;
    	}
    	
    	public static void printArr(int[] arr){
    		System.out.print("[");
    		for (int i = 0; i < arr.length; i++) {
    			if (i== arr.length - 1) {
    				System.out.println(arr[i] + "]");
    			}else{
    				System.out.print(arr[i]+",");
    			}
    		}
    	}
    }
    
    工具类:

    package com.byk.demo;
    
    import java.util.ArrayList;
    
    public class Data {
    	
    	static int[] valueArray = {6,4,3,5,3,5,5,2,5,7};
    	static int[] indexArray = {0,1,2,3,4,5,6,7,8,9};
    	
    	/*
    	 * 从索引from 根据arr1数组排序,arr2随着arr1对应而定
    	 */
    	public static void arraySort(int[] arr1,int[] arr2,int from){
    		for (int i = 0; i < arr2.length; i++) {
    			for (int j = 0; j < arr2.length; j++) {
    				if(arr1[i]>arr1[j]){
    					swap(arr1,i,j);
    					swap(arr2,i,j);
    				}
    			}
    		}
    	}
    	
    	public static void swap(int[] arr,int i,int j){
    		int temp = 0;
    		temp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = temp;
    	}
    	public static boolean isMaxUnique(int[] arr){
    	/*	int i=0;
    		while(i<arr.length){
    			if(arr[0] != arr[i]){
    				return false;
    			}
    			i++;
    		}
    		return true;*/
    		int[] arr2 = Data.indexArray;
    		ArrayList<Integer> al = maxMat(arr, arr2);
    		if(al.size() == 1){
    			return true;
    		}else{
    			return false;
    		}
    		
    	}
    	//返回最大值索引的集合。arr1为count,arr2为降序最大索引序列
    	public static ArrayList<Integer> maxMat(int[] arr1,int[] arr2){
    		ArrayList<Integer> ali = new ArrayList<Integer>();
    		a:for (int i=0; i < arr1.length;i++) {
    			if(arr1[i] == arr1[0]){
    				ali.add(arr2[i]);
    			}else{
    				break a;
    			}
    		}
    		return ali;
    	}
    }

    给出一个执行结果:

    执行 sureAB()
    [7,6,5,5,5,5,4,3,3,2]
    [9,0,5,6,8,3,1,4,2,7]
    执行 selectA(),打印 A:9
    [7,6,5,5,5,5,4,3,3,2]
    [9,0,6,8,3,5,1,2,4,7]
    执行selectB(),打印出B: 9
    你猜的值为:99
    猜大了
    执行 sureAB()
    [6,5,5,5,5,5,4,3,3,2]
    [0,3,5,6,8,9,1,4,2,7]
    执行 selectA(),打印 A:0
    [6,5,5,5,5,5,4,3,3,2]
    [0,5,6,8,9,3,1,2,4,7]
    执行selectB(),打印出B: 0
    你猜的值为:0
    猜小了
    执行 sureAB()
    [5,5,5,5,5,4,4,3,3,2]
    [3,5,6,8,9,0,1,4,2,7]
    执行 selectA(),打印 A:3
    [5,5,5,5,5,4,4,3,3,2]
    [5,6,8,9,3,1,0,2,4,7]
    执行selectB(),打印出B: 9
    你猜的值为:39
    恭喜您猜中了

    //再执行一次

    执行 sureAB()
    [7,6,5,5,5,5,4,3,3,2]
    [9,0,5,6,8,3,1,4,2,7]
    执行 selectA(),打印 A:9
    [7,6,5,5,5,5,4,3,3,2]
    [9,0,6,8,3,5,1,2,4,7]
    执行selectB(),打印出B: 9
    你猜的值为:99
    猜大了
    执行 sureAB()
    [6,5,5,5,5,5,4,3,3,2]
    [0,3,5,6,8,9,1,4,2,7]
    执行 selectA(),打印 A:0
    [6,5,5,5,5,5,4,3,3,2]
    [0,5,6,8,9,3,1,2,4,7]
    执行selectB(),打印出B: 0
    你猜的值为:0
    猜小了
    执行 sureAB()
    [5,5,5,5,5,4,4,3,3,2]
    [3,5,6,8,9,0,1,4,2,7]
    执行 selectA(),打印 A:3
    [5,5,5,5,5,4,4,3,3,2]
    [5,6,8,9,3,1,0,2,4,7]
    执行selectB(),打印出B: 9
    你猜的值为:39
    猜小了
    执行 sureAB()
    [5,5,5,4,4,3,2]
    [5,6,8,3,9,4,7]
    执行 selectA(),打印 A:6
    [4,4,3]
    [1,0,2]
    执行selectB(),打印出B: 1
    你猜的值为:61
    猜大了
    执行 sureAB()
    [5,4,4,3]
    [5,3,6,4]
    执行 selectA(),打印 A:5
    [5,4,4,3,3,2]
    [8,0,9,2,1,7]
    执行selectB(),打印出B: 8
    你猜的值为:58
    猜小了
    执行 sureAB()
    [4,4]
    [5,6]
    执行 selectA(),打印 A:5
    [4,4,4,4,3,3,3,2]
    [0,3,8,9,1,2,4,7]
    执行selectB(),打印出B: 9
    你猜的值为:59
    恭喜您猜中了



  • 相关阅读:
    python写的文件同步服务器
    从外部调用Django模块
    python监视线程池
    RabbitMQ手册翻译 RPC服务的例子
    python logging 模块完整使用示例
    使用内存磁盘加速linux
    About learning on the internet
    [转]伟大的程序员是怎样炼成的
    RabbitMQ手册翻译 Hello World的例子
    事半功倍:你应该知道的HTML5五大特性(转)
  • 原文地址:https://www.cnblogs.com/actanble/p/6713461.html
Copyright © 2020-2023  润新知