问题介绍
编辑
八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n1×n1,而皇后个数也变成n2。而且仅当 n2 ≥ 1 或 n1 ≥ 4 时问题有解。
八皇后问题最早是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出。之后陆续有数学家对其进行研究,其中包括高斯和康托,并且将其推广为更一般的n皇后摆放问题。八皇后问题的第一个解是在1850年由弗朗兹·诺克给出的。诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。1874年,S.冈德尔提出了一个通过行列式来求解的方法,这个方法后来又被J.W.L.格莱舍加以改进。
艾兹格·迪杰斯特拉在1972年用这个问题为例来说明他所谓结构性编程的能力。
八皇后问题出现在1990年代初期的著名电子游戏第七访客中。
八皇后核心代码:
#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
#include "string"
#include "graphics.h"//其内包含easyx图形函数库
#include<conio.h>
#include <cstdlib>
#include <stdio.h>
#include <windows.h>//延时函数头文件
using namespace std;
int pp = 0;//判断查看怎样的结果,决定了延时位置的不同,则展现结果就不同
void z0()//pp=0时,查看算法过程的动态演示
{
if (pp == 0) Sleep(0.4 * 1000); //延时函数,延时0.4秒
}2
void z1()//pp=1时,查看符合要求的92种结果
{
if (pp == 1) Sleep(1.2 * 1000);
}
int curr;
int c[8] = { 0 };
int num = 0;
char s[5];
int k[8][8];
void print()
{
sprintf(s, "%d", num);//将此时符合条件的解得个数(int)转化格式成为字符串(char s[5])
outtextxy(1000, 400, s);//将个数输出在屏幕的(1000,400)的位置
}
void pan(int curr)//验证curr行的放置
{
if (curr == 8) //当行数达到边界时,则出现了一个没有冲突符合条件的解
{
num++; //记录现在满足条件解的个数
print();
z1();//延时判断
}
else
{
for (int i = 0; i<8; i++) //循环验证在curr行时,把皇后放置在第i列时
{
int ok = 1;//标记此行是否放置了皇后
memset(k[curr], 0, sizeof k[curr]);//每次重新在此行放置皇后时,清空此行的之前放置的东西
k[curr][i] = 1;//标记在curr行i列放置的皇后
c[curr] = i;//表示curr行放置皇后的列数
setfillcolor(BLUE);
z0();
solidcircle(i * 100 + 50, curr * 100 + 50, 30);//并且将此时位置画上蓝色圆
for (int j = 0; j<curr; j++)//判断是否与前面的皇后位置有冲突
{
if (c[curr] == c[j] || curr - c[curr] == j - c[j] || curr + c[curr] == j + c[j])
{//判断是否在同一列和是否会在对角线上
setfillcolor(RED);
solidcircle(i * 100 + 50, curr * 100 + 50, 30);//若是不合适皇后,则显示红色圆片
z0();
clearcircle(i * 100 + 50, curr * 100 + 50, 30);
ok = 0;//如果出现冲突,则将此处的皇后撤掉,表示此行没有放置合适的皇后
k[curr][i] = 0;
break;//只要出现有冲突的,则跳出判断循环,把此行的皇后放置到下一列
}
}
if (ok)//若是此行已经放置好了合适的皇后
{
pan(curr + 1);//进行下一行皇后位置的寻找
clearcircle(i * 100 + 50, curr * 100 + 50, 30);//寻找结束之后,清除上一行皇后位置
}
}
}
}
int main()
{
char p;//判断是否进入程序产看八皇后结果
cout << "输入Y进入查看,N退出查看" << endl << "请输入:" << endl;
cin >> p;
while(p == 'Y')//进入产看选择循环,可多次查看两种结果展示
{
cout << "请输入1或者0:" << endl;
cout << "提示:1查看结果,0查看动态演示" << endl;
cin >> pp;
memset(k, 0, sizeof k);//清零二维数组
initgraph(1200, 800);//定义画布大小1200(长)*800(宽)
IMAGE img1; // 定义 IMAGE1 对象
loadimage(&img1, "D:\\WSX.jpg",400,250); // 读取图片到 img1 对象中
putimage(801, 0, &img1); // 在左上角的坐标 (801, 0) 位置显示 IMAGE1 对象
IMAGE img2;
loadimage(&img2, "D:\\WSX2.jpg", 400, 250);
putimage(801, 250, &img2);
IMAGE img3;
loadimage(&img3, "D:\\WSX3.jpg", 400, 250);
putimage(801, 500, &img3);
for (int i = 0; i < 800; i = i + 100) //创建8*8的白色边框网格棋盘
{
for (int j = 0; j < 800; j = j + 100)
{
setfillcolor(WHITE);
rectangle(j, i, j + 100, i + 100);
}
}
pan(0);//进入皇后的放置判断
//system("pause");
closegraph();//关闭画布,继续进入选择
system("pause");
cout << "继续查看输入Y,退出查看请输入N" << endl << "请输入:" << endl;
cin >> p;
}
cout << "感谢使用!" << endl;
system("pause");
return 0;
}