1. 程式人生 > >JavaSE_28th_陣列——數3退1遊戲

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