<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          海龜繪圖案例分析之移動(dòng)火柴變等式游戲(3)

          共 5309字,需瀏覽 11分鐘

           ·

          2022-02-20 01:34

          說在前面

          移動(dòng)一根火柴棒使等式成立,是一種簡單有趣的智力游戲,只需具備簡單的算術(shù)知識(shí),就能參與游戲,老少皆宜,深受大家的喜愛。

          上兩節(jié)課我們已經(jīng)學(xué)習(xí)了創(chuàng)建題庫繪制七段管數(shù)字算式的方法,今天我們就把這兩者組合起來,并學(xué)習(xí)第三部分——點(diǎn)擊鼠標(biāo)移動(dòng)火柴棒。

          1.游戲基本框架

          本小游戲主要分為三個(gè)部分:創(chuàng)建題庫,繪制游戲界面和響應(yīng)屏幕事件。

          各部分對(duì)應(yīng)的自定義函數(shù)和主函數(shù)部分代碼框架如下所示:

          創(chuàng)建題庫部分我已經(jīng)在第一節(jié)課中做了詳細(xì)介紹,直接把源代碼復(fù)制過來就行了,繪制算式模塊相關(guān)函數(shù)我們?cè)诘诙?jié)課也已經(jīng)分析過了。接下來我將依次介紹繪制游戲界面和響應(yīng)屏幕事件。


          2.繪制游戲界面

          游戲界面主要包括標(biāo)題和3個(gè)功能鍵按鈕,點(diǎn)擊“隨機(jī)出題”按鈕后,還會(huì)在按鈕下方顯示題目。

          首先定義一個(gè)函數(shù)來輸出文字信息,代碼如下:

          '''函數(shù)功能:顯示提示信息函數(shù)名:draw_info(x, y, text, c, size, mypen)參數(shù)表:x, y -- 顯示信息位置;       text -- 顯示信息內(nèi)容;       c -- 畫筆顏色;       size -- 字體大??;       mypen -- 當(dāng)前畫筆對(duì)象。返回值:沒有返回值。'''def draw_info(x, y, text, c, size, mypen):    mypen.color(c)    mypen.clear()    mypen.penup()    mypen.goto(x, y)    mypen.pendown()    mypen.write(text, align="center", font=("Arial", size, "normal"))

          接下來繪制3個(gè)功能鍵按鈕,我們先在主函數(shù)中定義好功能鍵方框的大小,位置和文字等信息,然后調(diào)用自定義函數(shù)draw_keys()繪制功能鍵按鈕。相關(guān)代碼如下:

          #主函數(shù)部分draw_info(x0+300, y0+100, "移動(dòng)火柴算術(shù)游戲:左鍵點(diǎn)擊選擇的火柴棒或目的地,右鍵撤銷操作", 'black', 20, tt)key_w, key_h = 110, 35 #功能鍵方框大小key_pos = [(x0+100+i*(key_w+30), y0+80) for i in range(3)]key_text = ("隨機(jī)出題", "輸入題目", "顯示答案")for i in range(len(key_pos)): #繪制功能鍵按鈕    draw_keys(key_pos[i][0], key_pos[i][1], key_w, key_h, key_text[i], tt)#自定義函數(shù)'''函數(shù)功能:根據(jù)輸入的坐標(biāo)和大小,繪制方框和文字函數(shù)名:draw_keys(x, y, w, h, text, mypen)參數(shù)表:x, y -- 方框左上角坐標(biāo);        w, h -- 方框的寬和高;        text -- 方框中文字;        mypen -- 繪制方框和文字所需要的畫筆返回值:沒有返回值。'''def draw_keys(x, y, w, h, text, mypen):    mypen.penup()    mypen.goto(x, y)    mypen.down()    mypen.seth(0)    for i in range(2):        mypen.fd(w)        mypen.right(90)        mypen.fd(h)        mypen.right(90)    mypen.penup()    mypen.goto(x+w/2, y-h*5/6)    mypen.down()    mypen.write(text, align="center", font=("黑體", 18, "normal"))

          ?

          3.使用屏幕事件

          turtle使用onclick(fun, btn=1, add=None)函數(shù)來響應(yīng)單擊鼠標(biāo)事件,其中fun是該事件綁定的函數(shù)名,調(diào)用fun函數(shù)時(shí),系統(tǒng)自動(dòng)傳入兩個(gè)參數(shù)表示在畫布上點(diǎn)擊的坐標(biāo);btn表示鼠標(biāo)按鈕編號(hào),默認(rèn)值為1(鼠標(biāo)左鍵),也可以設(shè)置為2(鼠標(biāo)中間滾輪)或3(鼠標(biāo)右鍵)。

          我們?cè)谥骱瘮?shù)中添加如下代碼,即可使用屏幕事件:

          tt.onscreenclick(play_game, 1)????? #左鍵單擊(選擇來源地或目的地)

          tt.onscreenclick(cancel_game, 3)??? #右鍵單擊(撤銷剛才的移動(dòng)操作)

          ?

          4.單擊鼠標(biāo)左鍵

          本游戲的重頭戲是響應(yīng)單擊鼠標(biāo)左鍵事件。它根據(jù)玩家點(diǎn)擊的不同位置做出不同反應(yīng)。有效點(diǎn)擊位置有兩處:功能鍵方框和構(gòu)成算式的火柴棒。

          已知3個(gè)功能鍵方框的坐標(biāo)已經(jīng)存儲(chǔ)在列表key_pos中,所有火柴棒的坐標(biāo)已經(jīng)存儲(chǔ)在列表pos_map中,我們只需判斷鼠標(biāo)在畫布上點(diǎn)擊坐標(biāo)的所處范圍,就可以判斷玩家點(diǎn)擊的是哪個(gè)功能鍵或火柴棒。

          (1)???點(diǎn)擊“隨機(jī)出題”按鈕

              if key_pos[0][0] < x < key_pos[0][0]+key_w and key_pos[0][1]-key_h < y < key_pos[0][1]: #點(diǎn)擊“隨機(jī)出題”按鈕        from_num = to_num = -1 #火柴棒的來源地和目的地下標(biāo)        stick_flag = [False for i in range(25)] #判斷某根火柴棒是否已繪制,共25根         for p in stick_pens:            p.clear()        que_num = random.randint(0, len(ques)-1) #隨機(jī)生成題目編號(hào)        draw_expression(x0, y0, 'green', ques[que_num]) #繪制算術(shù)表達(dá)式

          代碼說明:程序用到了4個(gè)全局變量que_nu, from_num, to_num, stick_flag,每次出題時(shí)都先對(duì)它們進(jìn)行初始化處理,同時(shí)清除所有的火柴棒畫面,從題庫中隨機(jī)生成題目編號(hào),并繪制該題目算式。

          (2)???點(diǎn)擊“輸入題目”按鈕

              elif key_pos[1][0] < x < key_pos[1][0]+key_w and key_pos[1][1]-key_h < y < key_pos[1][1]: #點(diǎn)擊“輸入題目”按鈕        from_num = to_num = -1 #火柴棒的來源地和目的地下標(biāo)        stick_flag = [False for i in range(25)] #判斷某根火柴棒是否已繪制,共25根         for p in stick_pens:            p.clear()        try:            que = read_question() #從文本框手動(dòng)輸入題目,并檢查是否有解            if que: #要預(yù)防玩家取消輸入的情形                draw_expression(x0, y0, 'green', que) #繪制算術(shù)表達(dá)式                que_num = ques.index(que) #在題庫中查找該算術(shù)式的編號(hào),若無解則拋出異常        except ValueError:            draw_expression(x0+200, y0-250, 'red', '無解') #若為無效算式,顯示無解

          代碼說明:此段代碼的操作和“隨機(jī)出題”基本相同,只多了“從文本框手動(dòng)輸入題目,并檢查是否有解”的環(huán)節(jié)。程序使用內(nèi)置函數(shù)index()來查找算式在題庫中的編號(hào),若找不到則拋出異常,說明該算式無效。為避免因拋出異常而使程序中斷,需要使用try/except 語句來捕捉異常。

          自定義read_question()用來處理從列表框輸入題目的操作,代碼如下:

          '''函數(shù)功能:從列表框輸入原始算式函數(shù)名:read_question()參數(shù)表:無返回值:返回輸入的原始算式。'''def read_question():    s = tt.textinput("輸入原始算式", "請(qǐng)輸入原始算式")    que = []    if s:        for c in s:             if c != ' ':                que.append(c)????????return?''.join(que)

          (3)???點(diǎn)擊“顯示答案”按鈕

              elif key_pos[2][0] < x < key_pos[2][0]+key_w and key_pos[2][1]-key_h < y < key_pos[2][1]: #點(diǎn)擊“顯示答案”按鈕        for i in range(len(anss[que_num])): #顯示所有可能的答案,每行顯示一個(gè)答案            draw_expression(x0, y0-200*(i+1), 'red', anss[que_num][i])  

          代碼說明:此段代碼很簡單,只需根據(jù)題目編號(hào),顯示所有可能的答案即可。

          (4)???點(diǎn)擊火柴棒區(qū)域

              else:  #點(diǎn)擊火柴棒區(qū)域        stick_num = get_stick_num(x, y) #根據(jù)點(diǎn)擊位置坐標(biāo),獲取火柴棒的序號(hào)        if stick_num >= 0: #點(diǎn)中了某根火柴棒            if stick_flag[stick_num] and from_num == -1 and to_num == -1: #首次單擊,只能移動(dòng)已繪制的火柴棒,且只能移動(dòng)一次                from_num = stick_num                #繪制來源地火柴棒為紅色                draw_rectangle(pos_map[stick_num][0]+x0,pos_map[stick_num][1]+y0,pos_map[stick_num][2]+x0,pos_map[stick_num][3]+y0,'red',stick_pens[stick_num])            elif from_num != -1 and to_num == -1 and not stick_flag[stick_num]: #二次單擊,只能把火柴棒移動(dòng)到未繪制處                stick_pens[from_num].clear()                to_num = stick_num                stick_flag[from_num] = False                stick_flag[to_num] = True                #繪制目的地火柴棒為綠色                draw_rectangle(pos_map[stick_num][0]+x0,pos_map[stick_num][1]+y0,pos_map[stick_num][2]+x0,pos_map[stick_num][3]+y0,'green',stick_pens[stick_num])                #輸出答案是否正確                draw_info(x0+600, y0-100, show_answer(anss[que_num]), 'red', 60, stick_pens[25])

          代碼說明:首先調(diào)用get_stick_num(x, y)函數(shù),根據(jù)點(diǎn)擊位置坐標(biāo),獲取火柴棒的序號(hào),若未選擇任何火柴棒則返回-1。參考代碼如下:

          '''函數(shù)功能:根據(jù)鼠標(biāo)左鍵點(diǎn)擊的位置,獲取該位置火柴棒的序號(hào)函數(shù)名:get_stick_num(x, y)參數(shù)表:x, y -- 表示鼠標(biāo)在畫布上點(diǎn)擊的坐標(biāo)。返回值:返回該位置火柴棒在全局變量pos_map列表中的下標(biāo),若未選擇任何火柴棒則返回-1。 '''def get_stick_num(x, y): #獲取火柴棒的序號(hào)    for i, p in enumerate(pos_map):        if p[0]+x0 <= x <= p[2]+x0 and p[3]+y0 <= y <= p[1]+y0:            return i    return -1

          if stick_flag[stick_num] and from_num == -1 and to_num == -1用來判斷當(dāng)前被點(diǎn)中的火柴棒是否已經(jīng)被繪制?是否還沒有選中來源地和目的地火柴棒?當(dāng)結(jié)果均為真時(shí),表示是首次單擊來源地火柴棒。此時(shí)設(shè)置全局變量from_num = stick_num,并繪制被點(diǎn)中的火柴棒為紅色。

          elif from_num != -1 and to_num == -1 and not stick_flag[stick_num]用來判斷是否屬于第二次單擊?即來源地火柴棒已被選中,但目的地火柴棒尚未選中的情形。因?yàn)榈诙螁螕魰r(shí),只能把火柴棒移動(dòng)到未繪制處,故還要判斷當(dāng)前被選中的位置是否還沒有繪制火柴棒。

          如果是第二次單擊,則清除來源地火柴棒,設(shè)置全局變量to_num = stick_num,stick_flag[from_num] = False,stick_flag [to_num] = True,繪制目的地火柴棒為綠色,并輸出文字提示答案是否正確。

          其中自定義函數(shù)show_answer()用來判斷答案是否正確并顯示結(jié)果。參考代碼如下:

          '''函數(shù)功能:通過對(duì)比參考答案中火柴棒的分布情況,判斷玩家移動(dòng)火柴棒后組成算式是否為正確答案。其中全局變量stick_flag中存儲(chǔ)了玩家移動(dòng)火柴棒后組成算式中火柴棒的繪制情況;局部變量ans_stick_flag中存儲(chǔ)了正確答案組成算式中火柴棒的繪制情況。函數(shù)名:show_answer(ans)參數(shù)表:ans -- 當(dāng)前題目對(duì)應(yīng)的參考答案。返回值:若玩家答案與某個(gè)參考答案相同,則返回"正確",否則返回"錯(cuò)誤"。 '''def show_answer(ans): #判斷答案是否正確并顯示結(jié)果      for exp in ans: #可能有多個(gè)答案        ans_stick_flag = [False for i in range(25)] #判斷某根火柴棒是否已繪制,共25根        for i in (0, 1, 2):            for j in digits[int(exp[i*2])]:                ans_stick_flag[7*i+j] = True        for i in range(21, 25):            if i == 22 and exp[1] == '-': #減法沒有豎線                continue            ans_stick_flag[i] = True        if ans_stick_flag == stick_flag: #答案正確            return "正確"????return?"錯(cuò)誤"
          5.單擊鼠標(biāo)右鍵
          '''函數(shù)功能:當(dāng)已經(jīng)選擇或者移動(dòng)火柴棒后,在任意位置點(diǎn)擊右鍵均可撤銷相關(guān)操作函數(shù)名:cancel_game(x, y)參數(shù)表:x, y -- 表示鼠標(biāo)在畫布上點(diǎn)擊的坐標(biāo)。返回值:沒有返回值。 '''def cancel_game(x, y):    global from_num, to_num #火柴棒的來源地和目的地下標(biāo)    global stick_flag #記錄火柴棒是否已經(jīng)繪制        if from_num == -1: #沒有點(diǎn)擊火柴棒的來源地        return        if to_num != -1: #已經(jīng)移動(dòng)火柴棒,撤銷移動(dòng)操作        stick_flag[to_num] = False        stick_flag[from_num] = True        stick_pens[to_num].clear()        stick_pens[25].clear() #清除提示文字        to_num = -1        #還原已選擇火柴棒,并顯示其為紅色        draw_rectangle(pos_map[from_num][0]+x0,pos_map[from_num][1]+y0,pos_map[from_num][2]+x0,pos_map[from_num][3]+y0,'red',stick_pens[from_num])    else:  #尚未移動(dòng)火柴棒,撤銷選擇操作,并還原已選擇火柴棒的顏色為綠色        draw_rectangle(pos_map[from_num][0]+x0,pos_map[from_num][1]+y0,pos_map[from_num][2]+x0,pos_map[from_num][3]+y0,'green',stick_pens[from_num])        from_num = -1

          代碼說明:當(dāng)from_num的值為-1時(shí),表示還沒有選擇來源地火柴棒,則無需做任何撤銷操作;如果to_num != -1,表示已經(jīng)完成了第二次單擊(移動(dòng)火柴棒)操作,此時(shí)撤回移動(dòng)操作,回到第一次單擊(選中火柴棒)狀態(tài);若to_num == -1,表示僅完成第一次單擊(選中火柴棒)操作,此時(shí)撤銷操作會(huì)取消對(duì)來源地火柴棒的選擇,并還原其顏色為綠色。

          至此,所有功能模塊和核心代碼都已經(jīng)介紹完畢,你只需把這些代碼組合在一起,就能愉快地享受移動(dòng)火柴棒游戲了。


          課后作業(yè)

          1.本程序僅實(shí)現(xiàn)了移動(dòng)火柴棒游戲的基本功能,還有更多有趣的功能等待你來擴(kuò)展和開發(fā),例如增加計(jì)分功能,每答對(duì)1題記1分;又比如增加定時(shí)功能,限定時(shí)間內(nèi)未解題則自動(dòng)跳到下一題等。

          2.在第二節(jié)課的課后練習(xí)中我請(qǐng)大家用另一種思路繪制七段管算術(shù)表達(dá)式,細(xì)心的朋友可能會(huì)發(fā)現(xiàn)視頻中的算式就是用這種方法繪制的,看上去更美觀些。

          失之毫厘,謬以千里,繪圖方式的不一樣,會(huì)使得后面響應(yīng)鼠標(biāo)事件的代碼也大不相同。你能否畫出更具個(gè)性化的七段管數(shù)字,并完成整個(gè)游戲功能呢?

          ?

          需要本文PPT、源代碼和課后練習(xí)答案的,可以加入“Python算法之旅”知識(shí)星球參與討論和下載文件,Python算法之旅”知識(shí)星球匯集了數(shù)量眾多的同好,更多有趣的話題在這里討論,更多有用的資料在這里分享。

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

          相關(guān)優(yōu)秀文章:

          閱讀代碼和寫更好的代碼

          最有效的學(xué)習(xí)方式

          Python算法之旅文章分類

          海龜繪圖案例分析之移動(dòng)火柴變等式游戲(1)

          海龜繪圖案例分析之移動(dòng)火柴變等式游戲(2)

          瀏覽 130
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码人妻一区二区三区免费n鬼沢 | 性,国产三级在线 | 日韩理论视频 | 亚欧操逼 | 成人网站在线观看mv视频 |