问题描述:n个人排成一圈。从某个人开始,依次报数,数到m的人被杀死。下一个人重新从1开始报数,数到m的人被杀死。直到剩下最后一个人。
解决思路:从数学角度去看,每一次报数决定谁去死是一个n、m的求余数过程。从程序角度看,玩家和编号一一对应,每一次报数玩家减少一个,编号重新排列。
程序:
1.首先声明相关变量
$childAmount = 6; //总人数 $endNumber = rand(1,6); //死亡编号取随机值 $gameNumber = 0;//游戏次数 $childArray = array('a','b','c','d','e','f');//玩家姓名数组 $playArray = array();//编号姓名对应关系数组 $killArray = array();//死亡顺序名单数组 //初始化 shuffle($childArray);//取随机排序
2.游戏开始前数组准备
//初始化 shuffle($childArray);//取随机排序 //构建关联数组 for($i=0;$i<count($childArray);$i++){ $playArray[$i+1] = $childArray[$i]; } echo '<pre>'; echo "玩家数:".$childAmount."死亡编号:".$endNumber."<br>"; echo "这是初始游戏编号:"; print_r($playArray); echo '</pre>';
3.游戏开始
//死亡循环 while($childAmount > 1){//判断人数是否大于1,决定游戏是否结束 $number = $endNumber % $childAmount;//求取余数 //当余数为0时,死亡的是编号最大的人 if($number == 0){ $killArray[] = $playArray[$childAmount];//加入死亡名单 unset($playArray[$childAmount]);//该玩家死亡 $childAmount -= 1;//游戏人数减一 $gameNumber += 1;//死亡循环次数加一 }else{//余数不为0,死亡的是编号等于余数的人 $temp = array(); $killArray[] = $playArray[$number]; unset($playArray[$number]); //规律:余数不为0,大于以及小于该余数的编号之后的人编号从1开始重新排列。大于该编号的人编号为(本身编号-死亡编号),小于该编号的人编号为(本身编号+当前最大编号-死亡编号) foreach($playArray as $key => $value){ if($key > $number){ $temp[$key-$number] = $value; }else{ $temp[$key+$childAmount-$number] = $value; } } ksort($temp);//按键名排序 $playArray = $temp; $childAmount -= 1; $gameNumber += 1; } if($childAmount == 1){ echo '<pre>'; echo '幸存者是:'; print_r($playArray); echo '</pre>'; } } echo '<pre>'; echo "死亡顺序:"; print_r($killArray); echo '</pre>';