n皇后c语言,N皇后问题摆法算法描述

题目说明:在一个N×N的国际象棋棋盘中摆N个皇后,使这N个皇后不能互相被对方吃掉。

题目要求:

(1)依次输出各种成功的放置方法。

(2)最好能画出棋盘的图形形式,并动态的演示试探过程。

(3)程序能方便的移植到其它规格的棋盘上。

例如:在一个4×4的棋盘可以摆放的棋位置{(0,1)(1,3)(2,0)(3,2)},{(0,2)(1,0)(2,3)(3,1)}两种。

题目分析:

一、试探过程分析:

N×N皇后问题的求解过程就是一个试探回逆的过程。如图-1

NQueen_img_0.jpg 

(图1-1)

1、首先查找第一行的可放位置,第一行全部可以放,那么我们就先将第一个皇后放在(0,0)点。

NQueen_img_1.jpg

(图1-2)

2、再查找第二行,由于第一行的(0,0)已经放了皇后,故第二行的(1,0)和(1,1)都能放皇后了,可放的就是(1,2)和(1,3)点,在(1,2)放上皇后。

NQueen_img_2.jpg

(图1-3)

3、再查找第三行,查找所以发现第三行没有可放的位置了,回逆到第二行讲皇后放到(1,3)再查找第3行。如果还不行,就回到第一行将第一行的皇后放人下一个可放的点,依次类推,查找N×N上的所以可放的位置,直到第一行所以位置被放完,输出结果。

4、根据上面的规律可以发现,对于一个皇后放在坐标(x,y),它的下一行位置为(x-1,y)(x,y)(x+1,y)的坐标都不能再放皇后。我们用一个数组来存放本行能放皇后的点。用循环来查找上面行对本行的影响,将收到影响的点置FAlSE。

5、计算公式为:iPlaceOver[col - (column - i)] = false;

iPlaceOver[col] = false;

iPlaceOver[col + (column - i)] = false;

其中col是上面行皇后的位置,column是当前的第N行。

6、跌代过程:for (i = 0 ; i < m_iCount ; i ++)

{

if (iPlaceOver) //如果是可以放皇后的位置

{

m_piSaveQPlace[column] = i;//保存位置

ComputQueenPlace(column + 1);//递归搜索下一行

}

}7、为了动态保存计算结果,程序使用了一个整形的数组指针存放每次结果中每行的位置。为了方便和清晰的显示,我使用了一个结构保存。

8、增加了一个位图保存函数,用来保存希望保存为位图的结果。

二、程序动态显示试探结果说明:

为了显示试探过程,把视图指针传为递归函数,用来在得到真确的结果的时候可以刷新视图显示结果。在显示的时候为了防止过分闪动,使用了内存DC将位图直接帖到视图中。

三、类结构规划:

class CQueen

{

private:

struct PlaceList

{

int*Place;

};

PlaceList * m_pPlaceList;

intm_iListMaxSize;

int m_iListNowSize;

intm_iCount;

CSizem_sizeView;

bool m_bRuning;

int*m_piSaveQPlace; // 存每行中皇后的位置

intm_iNowCol;

CBitmap *m_pGridBitmap;

intm_iDrawIndex;

public:

void DrawQueenN(CDC *pDC);

void DrawList(int index);

void ComputQueenPlace(int column , CView *view = NULL); // 皇后问题求解函数

CSize GetQueenGridSize();

int GetQueenPlace(int row);

int GetListSize();

int GetDrawIndex();

void SetRow(int row);

void SaveToBMPFile();

CQueen(int row);

CQueen();

~CQueen();

private:

void DrawGird(CDC *pDC);

void DrawQueen(CDC *pDC);

void AddPlace(int *place);

void FreeList();

};代码分析:

1、递归代码

void CQueen::ComputQueenPlace(int column , CView *view)

{

int row = 0;

int i ;

int col ;

m_iNowCol = column;

if (column == m_iCount) // 相等说明全部递归完成

{

AddPlace(m_piSaveQPlace);

m_bRuning = false;

return;

}

m_bRuning = true;

int *iPlaceOver = new int[m_iCount];

for ( i = 0 ; i < m_iCount ; i ++)// 初始化为都能放棋子

{

iPlaceOver = true;

}

// 将不能放棋子的点置False

for (i = 0 ; i < column ; i ++)

{

col = m_piSaveQPlace;

if ((col – (column – i)) >= 0)

{

iPlaceOver[col - (column - i)] = false;

}

if ((col + (column – i)) < m_iCount)

{

iPlaceOver[col + (column - i)] = false;

}

iPlaceOver[col] = false;

}

// 递归调用每一次的可能

for (i = 0 ; i < m_iCount ; i ++)

{

if (iPlaceOver)

{

m_piSaveQPlace[column] = i;

if (view != NULL && m_iDrawIndex == -1)

{

CDC *pDC = view->GetDC();

DrawQueenN(pDC);

view->ReleaseDC(pDC);

Sl eep(20);

}

ComputQueenPlace(column + 1 , view);

}

}

m_bRuning = false;

delete[] iPlaceOver;

m_iNowCol = 0;

}2、保存找到的点代码

void CQueen::AddPlace(int *place)

{

if (m_iListNowSize == m_iListMaxSize)

{

m_iListMaxSize += 10;

PlaceList *temlist = new PlaceList[m_iListMaxSize];

for ( int i = 0 ; i < m_iListNowSize; i ++)

{

temlist.Place = m_pPlaceList.Place;

}

delete[] m_pPlaceList;

m_pPlaceList = temlist;

}

int *iPlace = new int[m_iCount];

for ( int i = 0 ; i < m_iCount ; i ++)

{

iPlace = place;

}

m_pPlaceList[m_iListNowSize++].Place = iPlace;

}

用户使用:

NQueen_img_3.jpg

(图2-1)

程序运行结果:

NQueen_img_4.jpg

(图3-1)

结束语

这段时间有些空,写点数据结构课程设计上面的题目。以后将陆续发点这方面的代码,供大家一起交流,如果代码中有什么不妥当或不构完美的地方,也请大家不吝赐教。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值