Python算法之旅字符串游戲之九路棋盤

阿福:小美,聽說你學過海龜繪圖,能幫我用turtle?來畫一張棋譜嗎?

小美:什么棋譜?

阿福:就是一張9路圍棋盤的棋譜,它的樣子如圖1所示:

圖1

知識小貼士:

turtle?(海龜繪圖)很適合用來引導孩子學習編程。最初來自于Wally Feurzig 和 Seymour Papert 于1966 年所創(chuàng)造的 Logo 編程語言。它在繪圖區(qū)設置了一只想象中的小海龜(畫面顯示一個箭頭代表小海龜?shù)念^),起始位置在 x-y 平面的 (0, 0) 點,面向x軸正方向。小海龜根據(jù)一組函數(shù)指令的控制,在這個平面坐標系中移動,從而在它爬行的路徑上繪制了圖形。


小美:這種棋譜啊,小菜一碟!只要先畫橫豎各9條線,再畫上9個星位圓點,棋盤就畫好了。接下來把黑白棋子畫上去就行了。

阿福:說得簡單,有這么容易嗎?我也不讓你畫棋子,你先把棋盤畫出來給我看看?

小美:這有什么難的。我不僅可以畫出9路棋盤,還能把棋盤上的橫縱坐標標記也畫出來,甚至推廣到13路、19路棋盤上去,你只需修改棋盤路數(shù)和星位坐標就行了。

import turtle astt

'''

函數(shù)功能:根據(jù)輸入的棋盤的路數(shù),格子寬度和左上角坐標,畫一個圍棋盤

函數(shù)名:draw_go_board(n,s, x0, y0, point)

參數(shù)表:n -- 棋盤的路數(shù);s -- 棋盤格子寬度;

?????? x0, y0 --棋盤左上角坐標;point -- 存儲了星位坐標的元組。

返回值:沒有返回值。

'''

defdraw_go_board(n, s, x0, y0, point):

??? for command in ('寫字母', '寫數(shù)字'):

??????? if command == '寫字母':

??????????? x, y = x0, y0 + s * 2 / 3

??????????? a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

??????? else:

??????????? x, y = x0 - s * 2 / 3, y0 - s / 5

??????????? a = list(range(1,27))

??????? for c in a[:n]:

??????????? tt.penup()

??????????? tt.goto(x, y)

??????????? tt.pendown()

??????????? tt.write(c,align="center", font=("Arial", 16, "normal"))

??????????? if command == '寫字母':

??????????????? x += s

??????????? else:

??????????????? y -= s

??? forcommand in ('畫橫線', '畫豎線'):

??????? x, y = x0, y0

??????? for i in range(n):

??????????? tt.penup()

??????????? tt.goto(x, y)

??????????? tt.pendown()

??????????? tt.forward(s*(n-1))

??????????? if command == '畫橫線':

??????????????? y -= s

??????????? else:

??????????????? x += s

??????? tt.right(90)

??? for x, y in point: #畫星位

??????? tt.penup()

??????? tt.goto(x, y)

??????? tt.pendown()

??????? tt.dot(12)


tt.TurtleScreen._RUNNING= True? #啟動繪圖,在IDE中運行加這句可避免報錯

tt.speed(0)

tt.ht()#隱藏筆頭

#n, s, (x, y), s分別存儲了棋盤的路數(shù),格子寬度和左上角坐標

n, s, x, y = 9,60, -240, 240

#星位坐標

point =((-120,120),(0,120),(120,120),

???????? (-120,0),(0,0),(120,0),

???????? (-120,-120),(0,-120),(120,-120))

draw_go_board(n,

s, x, y, point) #畫n路棋盤

tt.done()

圖2

?阿福:你怎么那么厲害!看來我小瞧你了。那好,你現(xiàn)在把棋子畫上去吧。

小美:棋盤畫好以后,我們只要另外再寫一個畫棋子的draw_go_table()函數(shù)就行了。但是在調(diào)用draw_go_table()之前我們需要先把棋盤上各個交叉點的信息存儲起來,我們可以用列表go_table存儲這些信息,例如go_table[0] = '空空空空空空空空空'表示第1行上全是空子,go_table[3] = '空白空白白黑黑黑白'表示了第4行上黑白子的分布情況。

阿福:有道理!那具體的程序應該怎樣寫呢?

小美:我都說這么明白了,你還沒反應過來啊?看來“大熊貓”這個標簽你還得掛一段時間。看清楚了!

'''

函數(shù)功能:在已經(jīng)畫好的棋盤上,按棋盤位置順序添加棋子信息(隱藏手數(shù)編號)

函數(shù)名:draw_go_table(n,s, x0, y0, go_table)

參數(shù)表:n -- 棋盤的路數(shù);s -- 棋盤格子寬度;

?????? x0, y0 --棋盤左上角坐標;go_table-- 存儲了各交叉點信息的列表。

返回值:沒有返回值。

'''

