闲来无事,我也写个八皇后

pigwen521 2011-06-09 04:48:22
刚入职,有点闲,记得大学有听说过什么八皇后,没有实现过,心血来潮,打算自己写一个,写了整整一天。。。回想起大学,哎,没好好学习,原来大学的课程还是有用的,学了总比没学好,当时觉得没用的知识,不一定以后也不着,并且很有可能用得着。。。在这里奉劝一下在校大学生,把大学的专业课程好好学好,对你绝对有用的,理解下课本上的思想也行(比如说编译原理,图形学,计算机体系结构,操作系统等,这些大部分人真的可能不会参加这方面的工作,但里面的各种思想是解决各种问题的精华中的精华,不限于在程序上),还有英语及交际口才能力,也非常非常非常重要,与你职业上能达到什么高度样紧密相关。
再发下牢骚,本人从小的理想就是当天文方面的物理科学家去探索浩瀚宇宙(留给我儿子去实现吧),无奈智力有限,英语太烂等,只能上个普通本科,做只普通程序猿,毕业后进个深圳一家普通公司,做网站的,学校学的是JAVA,工作就转向了PHP,工作了3年,期间与网站有关的都做(前台样式脚本、后台PHP、服务器LINUX等),今年运气好跳到了一家很大的公司,希望自己以后会越来越好~
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<?php
$num = 8; //几皇后?
echo showQueens(queen($num),$num);

/**
回溯主体函数,返回所有可能的方案数组
*/
function queen($num){
$queen=array(); //临时的一种方案
$queens=array();//全部方案
for($i=0;$i<$num;$i++){//从00位置开始放置皇后
for($j=0;$j<$num;$j++){
if(is_conflict($queen,$i,$j,$num)){ //有冲突则取下一个
if($j+1===$num){ //列到了再后一个都有冲突则回退
backRow($queen,$i,$j,$num);
countinue;
}
}else{ //没有冲突则前进
$queen[$i][$j]=1; //记录可行值
if($i===$num-1){ //前面到了最后一行,达成一种方案,记录。。
$queens[]=$queen;
unset($queen[$i]);
backRow($queen,$i,$j,$num);//回退
}else{
break;
}
}
}
}
return $queens;
}
function backRow(&$queen,&$i,&$j,$num){
$i=$i-1;
$j=getNextJ($queen[$i]);//求回退位置的J的下标
unset($queen[$i]);
if($j+1===$num){ //回退的行已经是最后一列了,接着回退
$i=$i-1;
if($i===-1){ //回退到了第一行,遍历结束
$i=$num;return;
}
$j=getNextJ($queen[$i]);
unset($queen[$i]);
}
}
function getNextJ($queen){
foreach($queen as $k=>$v){
return $k;
}
return false;
}

/**
显示打印结果
*/
function showQueens($queens,$num){
$html ='<div>'.$num.'皇后共'.count($queens).'种方案</div>';
foreach($queens as $queen){
$html .=showQueen($queen,$num);
}
return $html;
}
//图形显示
function showQueen($queen,$num){
$html ='<table style="text-align:center;">
<tr>';
for($i=-1;$i<$num;$i++){
$html .='<td width="52" height="52">'.$i.'</td>';
}
$html .='</tr>';
foreach($queen as $row=>$q){
$html .='<tr><td height="52">'.($row).'</td>';
for($i=0;$i<$num;$i++){
$html .='<td style="background-color:#00cc99;">'.$q[$i].'</td>';
}
$html .='</tr>';
}
$html .='</table>';
return $html;
}

/**
检查要前进i,j的位置上面有没有冲突
*/
function is_conflict($queen,$i,$j,$num){
$flag=check_conflict_col($queen,$i,$j); //竖列有没有冲突
if($flag)return $flag;

$flag=check_conflict_corner_left($queen,$i,$j); //左上对角有没有冲突
if($flag)return $flag;

$flag=check_conflict_corner_right($queen,$i,$j,$num); //右上对角有没有冲突
return $flag;
}

//竖列有冲突?
function check_conflict_col($queen,$i,$j){
for($row=0;$row<$i;$row++){
if($queen[$row][$j]===1){
return true;
}
}
return false;
}
//左上斜线有冲突?
function check_conflict_corner_left($queen,$i,$j){
$step=1;
while($i-$step>=0 && $j-$step>=0){
if($queen[$i-$step][$j-$step]===1){
return true;
}
$step++;
}
return false;
}
//右上斜线有冲突?
function check_conflict_corner_right($queen,$i,$j,$num){
$step=1;
while(($i-$step)>=0 && ($j+$step<$num)){
if($queen[$i-$step][$j+$step]===1){
return true;
}
$step++;
}
return false;
}
?>
</body>
...全文
289 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
dylante 2011-06-12
  • 打赏
  • 举报
回复
mark
学习学习
ImN1 2011-06-10
  • 打赏
  • 举报
回复
补充一点

Q放在棋盘中央控制格最多,冲突概率最大,所以寻点应该从棋盘四个角开始
ImN1 2011-06-10
  • 打赏
  • 举报
回复
你这个代码有点长,用位运算简单很多,不过可能整棋盘需要64bit...

Q所在位置和她控制的格子分别设一个64bit整数(相当于“位棋盘”,用移位运算基本就能确认控制格)

把不同的Q的位置和控制格进行与运算,没有冲突应该为0

因为都是整数,用数组交并差可以省很多循环


部分思路大致这样,代码不写了,我这台机器没有64bit,要放到服务器上测试很麻烦
另外,虽然是二进制位运算,但棋盘是8*8,用八进制去思考会明瞭些
床上等您 2011-06-10
  • 打赏
  • 举报
回复
不会玩国际象棋。。。所以一点都不太明白
kaifadi 2011-06-10
  • 打赏
  • 举报
回复
不错学习了!
pigwen521 2011-06-10
  • 打赏
  • 举报
回复
附个效果图。。。
www_7di_net 2011-06-10
  • 打赏
  • 举报
回复
写php的程序员能够想楼主这样安心研究算法的太少了,不错,加你为好友.
helloyou0 2011-06-10
  • 打赏
  • 举报
回复
nice~
foolbirdflyfirst 2011-06-10
  • 打赏
  • 举报
回复
不要满足呀,lz可速速前去置顶那个0/1背包贴,你既然解了8皇后,类似的回溯法可解决0/1背包的。
pigwen521 2011-06-10
  • 打赏
  • 举报
回复
to:8楼
谢谢了,我能把它写出来就很满意了。。
mumubangditu 2011-06-09
  • 打赏
  • 举报
回复
国际象棋一方真的有8皇后这样排列的话,对手绝对无解了……
黄袍披身 2011-06-09
  • 打赏
  • 举报
回复
在8*8国际象棋棋盘上,要求在每一行放置一个皇后,且能做到在竖方向,斜方向都没有冲突
LKK 2011-06-09
  • 打赏
  • 举报
回复
弱弱地问,什么是八皇后?

21,887

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