JavaSE_28th_数组——数3退1游戏

一、数3退1游戏解法

1)面向过程的解法

/**
 * 数3退1测试  类
 * @author fuchs
 *
 */
public class TestCount3Quit {
	public static void main(String[] args) {
		/* 创建一个500个长度的布尔数组,表示500个小孩的状态 */
		boolean[] kid = new boolean[500];
		/* 将该布尔数组中的所有元素初始化为true,即所有小孩都在圈子中 */
		for(int i=0; i<kid.length; i++) {
			kid[i] = true;
		}
		/* 记录剩下的人数 */
		int leftNum = kid.length;
		/* 记录报的数字(1~3) */
		int countNum = 0;
		/* 记录数组下标(0~499),轮到第index个小孩 */
		int index = 0;
		/*  */
		/* 当人数大于1时,一直循环 */
		while(leftNum > 1) {
			if(kid[index] == true) {
				countNum++;		//报数 
				/* 报到3 */
				if(countNum == 3) {
					countNum = 0;			//清零,下次从1开始数
					kid[index] = false;		//标记当前小孩为false,退出圈子
					leftNum--;				//剩下的人数自减
				}
			}
			index++;	//轮到下一个小孩
			if(index == kid.length) {
				index = 0;
			}
		}
		/* 找到最后那个孩子圈子中的小孩 */
		for(int i=0; i<kid.length; i++) {
			if(kid[i] == true) {
				System.out.println(i + 1);
			}
		}
	}
}

运行结果:

436

2)面向对象的解法

/**
 * 数3退1测试  类
 * @author fuchs
 *
 */
public class TestCount3Quit2 {
	public static void main(String[] args) {
		/* 创建一个500个小孩的圈子对象 */
		KidCircle kc = new KidCircle(1000);
		/* 创建一个小孩对象,并指向孩子圈中的第一个小孩 */
		Kid k = kc.firstKid;
		/* 记录报的数字(1~3) */
		int countNum = 0;
		/* 当人数大于1时,一直循环 */
		while(kc.count > 1) {
			/* 报数 */
			countNum++;
			/* 报到3 */
			if(countNum == 3) {
				countNum = 0;	//清零,下次从1开始数
				kc.deleteKid(k);//删除当前小孩
			}
			k = k.rightKid;		//当前小孩指向右手边的小孩
		}
		
		/* 退出循环时,kc.count为1,即孩子圈中只有1个小孩了,
		 * 最后剩下的这个小孩组成的1个人的圈子中,他既是最后一个人,也可以认为是最后一个人 */
		/* 打印这个圈子中的第一个小孩 */
		System.out.println(kc.firstKid.id + 1);
	}
}

/**
 * 孩子  类
 * @author fuchs
 *
 */
class Kid {
	int id;			//每个小孩的编号
	Kid leftKid;	//左手边的小孩
	Kid rightKid;	//右手边的小孩
}

/**
 * 孩子围成的圈  类
 * @author fuchs
 *
 */
class KidCircle {
	int count = 0;	//记录圈子中的人数
	Kid firstKid;	//圈子中的第一个小孩
	Kid lastKid;	//圈子中的最后一个小孩
	
	/* 构造一个人数为num的圈子 */
	KidCircle(int num) {
		for(int i=num; i>0; i--) {
			addKid();
		}
	}
	/* 添加一个小孩的方法 */
	void addKid() {
		/* 创建一个小孩对象 */
		Kid kid = new Kid();
		/* 根据圈子中的人数,来记录小孩的id号 */
		kid.id  = count;
		
		/* 如果圈子中还没有人 */
		if(count <= 0) {
			firstKid = kid;			//把创建的这个小孩作为圈子中的第一个小孩
			lastKid = kid;			//这个小孩也是圈子中的最后一个人
			kid.leftKid = kid;		//这个小孩的左手边是自己
			kid.rightKid = kid;		//右手边的小孩也是自己
		}
		/* 如果圈子里已经有人了 */
		else if(count > 0) {
			lastKid.rightKid = kid;		//这个小孩牵者最后一个小孩的右手
			firstKid.leftKid = kid;		//这个小孩牵着第一个小孩的左手
			kid.leftKid = lastKid;		//这个小孩的左手是最后一个小孩
			kid.rightKid = firstKid;	//这个小孩的右手是第一个小孩
			lastKid = kid;				//这个小孩成为最后一个小孩
		}
		count++;						//圈子中的小孩数量增加1
	}
	
	void deleteKid(Kid kid) {
		/* 如果圈子中还没有人 */
		if(count <= 0) {
			return;			//不能删除
		}
		/* 圈子中有一个小孩 */
		else if(count == 1) {
			firstKid = lastKid = null;
		}
		/* 圈子中有多个小孩 */
		else if(count > 1) {
			kid.leftKid.rightKid = kid.rightKid;	//让这个小孩右手边的小孩成为他左手边小孩右手边的小孩
			kid.rightKid.leftKid = kid.leftKid;		//让这个小孩左手边的小孩成为他右手边小孩左手边的小孩
			/* 如果删除的小孩是圈中的第一个小孩 */
			if(kid == firstKid) {
				firstKid = kid.rightKid;	//让第一个小孩右手边的小孩成为第一个小孩
			} else if(kid == lastKid) {
				lastKid = kid.leftKid;		//让最后一个小孩左手边的小孩成为最后一个小孩
			}	
		}
		count--;			//圈子中的小孩数量增加1
	}	
}


运行结果:

436









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值