def draw_go_table(n, s, x0, y0, go_table):

??? for i in range(n):

??????? x, y = x0, y0 - i * s+ s / 2

??????? for j in range(n):

??????????? if go_table[i][j]== '空': #跳過空子

??????????????? x += s

??????????????? continue

??????????? if go_table[i][j]== '黑': #畫黑子

???????????????tt.color('white', 'black')

??????????? else:????????????????????? #畫白子

??????????????? tt.color('black','white')

??????????? tt.penup()

??????????? tt.goto(x, y)

??????????? tt.pendown()

??????????? tt.begin_fill()

??????????? tt.circle(s*5/12)

??????????? tt.end_fill()

??????????? x += s


tt.TurtleScreen._RUNNING = True?#啟動繪圖,在IDE中運行加這句可避免報錯

tt.speed(0)

tt.ht()#隱藏筆頭

#n, s, (x, y), s分別存儲了棋盤的路數(shù),格子寬度和左上角坐標

n, s, x, y = 9, 60, -240, 240

#星位坐標

point = ((-120,120),(0,120),(120,120),

????????(-120,0),(0,0),(120,0),

????????(-120,-120),(0,-120),(120,-120))

draw_go_board(n, s, x, y, point) #畫n路棋盤

go_table = ['空空空空空空空空空','空空空空空空空空空','空空白空空白白白空',

??????????? '空白空白白黑黑黑白','空黑白白黑黑空黑空','空黑黑黑空空空空空',

??????????? '空空空空空空空空空','空空空空空空空空空','空空空空空空空空空']

draw_go_table(n, s, x, y, go_table) #畫棋譜(隱藏手數(shù)編號)

tt.done()

圖3

古老師:小美,又在欺負阿福了啊!你可別小看他,別看他嘴上不說,心里可清楚得很哪。不過小美這段時間進步確實挺大的,不僅能熟練使用各種turtle?方法,連自定義函數(shù)也寫得很漂亮了呢!但我不得不說的是,你畫的圖并不是真正的圍棋譜,真正的圍棋譜上面是要顯示手數(shù)編號的,就像圖4這種樣子:

圖4

阿福:沒錯,其實這張圖才是我想讓你畫的。

小美:那你不早說!不過要加上手數(shù)編號的話還真有點難度呢。不能簡單地用”黑白空”字符來表示了。不僅要包含棋子顏色信息,還要包含手數(shù)編號信息,那豈不是要用2個變量來表示同一個交叉點的信息?

阿福:其實一個變量就夠了,但是不能用字符,而要用整數(shù),0表示空子,正數(shù)表示黑子,負數(shù)表示白子,它們的絕對值表示手數(shù)編號。

古老師:有道理!阿福,不愧是初中生啊,數(shù)學沒有白學!小美,你知道負數(shù)嗎?

小美:知道的,興趣小組里老師講過。

古老師:那就好。這樣吧,小美,你先用阿福說的方法存儲棋盤上各個交叉點的信息,再用你剛才畫圖3的思路,按照從上到下、從左到右的順序把棋譜畫出來。阿福呢,給你一個更艱巨的任務:按照落子順序把棋譜畫出來。

阿福:古老師你偏心,凈挑難題考我。如果按照落子順序畫棋譜的話,那就需要存儲棋子的手數(shù)編號、顏色和坐標等信息了,原來的經(jīng)驗都沒用了,難度不止增大一點點啊。

古老師:誰叫你是高手呢,能者多勞嘛。不過你的思路是正確的,照著這個思路去做肯定能成功。這樣吧,今天我有事先走了。棋譜畫好了記得告訴我一聲哦。拜拜。


有事沒事最好拉到文末看看,說不定作者今天提供了彩蛋哦!

需要本文word版的,可以加入“Python算法之旅”知識星球參與討論和下載文件,“Python算法之旅”知識星球匯集了數(shù)量眾多的同好,更多有趣的話題在這里討論,更多有用的資料在這里分享。

我們專注Python算法,感興趣就一起來!


?彩蛋

小美:阿福,古老師很器重你啊!對了,畫那個帶手數(shù)編號的棋子,是不是要先把棋子畫好,再寫編號啊?

阿福:古老師就是嘴巴甜!你不也經(jīng)常被夸嗎?沒錯,如果先寫編號的話,填充棋子顏色的時候就會把編號覆蓋掉。好了,我們都抓緊時間行動吧,早點給古老師看結(jié)果。

小美:嗯。。。。。。我好了。

'''

函數(shù)功能:在已經(jīng)畫好的棋盤上,按棋盤位置順序添加棋子信息(顯示手數(shù)編號)

函數(shù)名:draw_go_table2(n,s, x0, y0, go_table)

參數(shù)表:n -- 棋盤的路數(shù);s -- 棋盤格子寬度;x0, y0

-- 棋盤左上角坐標;

go_table -- 存儲各交叉點信息的列表,0、正數(shù)和負數(shù)分別代表空、黑子和白子,其絕對值為手數(shù)編號。

返回值:沒有返回值。

'''?????

