馬踏棋盤算法

由于今天的馬踏棋盤算法并不是使用OC編寫丙躏,所以择示,今天的標(biāo)題也就不是"使用OC....."了,下面直接開始我們的正題晒旅,還是老規(guī)矩栅盲,先上一張圖:

馬踏棋盤示意圖.png

我們的需求是,將"馬"放在任意制定的方格中废恋,按照"馬"走棋的規(guī)則將"馬"進(jìn)行移動谈秫。要求每個方格只能進(jìn)入一次,最終使得"馬"走遍棋盤的64個方格鱼鼓。并且將馬走的步數(shù)標(biāo)記出來拟烫,也就是第一步就標(biāo)記為1,第二步就標(biāo)記為2迄本、依次類推硕淑,直到馬走完了64個位置之后那么就算完成了,下面我們直接來看代碼,因為我在代碼里就已經(jīng)將思路標(biāo)記上了喜颁,每一句代碼幾乎都有詳細(xì)的注釋:

#define MaxRow 8//最大行
#define MaxCol 8//最大列
int chess[MaxRow][MaxCol];//棋盤二維數(shù)組

#pragma  mark -  馬踏棋盤算法(騎士周游問題)
#pragma  mark -

/**
 對八種情況分析尋找下一步可以走的位置

 @param x 當(dāng)前馬所在棋盤位置的x坐標(biāo)
 @param y 當(dāng)前馬所在棋盤位置的y坐標(biāo)
 @param count 不考慮邊緣的情況,馬在任意一位置的下一個位置都可能有八種情況曹阔,count就是對這八種情況進(jìn)行判斷
 只要找到其中一種就返回1
 @return 找到返回1半开,否則返回0
 */
int nextStep(int *x ,int *y,int count) {
    switch(count)
    {
        case 1:
            if(*x + 2 <= MaxCol - 1 && *y - 1 >= 0 && chess[*x + 2][*y - 1] == 0)
            {
                *x += 2;
                *y -= 1;
                return 1;
            }
            break;
        case 2:
            if(*x + 2 <= MaxCol - 1 && *y + 1 <= MaxRow - 1 && chess[*x + 2][*y + 1] == 0)
            {
                *x += 2;
                *y += 1;
                return 1;
            }
            break;
        case 3:
            if(*x + 1 <= MaxCol - 1 && *y - 2 >= 0 && chess[*x + 1][*y - 2] == 0)
            {
                *x += 1;
                *y -= 2;
                return 1;
            }
            break;
        case 4:
            if(*x + 1 <= MaxCol - 1 && *y + 2 <= MaxRow - 1 && chess[*x + 1][*y + 2] == 0)
            {
                *x += 1;
                *y += 2;
                return 1;
            }
            break;
        case 5:
            if(*x - 2 >= 0 && *y - 1 >= 0 && chess[*x - 2][*y - 1] == 0)
            {
                *x -= 2;
                *y -= 1;
                return 1;
            }
            break;
        case 6:
            if(*x - 2 >= 0 && *y + 1 <= MaxRow - 1 && chess[*x - 2][*y + 1] == 0)
            {
                *x -= 2;
                *y += 1;
                return 1;
            }
            break;
        case 7:
            if(*x - 1 >= 0 && *y - 2 >= 0 && chess[*x - 1][*y - 2] == 0)
            {
                *x -= 1;
                *y -= 2;
                return 1;
            }
            break;
        case 8:
            if(*x - 1 >= 0 && *y + 2 <= MaxRow - 1 && chess[*x - 1][*y + 2] == 0)
            {  
                *x -= 1;  
                *y += 2;  
                return 1;  
            }  
            break;  
        default:  
            break;  
    }  
    return 0;
}



/**
 深度優(yōu)先搜索

 @param x 開始搜索的x
 @param y 開始搜索的y
 @param step 第多少步
 @return 返回1表示下一步可行 0表示不可行
 */
int TraversalChessBoard(int x ,int y ,int step) {
    //臨時變量記錄當(dāng)前位置x和y
    int x1 = x,y1 = y;
    //flag作為標(biāo)記是否找到下一個位置 count為遍歷的8中情況
    int flag =0,count = 1;
    //標(biāo)記當(dāng)前的位置已經(jīng)被??踏過 標(biāo)記為step,也就是剛剛走的是第多少步
    chess[x][y] = step;
    //當(dāng)步數(shù)剛好等于棋盤的格子個數(shù) 就證明已經(jīng)走完了
    if (step == MaxRow * MaxCol) {
        //成功 打印結(jié)果
        Print();
        return 1;
    }
    
    //沒有走完就 尋找下一個位置并且將八種情況都走一遍
    flag = nextStep(&x1, &y1, count);
    //只要flag為0證明上一次沒有找到下一步赃份,這里我們把剩下的其他位置都走一遍
    while (flag == 0 && count < MaxRow) {
        //讓走法+1
        count++;
        //讓flag重新標(biāo)記
        flag = nextStep(&x1, &y1, count);
    }
    
    //當(dāng)找到下一個位置了之后寂拆,就從找到的位置開始繼續(xù)遞歸尋找
    while (flag) {
        // 遞歸調(diào)用走向下一個位置,因為在NextStep函數(shù)中直接修改了當(dāng)前位置的坐標(biāo)抓韩,所以此時的x1和y1就表示下一個可走位置的坐標(biāo)
        if (TraversalChessBoard(x1, y1, step+1)) {
            return 1;
        }
        //如果不是返回1纠永,那證明剛剛的路徑?jīng)]法走完 我們就回溯到上一個位置去
        x1 = x;
        y1 = y;
        // 前count種可走位置的情況都判斷過了,從count+1種情況繼續(xù)判斷
        count++;
        //沒有走完就 尋找下一個位置并且將八種情況都走一遍
        flag = nextStep(&x1, &y1, count);
        //只要flag為0證明上一次沒有找到下一步谒拴,這里我們把剩下的其他位置都走一遍
        while (flag == 0 && count < MaxRow) {
            //讓走法+1
            count++;
            //讓flag重新標(biāo)記
            flag = nextStep(&x1, &y1, count);
        }
        
    }
    
    //如果八種情況都是沒法找到合適的位置 那就從當(dāng)前位置回退到上一個位置 返回0就行 而且將二維數(shù)組中的位置置為0 證明它沒有走過
    if (0 == flag) {
        chess[x][y] = 0;
    }
    
    return 0;
}

