程式設計之美 遊戲之樂 中國象棋將帥問題

2021-09-28 19:36:55 字數 3039 閱讀 3161

下過中國象棋的朋友都知道,雙方的「將」和「帥」相隔遙遠,並且不能照面。在象棋殘局中,許多高手能利用這一規則走出許多精妙的殺招。假設棋盤上只有「將」和「帥」二子。(下面為了敘述方面,我們約定用a表示「將」,b表示「帥」)。 

a和b分別被限制在自己的九宮格內,不能走出九宮格,不能走斜線,只能走橫豎線上的一步。 

請寫出乙個程式,輸出a、b所有合法位置。要求**中只能使用乙個位元組儲存變數。

問題本身並不複雜,只要把所有a、b互相排斥的條件列舉出來就可以完成本題的要求。由於本題要求只能儲存使用乙個變數,所有首先必須想清楚在寫**的時候,有哪些資訊需要儲存,並且盡量高效地儲存資訊。稍微思考一下,可以知道這個程式的大體框架是:

遍歷a的位置 

遍歷b的位置 

判斷a,b的位置組合是否滿足要求。 

如果滿足,則輸出。

因此,需要儲存的是a、b的位置資訊,並且每次迴圈都要更新,首先建立乙個邏輯座標系統,乙個可行的辦法是用1-9的數字,按照行有限的順序來表示每個格點的位置。這樣,只需要用模餘運算就可以得到當前的列號,從而判斷a、b是否相斥

1   2   3 

4   5   6 

7   8   9 

第二,題目要求只用乙個變數,我們卻要儲存a和b兩個子的位置資訊,該怎麼辦呢?

對於bool型別,沒有辦法做任何擴充套件了,因為它只能表示true和false兩個值;而byte或int型別,它們能夠表達的資訊則更多。事實上,對於本題來說,每個子都只需要9個數字就可以表示它的全部位置。

乙個8位的byte型別能夠表達2^8=256個值,所以用它來表示a、b的位置資訊綽綽有餘。因此可以把這個位元組的變數(設為b)分為兩部分。用前面的4bit表示a的位置,用後面的4bit表示b的位置,而4個bit可以表示16個數。這已經足夠了。

問題在於:如何使用bit級的運算將資料從這一byte變數的左邊和右邊分別存入和讀出。

**如下:

#include #define half_bite_length 4

#define fulimask 255

#define lmask (fulimask << half_bite_length)

#define rmask (fulimask >> half_bite_length)

#define rset(b,n) (b=((lmask&b)|(n)))

#define lset(b,n) (b=((rmask&b)|((n) << half_bite_length)))

#define rget(b) (rmask & b)

#define lget(b) ((lmask & b) >> half_bite_length)

#define gridw 3

int main()

a= 1, b= 2

a= 1, b= 3

a= 1, b= 5

a= 1, b= 6

a= 1, b= 8

a= 1, b= 9

a= 2, b= 1

a= 2, b= 3

a= 2, b= 4

a= 2, b= 6

a= 2, b= 7

a= 2, b= 9

a= 3, b= 1

a= 3, b= 2

a= 3, b= 4

a= 3, b= 5

a= 3, b= 7

a= 3, b= 8

a= 4, b= 2

a= 4, b= 3

a= 4, b= 5

a= 4, b= 6

a= 4, b= 8

a= 4, b= 9

a= 5, b= 1

a= 5, b= 3

a= 5, b= 4

a= 5, b= 6

a= 5, b= 7

a= 5, b= 9

a= 6, b= 1

a= 6, b= 2

a= 6, b= 4

a= 6, b= 5

a= 6, b= 7

a= 6, b= 8

a= 7, b= 2

a= 7, b= 3

a= 7, b= 5

a= 7, b= 6

a= 7, b= 8

a= 7, b= 9

a= 8, b= 1

a= 8, b= 3

a= 8, b= 4

a= 8, b= 6

a= 8, b= 7

a= 8, b= 9

a= 9, b= 1

a= 9, b= 2

a= 9, b= 4

a= 9, b= 5

a= 9, b= 7

a= 9, b= 8

e:\source\repos\c_demo\debug\c_demo.exe (程序 10136)已退出,返回**為: 0。

若要在除錯停止時自動關閉控制台,請啟用「工具」->「選項」->「除錯」->「除錯停止時自動關閉控制台」。

按任意鍵關閉此視窗...

另一種解法:

因為兩個棋子都只有9種擺放的位置,兩個組合最多有9*9=81種位置,那麼我們擁有的變數只要可以表示這麼多變數就可以了,這樣的話byte,char都是可以的選擇。

int main() 

return 0;

}

這段**的想法就是把兩個資料的儲存方式變為乙個數字,這個數字是(a+1)*9+(b+1),兩個加一是為了讓最小的數字比如0–9之間的數也能起到作用。因為是從零開始,所以直到80就完成了對所有可能性的掃瞄。 

其中的結果要%3是因為需要知道ab位置的行數,如果行數相等就不輸出,如果不相等就輸出ab的值。

第三種解法:

struct

i;int main()

} }return 0;

}

這段**的想法和上乙個差不多,只是儲存方式更加直接,掃瞄方式也更加直接,沒有異議。用陣列中的第乙個數表示a的位置,用陣列中的第二個數表示b的位置。只是兩個byte是兩個位元組,是超過位元組限制。(如果不考慮位元組限制的話這也是乙個不錯的方法。)

第1章 遊戲之樂 中國象棋將帥問題

中國象棋裡面雙方的 將 和 帥 各自呆在自己的九宮格裡,一步只能橫移或縱移一格,而且雙方不能見面 既不能處在同一條縱線上 在殘局時有的人會用這一規則走出絕妙殺招。假設一方的 將 為a,另一方的 帥 為b,現在求雙方所能出現的所有合法位置,所需變數只能用乙個位元組來儲存。我們用1 9的數字來,按行優先...

第1章 遊戲之樂 中國象棋將帥問題

中國象棋裡面雙方的 將 和 帥 各自呆在自己的九宮格裡,一步只能橫移或縱移一格,而且雙方不能見面 既不能處在同一條縱線上 在殘局時有的人會用這一規則走出絕妙殺招。假設一方的 將 為a,另一方的 帥 為b,現在求雙方所能出現的所有合法位置,所需變數只能用乙個位元組來儲存。我們用1 9的數字來,按行優先...

《程式設計之美》 中國象棋將帥問題

即將面臨找工作,最近在看 程式設計之美 這本書。自己能力有限所以覺得有些題目難度不小,但仍覺受益匪淺,有時間一定再讀幾遍。下面是關於 中國象棋將帥問題 的一些心得 書中給出的演算法的精妙之處這裡不再贅述,給出自己的想法 原理與書中給出演算法相同,通過迴圈實現。對其中的任意乙個位置k,其餘8個位置都可...