华容道游戏破解PHP版

参见下面的文章,华容道用C#写出破解后,感觉程序实在是简单,于是尝试移植到其他语言上

http://blog.csdn.net/robinspada/article/details/79354500

仅仅是简单移植,没有特别优化,运行时间如下



<?php
class Huarongdao
{
	//已经走过地图类型(去重复用)
	protected $history=[];
	//每一步的所有走法(走到终点回溯上一步用,如果只求步数则可以不要)
	protected $allNodes=[];
	//下一步各种走法节点
	protected $nextList=null;

	protected $index=0;

	const Left = -1;
	const Right= 1;
	const Up=-4;
	const Down=4;
	
	function Move($dir,$map, $ch, $first = true) {
		$work=str_split (str_replace($ch,' ',$map));

		for ($i = 0; $i < 20; $i++){
			if (substr($map,$i,1) == $ch){
				$pos = $i + $dir;
				$x = $i % 4;

				if ($dir == self::Left  && $x == 0 ||
					$dir == self::Right && $x == 3 ||
					$pos < 0 || $pos >= 20) return;

				if ($work[$pos] != ' ') return;
				$work[$pos] = $ch;
			}
		}
		$work = join($work);

		//重复检查
		if ($this->IsDuplicate($work)) return;
		//加入下一步,记录父节点
		$this->nextList[]=['map'=>$work, 'parent'=>$this->index];
		if ($first){
			//试着走第二步,但不能退回
			if ($dir != self::Right) $this->Move(self::Left, $work, $ch, false);
			if ($dir != self::Left) $this->Move(self::Right, $work, $ch, false);
			if ($dir != self::Down) $this->Move(self::Up, $work, $ch, false);
			if ($dir != self::Up) $this->Move(self::Down, $work, $ch, false);
		}
	}
	function IsDuplicate($map){
		$layout = $map;
		//相似的形状统一成一种,去重复
		$layout=str_replace('3', '1',$layout);
		$layout=str_replace('4', '1',$layout);
		$layout=str_replace('6', '1',$layout);
		$layout=str_replace('7', '0',$layout);
		$layout=str_replace('8', '0',$layout);
		$layout=str_replace('9', '0',$layout);

		if (array_key_exists($layout,$this->history)) return true;
		$this->history[$layout]='1';

		//左右镜像(大约节约1/2时间),去重复
		$reverse = str_split($layout);
		for ($k = 0; $k < 20; $k++){
			$x = 3 - ($k % 4);
			$y = intval($k / 4);
			$reverse[$y * 4 + $x] = substr($layout,$k,1);
		}
		$reverse=join($reverse);
		if (array_key_exists($reverse,$this->history)) return true;

		return false;
	}
	function Print($index){
		$outList = [];
		$parent = $index;
		for ($level = count($this->allNodes)-1; $level >= 0; $level--){
			$outMap = $this->allNodes[$level][$parent]['map'];
			$parent = $this->allNodes[$level][$parent]['parent'];
			$outList[]=$outMap;
		}
		$cnt = 0;
		for ($j = count($outList) - 1; $j >= 0; $j--){
			echo "--------------------------" . $cnt++."\n";
			for ($y = 0; $y < 5; $y++)
			{
				echo substr($outList[$j],$y * 4, 4)."\n";
			}
		}
	}
	function microtime_float(){
		list($usec, $sec) = explode(" ", microtime());
		return ((float)$usec + (float)$sec);
	}
	function Scan(){
		$initMap =
			 "1223".
			 "1223".
			 "4556".
			 "4786".
			 "9  0";
		$curList = [ ['map'=>$initMap,'parent'=>0] ];

		$begin = $this->microtime_float();
		//迭代直到无路可走
		while (count($curList)>0){
			//记录每一步
			$this->allNodes[]=$curList;

			$this->nextList = [];
			for($this->index = 0; $this->index < count($curList); $this->index++){
				$map = $curList[$this->index]['map'];
				//到达终点的判断
				if (substr($map,4 * 4 + 1,1) == '2' && substr($map,4 * 4 + 2,1) == '2'){
					echo "time:".($this->microtime_float() - $begin)."\n";
					$this->Print($this->index);
					return;
				}
				//穷举各种可能性,去重复,加入到下一步的节点
				for ($ch = '0'; $ch <= '9'; $ch++){
					$this->Move(self::Left,$map, $ch);
					$this->Move(self::Right, $map, $ch);
					$this->Move(self::Up, $map, $ch);
					$this->Move(self::Down, $map, $ch);
				}
			}
			//迭代
			$curList = $this->nextList;
		}
		echo "无解";
	}
}

(new Huarongdao())->Scan();
?>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值