/**
 * 打印棋盤尝江,棋盤中每個格子的數(shù)值就是遍歷的次序
 */
void Print()
{
    int i, j;
    for(i = 0; i < MaxRow; i++)
    {
        for(j = 0; j < MaxCol; j++)
        {
            printf("%2d\t", chess[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

這里我需要對第一個方法也就是nextStep這個方法進(jìn)行一下說明,這個方法是用于尋找馬下一步要走的位置英上,假如我們當(dāng)前要走到1這個位置炭序,那么x需要-1 ,y則需要-2苍日,然后再判斷一下是否跑出了棋盤的位置惭聂,接著還需要判斷1這個位置是否馬已經(jīng)走過了,如果上面我說的幾種情況都滿足了相恃,那么就說明這個位置是可以走的辜纲,就返回1,這就是這個方法大概的意思拦耐,不考慮邊緣情況下耕腾,馬總共有8種方式可以走,因此這里通過一個switch對8中情況進(jìn)行了考慮杀糯,接著就是TraversalChessBoard這個方法了幽邓,這個方法里面我已經(jīng)寫上了詳細(xì)的注釋了,應(yīng)該都能看懂了火脉,當(dāng)然牵舵,注重要的是得理解,如果不理解倦挂,也是很難看明白的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末畸颅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子方援,更是在濱河造成了極大的恐慌没炒,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犯戏,死亡現(xiàn)場離奇詭異送火,居然都是意外死亡拳话,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門种吸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弃衍,“玉大人,你說我怎么就攤上這事坚俗【刀ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵猖败,是天一觀的道長速缆。 經(jīng)常有香客問我,道長恩闻,這世上最難降的妖魔是什么艺糜? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮幢尚,結(jié)果婚禮上倦踢,老公的妹妹穿的比我還像新娘。我一直安慰自己侠草,他們只是感情好辱挥,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著边涕,像睡著了一般晤碘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上功蜓,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天园爷,我揣著相機與錄音,去河邊找鬼式撼。 笑死童社,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的著隆。 我是一名探鬼主播扰楼,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼美浦!你這毒婦竟也來了弦赖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浦辨,失蹤者是張志新(化名)和其女友劉穎蹬竖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡币厕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年列另,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旦装。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡页衙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出同辣,到底是詐尸還是另有隱情拷姿,我是刑警寧澤惭载,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布旱函,位于F島的核電站,受9級特大地震影響描滔,放射性物質(zhì)發(fā)生泄漏棒妨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一含长、第九天 我趴在偏房一處隱蔽的房頂上張望券腔。 院中可真熱鬧,春花似錦拘泞、人聲如沸纷纫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辱魁。三九已至,卻和暖如春诗鸭,著一層夾襖步出監(jiān)牢的瞬間染簇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工强岸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锻弓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓蝌箍,卻偏偏與公主長得像青灼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子妓盲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 最近在學(xué)習(xí)深度優(yōu)先搜索算法聚至,接觸到了馬踏棋盤,決定嘗試一下本橙。 涉及算法:遞歸扳躬,回溯法,深度優(yōu)先搜索算法 題目需求:...
    鳳凰城的傳說閱讀 1,997評論 1 4
  • 圖的深度優(yōu)先遍歷思想 圖的遍歷通常有兩種遍歷次序方案: 深度優(yōu)先遍歷和廣度優(yōu)先遍歷。深度優(yōu)先遍歷(DepthFir...
    AceKitty閱讀 3,242評論 1 4
  • 問題定義: 將馬隨機放在國際象棋的Board[0~7][0~7]的某個方格中贷币,馬按走棋規(guī)則進(jìn)行移動击胜。,走遍棋盤上全...
    maskwang520閱讀 639評論 0 2
  • Q0: 樓主我練了你推薦的役纹,怎么感覺一點都不厲害芭妓ぁ! A0: 吾日三醒吾身 滿級了嗎 滿寶具了嗎 芙芙喂足了嗎 三...
    cec21530c5dd閱讀 762評論 0 0
  • 時間真快促脉,今天周四辰斋,馬上周末啦 今年于我來說,周日是新一周的開始瘸味;那么這周除了每日學(xué)習(xí)任務(wù)正常進(jìn)行外宫仗,還需要讀兩本...
    HHzhao閱讀 172評論 0 0