VC版八皇后

一.  功能需求: 

1. 能夠讓玩家擺棋,並讓電腦判斷是否正確

2. 能讓電腦給予幫助(給出所有可能結果)

3. 實現悔棋功能

4. 實現重置功能

5. 添加點按鍵音效果更佳

二.  總體設計計:

1.   核心算法:

   遞歸實現(回溯算法):

   思路:按行分別安排皇后(Q),Q數目目前爲8.

           Q1從第一行第一列開始到最後一列,先放在第一列;

           Q2從第二行第一列到最後一列,每次都檢查衝突,不衝突纔可以落子;

           依次嘗試Qm… 如果Qm沒有可擺放的位置,則返回Qm-1,同時Qm-1放棄剛纔的位置;

           當Q1嘗試過首行的所有列的位置後,算法結束。

          統計遞歸併羅列所有解法。

2.   具體功能實現的設計:

(1)  電腦判斷玩家的擺法正確與否:

對每一個棋子向右、下、右下和左下四個方向檢查,若遇到任何一個方向存在棋子,則返回錯誤,若八個棋子都遍歷完後都不衝突,則返回正確。

(2)  電腦給予幫助:

調用核心算法,遍歷所有結果,並顯示結果

(3)  實現悔棋:

用棧來存儲每個棋子的位置,以實現悔棋。

(4)  實現重置:

將二維數組賦值爲空,並顯示。

(5)  加音樂:

使用sndPlaySound(lpSound1,SND_ASYNC|SND_MEMORY)函數播放音樂。

  

三.  詳細設計:

1. 電腦判斷玩家的擺法正確與否:

  //-------------電腦檢查玩家擺放是否正確----------------

bool CQueenDlg::Check()

{

    intcolumn = -1;

    introw  = -1;

    intcount = 0;

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

    {

       for(int j = 0 ; j < 8; j++)

       {

           if(Image[i][j]== 1 || Image[i][j] == 2)//若找到皇后,向左、下、右下、左下掃描看是否有與其在同一條線上的皇后

           {

              

              count++;

              if(column== j || row == i) //若右或下方是否有與其在一條斜線上的棋子

              {

                  returnfalse;

              }

              column= j;

              row= i;

              intm = i+1;

              intn = j+1;

              while(m< 8 && n < 8) //檢查其右下方是否有與其在一條斜線上的棋子

              {

                 

                  if(Image[m][n]== 1 || Image[m][n] == 2)

                  {

                     returnfalse;

                  }

                  m++;

                  n++;

              }

              m= i+1;

              n= j-1;

              while(m < 8 && n >-1)//檢查其左下方是否有與其在一條斜線上的棋子

              {

                  if(Image[m][n]== 1 || Image[m][n] == 2)

                  {

                     returnfalse;

                  }

                  m++;

                  n--;

              }

           }

       }

    }

    if(count!= 8)

    {returnfalse;}

    returntrue;

}

2. 電腦給予幫助:

//------------------存儲擺放的結果.----------------

voidCQueenDlg::StoreAllResult()

{

inti,j;

 

//  InitImage();

 

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

{

    for(j=0;j<8;j++)

    {

        if(line[i]==j)

        {

           if(Image[j][i]== 0)

           {

                StoreImage[answer][j][i] = 1;

           }

           elseif(Image[j][i] == -1)

           {

             StoreImage[answer][j][i] = 2;

           }

        }  

    }

}

 

   answer++;

 

}

//-----------判斷擺放的位置是否正確,不正確返回1,正確返回0.-------------

int CQueenDlg::Judge(int t)

{

inti,n=0;

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

{

    if(line[i]==line[t])

    {

        n=1;

        break;

    }

    if(line[i]+i==line[t]+t)

    {

        n=1;

        break;

    }

    if(line[i]-i==line[t]-t)

    {

        n=1;

        break;

    }

}

returnn;

}

//--------------主要控制函數.----------------

void CQueenDlg::control(intn)

{

intt=8;

for(line[n]=0;line[n]<t;line[n]++)

{

    if(Judge(n))

        continue;

    else

    {

        if(n!=7)

           control(n+1);

        else

        {

            StoreAllResult();          

        }

    }

}

}

3. 實現悔棋:

 //---------悔棋(消息響應函數)-----------------

void CQueenDlg::OnBtnReback()

{

    //TODO: Add your control notification handler code here

    introw,column;

    if(!IsComputerHelp)

    {

       if(queen!= 0)

       {

           queen--;

           row= storeStep[queen].row;//存放每個棋子的位置(即列號)

           column= storeStep[queen].column;

       if(Image[row][column]== 1) //原皇后背景爲白色,設置爲白色

           {

              Image[row][column]= 0;

           }

    elseif(Image[row][column] == 2) //原皇后背景爲黑色,設置爲黑色

           {

              Image[row][column]= -1;

           }

           Invalidate(FALSE);

       }

    }

   

}

4. 實現重置:

 //-----------初始化界面的二維數組---------------

void CQueenDlg::InitImage()

{

    intm = 0;

    for(inti = 0; i < 8 ; i++)

       {

           for(intj = 0; j < 8; j++)

           {

              if(m%2== 0)

              {

                  Image[i][j]= 0;

              }

              else

              {

                  Image[i][j]= -1;

              }

              m++;

           }

           m++;

       }

}

5. 加音樂:

  void CQueenDlg::PlayMusic(int Id)

{

    ////////////加按鍵音

    switch(Id)

    {

    case1:res=FindResource(::AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_WAVE_PUTSTONE),"WAVE");break;//落子音樂

    case 2:res=FindResource(::AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_WAVE_ERROR),"WAVE");break;//不能落子音樂

    case3:res=FindResource(::AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_WAVE_WIN),"WAVE");break;   //玩家勝利音樂

    case4:res=FindResource(::AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_WAVE_LOSE),"WAVE");break;  //玩家失敗音樂

    default:break;

    }

   

    hSound1=LoadResource(::AfxGetApp()->m_hInstance,res);

    lpSound1=(LPSTR)LockResource(hSound1);

                  sndPlaySound(lpSound1,SND_ASYNC|SND_MEMORY);

}

四.  測試與實現:

 


  

五.  總結:

    通過對八皇后問題的求解,使我對遞歸算法有了更進一步的瞭解,類似八皇后及迷宮這樣的問題都可以用回溯算法來解決。這些都是數據結構與算法中重要的算法,當時學的不是很好,通過不斷地練習才逐步掌握了。

本程序的優點:實現了八皇后的基本功能,實現了悔棋功能,界面友好,有音樂提示等。

本程序的缺點:只實現了八皇后,而沒能實現五皇后、六皇后等其他格式,提示與找出玩家錯誤不足等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章