九王(9Kings)与组合样本生成算法

《九王》,又名《9Kings》是一款深受博主青睐的游戏,其玩法围绕打牌构筑各种类型地块,与前来进犯的敌军战斗展开,其中,各种地块摆放的位置产生的效果相异,长期影响构筑策略。
九王示例图
博主寻思编写程序生成全部的位置组合。确定待摆放地块数量和地块总数后,全部的摆放位置组合也确定了,

九王表格tu1
上图摆放位置组合[1,2,3]

九王表格tu2
上图摆放位置组合[1,3,4]
其组合数量等于公式image

for 循环或递归搭配迭代器算法组合均可生成摆放位置组合样本,下面介绍两种算法原理。

for 循环

for 循环嵌套层数和摆放地块数目相等。

摆放地块数目等一时

for(i = 1,2...总地块数目)
  创建数组[i]存入二维数组[[i],[i]....]

摆放地块数目等二时

for(i = 1,2...总地块数目-1)
  for(j = i+1,i+2...总地块数目)
    创建数组[i,j]存入二维数组[[i,j],[i,j]....]

摆放地块数目等三时

for(i = 1,2...总地块数目-2)
  for(j = i+1,i+2...总地块数目-1)
    for(k = j+1,j+2...总地块数目)
    创建数组[i,j,k]存入二维数组[[i,j,k],[i,j,k]....]

摆放地块数目等n时

for(i = 1,2...总地块数目-(n-1))
  for(j = i+1,i+2...总地块数目-(n-2))
    for(k = j+1,j+2...总地块数目-(n-3))
        ....
          for(l....总地块-(n-n))
            创建数组[i,j,k,l...]存入二维数组[[i,j,k,l...],[i,j,k,l...]....]

递归搭配迭代器

示例中,递归嵌套层数和摆放地块数目加一相等。

此处省略数组迭代器、数组迭代器的迭代器与业务类源码,源码请见末尾的附录标题处

	void getSamples(int lvl, int init)  {
		if(lvl == 摆放地块数) {
			数组的迭代器的迭代器中存入新创建的数组迭代器
		} else {
			for(int i=init;i<总地块数-摆放地块数+递归层数+1;i++) {
				int beforeIndex = 一维数组迭代器的迭代器取当前索引;
				getSamples(1+lvl,i+1);//递归
				int afterIndex = 一维数组迭代器的迭代器取当前索引;
				for (遍历小于等于 afterIndex 至大于 beforeIndex 的数) {
					取数组迭代器的迭代器当前的索引标记的数组迭代器,向其存入i
				}
			}
		}
	}

该递归函数的 else 分支部分是精华,下面将该精华的的执行情形分成两种,一种是 else 分支开始,从递归位置进入下一个递归的 if 分支再返回该递归位置向下执行至 for 遍历小于等于 afterIndex 至大于 beforeIndex 的数结束。一种是 else 分支开始,从递归位置进入下一个递归的 else 分支再返回该递归位置向下执行至 for 遍历小于等于 afterIndex 至大于 beforeIndex 的数结束。

下图展示第一种情形的数据结构变化
image

下图展示第二种情形的数据结构变化
image

附录

数组迭代器

import java.util.Iterator;

public class ArrIterator implements Iterable<Integer>/* ,Cloneable*/{
	Integer[] store;
	private int index = -1;

	
	public ArrIterator(int numOfOneSample) {
		super();

		store= new Integer[numOfOneSample];
	}

	@Override
	public Iterator<Integer> iterator() {
		return new Itr();
	}
	
	public void append(Integer e) {
		store[++index] = e;
		if(index == store.length - 1)
			index = -1;
	}
	
	private class Itr implements Iterator<Integer> {
		int cursor = index==-1?store.length-1:index;
		int count = store.length;

		@Override
		public boolean hasNext() {
			return count>0;
		}

		@Override
		public Integer next() {
			count--;
			Integer e = store[cursor];
			cursor = cursor == 0?store.length-1:cursor-1;
			return e;
		}
		
	}
	

}

数组迭代器的迭代器

import java.util.Iterator;

public class ItrsIterator implements Iterable<ArrIterator> {
	private ArrIterator[] store;
	private int index = -1;
	
	public int getIndex() {
		return index;
	}
	
	public ArrIterator getArrItr(int index) {
		return store[index];
	}

	public ItrsIterator(int numOfSamples) {
		super();
		store= new ArrIterator[numOfSamples];
		System.out.println("numOfSamples="+numOfSamples);
	}
	@Override
	public Iterator<ArrIterator> iterator() {
		return new Itr();
	}
	
	public void append(ArrIterator e) {
		store[++index] = e;
		if(index == store.length - 1)
			index = -1;
	}
	
	private class Itr implements Iterator<ArrIterator> {
		int cursor = index==-1?store.length-1:index;
		int count = store.length;

		@Override
		public boolean hasNext() {
			return count>0;
		}

		@Override
		public ArrIterator next() {
			count--;
			ArrIterator e = store[cursor];
			cursor = cursor == 0?store.length-1:cursor-1;
			return e;
		}
		
	}

}

业务层

package test9;

import java.util.Arrays;
import java.util.Iterator;

public class Assembler {
	private ItrsIterator itrsIterator;
	private final int NUM_OF_GRIDS;
	private final int NUM_OF_ONE_SAMPLE;
	private int numOfSamples;
	
	public Assembler(int numOfGrids,int numOfOneSample) {
		this.NUM_OF_ONE_SAMPLE = numOfOneSample;
		this.NUM_OF_GRIDS = numOfGrids;
		this.calNumOfSamples(0, 0);
		this.itrsIterator = new ItrsIterator(this.numOfSamples);
	}
	
    //计算数组迭代器的迭代器中容器的长度
	private void calNumOfSamples(int lvl,int init) {
    		if(lvl == this.NUM_OF_ONE_SAMPLE) {
    			this.numOfSamples++;
    		} else {
    			for(int i=init;i<NUM_OF_GRIDS-NUM_OF_ONE_SAMPLE+lvl+1;i++) {
    				calNumOfSamples(1+lvl,i+1);
    			}
    		}
	}

	//获取组合样本的递归方法
	void getSamples(int lvl, int init)  {
		if(lvl == this.NUM_OF_ONE_SAMPLE) {
			this.itrsIterator.append(new ArrIterator(this.NUM_OF_ONE_SAMPLE));
		} else {
			for(int i=init;i<NUM_OF_GRIDS-NUM_OF_ONE_SAMPLE+lvl+1;i++) {
				int beforeIndex = this.itrsIterator.getIndex();
				System.out.println("before callback,index="+beforeIndex);
				getSamples(1+lvl,i+1);
				int afterIndex = this.itrsIterator.getIndex();
				System.out.println("after callback,afterIndex="+afterIndex);
				for (int j = afterIndex == -1 ? this.numOfSamples-1:afterIndex; j > beforeIndex; j--) {
					this.itrsIterator.getArrItr(j).append(i);
				}
			}
		}
	}
	
	//遍历数组迭代器的迭代器和数组迭代器
	void iterateItrs() {
		Iterator<ArrIterator> iterators = this.itrsIterator.iterator();
		while(iterators.hasNext()) {
			ArrIterator arrItr = iterators.next();
			Iterator<Integer> iterator = arrItr.iterator();
			while(iterator.hasNext()) {
				System.out.print(iterator.next()+" ");
			}
			System.out.println();
		}
	}
	
	
}

posted on 2026-01-07 15:16  技术小伙伴  阅读(10)  评论(0)    收藏  举报