defdraw_go_table2(n, s, x0, y0, go_table):

??? for i in range(n):

??????? x, y = x0, y0 - i * s + s / 2

??????? for j in range(n):

??????????? if go_table[i][j] == 0: #跳過空子

??????????????? x += s

??????????????? continue

??????????? if go_table[i][j] > 0: #畫黑子

??????????????? tt.color('white', 'black')

??????????????? num = go_table[i][j]

??????????? else:????????????????? #畫白子

??????????????? tt.color('black', 'white')

??????????????? num = -go_table[i][j]

??????????? #畫棋子

??????????? tt.penup()

??????????? tt.goto(x, y)

??????????? tt.pendown()

??????????? tt.begin_fill()

??????????? tt.circle(s*5/12)

??????????? tt.end_fill()

??????????? #顯示手數(shù)編號

??????????? tt.penup()

??????????? tt.goto(x, y - s * 3 / 5)

??????????? tt.pendown()

??????????? tt.write(num,align="center", font=("Arial", 16, "normal"))

??????????? x += s


tt.TurtleScreen._RUNNING= True? #啟動繪圖,在IDE中運行加這句可避免報錯

tt.speed(0)

tt.ht()#隱藏筆頭

#n, s, (x, y), s分別存儲了棋盤的路數(shù),格子寬度和左上角坐標

n, s, x, y = 9,60, -240, 240

#星位坐標

point =((-120,120),(0,120),(120,120),

???????? (-120,0),(0,0),(120,0),

???????? (-120,-120),(0,-120),(120,-120))

draw_go_board(n,

s, x, y, point) #畫n路棋盤

go_table =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,-18,0,0,-14,-8,-12,0],

??????????? [0,-10,0,-4,-6,13,11,19,-20],[0,15,-16,-2,1,7,0,9,0],[0,17,5,3,0,0,0,0,0],

???????????[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]]

draw_go_table2(n,

s, x, y, go_table) #畫棋譜(顯示手數(shù)編號)

tt.done()


阿福:動作挺快啊!我也好了。


'''

函數(shù)功能:在已經(jīng)畫好的棋盤上,添加棋子信息(按落子順序顯示手數(shù)編號)

函數(shù)名:draw_go_table3(n,s, x0, y0, go_table)

參數(shù)表:n -- 棋盤的路數(shù);s -- 棋盤格子寬度;x0, y0

-- 棋盤左上角坐標;

?????? go_table --存儲了各交叉點信息的列表,其元素值為(手數(shù)編號,棋子顏色,橫坐標,縱坐標)。

返回值:沒有返回值。

'''?????

def draw_go_table3(n,s, x0, y0, go_table):

??? for go in go_table:

??????? num = go[0]

??????? x, y = x0+(ord(go[2])-ord('A'))*s,y0-(go[3]-1)*s+s/2

??????? if go[1] == '黑': #畫黑子

??????????? tt.color('white', 'black')

??????? else:???????????? #畫白子

??????????? tt.color('black', 'white')

??????? #畫棋子

??????? tt.penup()

??????? tt.goto(x, y)

??????? tt.pendown()

??????? tt.begin_fill()

??????? tt.circle(s*5/12)

??????? tt.end_fill()

??????? #顯示手數(shù)編號

??????? tt.penup()

??????? tt.goto(x, y - s * 3 / 5)

??????? tt.pendown()

??????? tt.write(num, align="center",font=("Arial", 16, "normal"))


tt.TurtleScreen._RUNNING= True? #啟動繪圖,在IDE中運行加這句可避免報錯

tt.speed(0)

tt.ht()#隱藏筆頭

#n, s, (x, y), s分別存儲了棋盤的路數(shù),格子寬度和左上角坐標

n, s, x, y = 9,60, -240, 240

#星位坐標

point =((-120,120),(0,120),(120,120),

???????? (-120,0),(0,0),(120,0),

???????? (-120,-120),(0,-120),(120,-120))

draw_go_board(n,

s, x, y, point) #畫n路棋盤

#棋譜(按落子順序顯示手數(shù)編號)?

go_table = [(1,'黑','E',5),(2,'白','D',5),(3,'黑','D',6),(4,'白','D',4),(5,'黑','C',6),

??????????? (6,'白','E',4),(7,'黑','F',5),(8,'白','G',3),(9,'黑','H',5),(10,'白','B',4),

??????????? (11,'黑','G',4),(12,'白','H',3),(13,'黑','F',4),(14,'白','F',3),(15,'黑','B',5),

??????????? (16,'白','C',5),(17,'黑','B',6),(18,'白','C',3),(19,'黑','H',4),(20,'白','I',4)]

draw_go_table3(n,

s, x, y, go_table) #畫棋譜(顯示手數(shù)編號)?

tt.done()

圖5

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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