首頁 > 軟體

Python+Turtle製作海龜迷宮小遊戲

2022-04-15 10:01:43

導語

哈嘍!大家好!我是木木子~

縱觀之前的文章——我發現了一個特點,很多小夥伴兒都喜歡學習Turtle或遊戲程式碼,沒錯吧~

那今天這篇文章就是為這2方面的小夥伴兒精心準備滴!Turtle+遊戲一起安排一波啦!

從Turtle開始介紹—基礎知識到實踐案例這篇文章都寫到了嘞!不要以為是單單一個專案哦,想學Turtle的必學篇,不要錯過啦~

最後今天小編會帶大家寫一個利用Turtle的一款海龜闖關的三大迷宮哦!這工程量還是挺大的!都是繪製下來的話程式碼量比較多了撒,400行程式碼才完成這款“海龜闖關走迷宮的”小遊戲!

一、簡介

1.什麼是Turtle

Turtle英譯過來為烏龜,不過我們介紹的不是這種動物,而是以此命名的一個繪圖軟體。

在python檔案中介紹了Turtle本身是一款簡單、易上手的繪圖軟體,非常適合新手進入程式設計的世界。

海龜繪圖Turtle是Python內建模組,總之是非常簡單好玩的一個庫。

其動作主要有:擡筆,此後的動作只是移動畫筆,畫布上不會留下痕跡;落筆,只要移動畫筆,畫布上就會留下痕跡。

畫筆動作只絕對移動、相對移動、向前(後)移動、轉向(絕對角度、相對角度)、圓或圓弧、點(實心圓),故畫不了橢圓,繪製函數曲線困難!

2.怎麼玩轉Turtle

當然在這裡需要進入python程式設計環境,然後在這個python檔案中就可以開始動手寫有關turtle的程式碼。

Turtle是python安裝時自帶的內建模組,呼叫該模組非常簡單,直接使用import方式載入:

import turtle 或 from turtle import *

這也是程式的第一行程式碼,用於準備好使用turtle這個模組。

3.畫布的設定

1.1設定畫布大小

turtle.screensize()       # 返回預設大小(400, 300)

1.2以預設繪圖視窗大小顯示視窗,視窗居螢幕中心

turtle.screensize(width, hight[, bg])

其中:width——表示畫布寬度(單位畫素);Hight——表示畫布高度(單位畫素);bg——畫布背景顏色,該引數可預設,預設時為白色背景

1.3案例

如:

turtle.screensize(800, 600, "green"),表示畫布大小為800×600,綠色畫布。
turtle.setup(width, hight[, x, y])

其中:width, height——表示畫布寬和高。當為整數時表示畫素;為小數時則表示佔據計算機螢幕的比例

4.設定背景/畫布顏色

turtle.bgcolor()

二、Turtle的畫筆設定

turtle.pensize(size)

其中:size——畫筆粗細,用畫素表示。

1.turtle繪圖的基本方法

匯入turtle庫繪圖模組後,就可以實現繪圖,基本操作是向前(後)畫直線,旋轉(向左向右改變方向),畫圓(圓弧)等。

這裡介紹幾個最常用的命令。

1.1設定畫筆的屬性

命令 說明
turtle.pensize(width)用於設定畫筆的寬度(即粗細),width越大越粗
turtle.pencolor(color)用於設定畫筆的顏色,color引數可以是字串如"green","red",也可以是RGB三元組
turtle.shape(shape)用於設定畫筆的形狀,shape引數為字串,主要包含“turtle”烏龜形狀,“square”正方形形狀等
turtle.speed(speed)用於設定畫筆的移動速度。speed引數可以是字串如“fast”,"slow"等,也可以是0到10間的整數

1.2畫筆繪圖的命令

命令說明
turtle.fd(dis)沿當前畫筆方向向前移動dist畫素長度
turtle.bk(dist)沿當前畫筆相反方向移動dist畫素長度
turtle.right(degree)沿當前畫筆方向向右轉degree°
turtle.left(degree)沿當前畫筆方向向左轉degree°
turtle.down()將畫筆放下,開始畫圖
turtle.up()提起筆移動,不繪製圖形
turtle.circle()畫圓,半徑為正(負),表示圓心在畫筆的左邊(右邊)畫圓
setx( )將當前x軸移動到指定位置
sety( )將當前y軸移動到指定位置
setheading(degree)用於設定畫筆的方向,引數degree為畫筆方向與海龜座標系x軸正向的夾角度數
ht()用於將畫筆隱藏

三、最後的案例Turtle小遊戲

1.設計思路遊戲規則

這個海龜闖關的小迷宮遊戲是設計了三個關卡,執行程式碼之後會有相應的關卡彈窗設定,想完那關可以直接玩那關, 也可以按照順序闖關。

特別注意:

很多人擔心過不了關?沒關係,小編給大家開了一個掛,這個掛就是按住F1就出現了迷宮的路線圖哦!按住F2就是出現了一個海龜到起點自己走路線哈!

2.準備環節

小編用的Python3、Pycharm2021、Turtle模組匯入即可。

然後相應的圖片素材:

3.正式敲程式碼

# -*- coding: UTF-8 -*-
"""
原始碼基地:#806965976#
csdn賬號:顧木子吖
海龜迷宮闖關遊戲
"""
 
import turtle  # 匯入海龜繪圖模組
import random  # 匯入亂數模組
 
game_title = '小海龜大迷宮闖關小遊戲'  # 遊戲名字
 
level = 0  # 關卡
 
'''繪製地圖用的全域性變數'''
txt_path = 'map/map1.txt'  # 地圖資訊文字檔案路徑及名稱
road_color = (191, 217, 225)  # 迷宮通道的顏色
R, C = 0, 0  # 迷宮地圖的總行數R、總列數C
cell_size = 20  # 一個格子的尺寸
area_sign = {}  # 記錄入口和出口索引位置
mazeList = []  # 地圖列表
 
'''海龜物件'''
map_t = turtle.Turtle()  # 繪製地圖的海龜
map_t.speed(0)  # 設定繪圖速度最快(地圖繪製)
sign_t = turtle.Turtle()  # 繪製入口和出口標記的海龜
 
auto_t = turtle.Turtle()  # 自動走迷宮的海龜
auto_t.pensize(5)  # 畫筆粗細(自動)
auto_t.speed(0)  # 設定繪圖速度最快(手動)
auto_t.ht()  # 隱藏海龜遊標
 
manual_t = turtle.Turtle()  # 手動走迷宮的海龜
manual_t.pensize(5)  # 畫筆粗細(手動)
manual_t.speed(0)  # 設定繪圖速度最快(手動)
manual_t.shape('turtle')  # 設定海龜遊標為小海龜(手動)
manual_t.ht()  # 隱藏手動走迷宮所用的海龜遊標(手動)
 
# 要探索4個方向對應索引的變化規則
direction = [
    (1, 0),  # 右
    (-1, 0),  # 左
    (0, 1),  # 上
    (0, -1)  # 下
]
 
 
def imoveto(ci, ri):
    """
    功能:根據索引位置移動海龜(不畫線)
    :param ci: 列索引
    :param ri: 行索引
    :return:
    """
    auto_t.penup()  # 擡筆
    cx, cy = itoc((ci, ri))  # 將索引位置轉換為座標位置
    auto_t.goto(cx, cy)  # 移動到指定位置
    auto_t.pendown()  # 落筆
    auto_t.shape('turtle')  # 設定海龜遊標的形狀
    auto_t.color('red')  # 設定畫筆顏色為紅色
    auto_t.st()  # 顯示海龜遊標
 
 
def c_move_to(t, ctuple):  # 移動到指定位置
    """
    功能:根據座標位置移動到指定位置(不畫線)
    :param t: 海龜物件
    :param ctuple: 記錄座標位置的元組
    :return:
    """
    t.ht()  # 隱藏海龜遊標
    t.penup()  # 擡筆
    t.goto(ctuple[0], ctuple[1])  # 移動到座標指定的位置
    t.pendown()  # 落筆
 
 
def itoc(ituple):
    """
    將索引位置轉換為實際座標位置
    :param ituple: 行、列索引組成的元組
    :return: 實際座標位置
    """
    ci = ituple[0]
    ri = ituple[1]
    tx = ci * cell_size - C * cell_size / 2  # 根據索引值計算每個正方形的起點(x座標)
    ty = R * cell_size / 2 - ri * cell_size  # 根據索引值計算每個正方形的起點(y座標)
    cx = tx + cell_size / 2  # 正方形中心的x座標
    cy = ty - cell_size / 2  # 正方形中心的y座標
    return (cx, cy)
 
 
def ctoi(cx, cy):
    """
    根據cx和cy求在列表中對應的索引
    :param cx: x軸座標
    :param cy: y軸座標
    :return: 元組,(ci,ri)
    """
    ci = ((C - 1) * cell_size / 2 + cx) / cell_size  # 計算列索引
    ri = ((R - 1) * cell_size / 2 - cy) / cell_size  # 計算行索引
    return (int(ri), int(ci))  # 返回行列索引的元組
 
 
def get_map(filename):
    """
    功能:讀取儲存地圖的文字檔案內容到列表
    :param filename: 地圖檔名
    :return: 地圖列表
    """
    with open(filename, 'r') as f:  # 開啟檔案
        fl = f.readlines()  # 讀取全部行
    maze_list = []  # 儲存地圖的列表
    for line in fl:  # 將讀取的內容以空格分割為二維列表
        line = line.strip()  # 去掉空格
        line_list = line.split(" ")  # 以空格進行分割為列表
        maze_list.append(line_list)  # 將分割後的列表新增到地圖列表中
    return maze_list  # 返回地圖列表
 
 
def draw_square(ci, ri, colorsign):
    """
    功能:繪製組成地圖的小正方形
    :param ci: 列索引
    :param ri: 行索引
    :param colorsign: 填充顏色
    :return:
    """
    tx = ci * cell_size - C * cell_size / 2  # 根據索引值計算每個正方形的起點(x座標)
    ty = R * cell_size / 2 - ri * cell_size  # 根據索引值計算每個正方形的起點(y座標)
    map_t.penup()  # 擡筆
    map_t.goto(tx, ty)  # 移動到繪圖起點(正方形的左上角)
    if colorsign == '1':  # 判斷是否為牆(如果為牆,則隨機生成填充顏色)
        r = random.randint(100, 130)  # 紅色值
        g = random.randint(150, 180)  # 綠色值
        map_t.color(r, g, 200)  # 指定顏色為隨機生成的顏色
    else:
        map_t.color(colorsign)  # 設定為指定的通道顏色
    map_t.pendown()  # 落筆
    map_t.begin_fill()  # 填充開始
    for i in range(4):  # 繪製正方形
        map_t.fd(cell_size)
        map_t.right(90)
    map_t.end_fill()  # 填充結束
    map_t.ht()  # 隱藏海龜遊標
 
 
def draw_map(mazelist):
    """
    功能:遍歷地圖列表繪製迷宮地圖
    :param mazelist: 儲存地圖資料的列表
    :return:
    """
    turtle.tracer(0)  # 隱藏動畫效果
    global area_sign  # 全域性變數,記錄入口和出口索引位置
    for ri in range(R):  # 遍歷行
        for ci in range(C):  # 遍歷列
            item = mazelist[ri][ci]
            if item in ['1']:  # 判斷牆
                draw_square(ci, ri, '1')  # 繪製牆
            elif item == "S":  # 判斷入口
                draw_square(ci, ri, road_color)  # 繪製通道
                draw_sign(ci - 1, ri, '入口')  # 標記入口
                area_sign['entry_i'] = (ci, ri)  # 儲存入口索引
            elif item == "E":  # 判斷出口
                draw_square(ci, ri, road_color)  # 繪製通道
                draw_sign(ci - 1, ri, '出口')  # 標記出口
                area_sign['exit_i'] = (ci, ri)  # 儲存出口索引
            else:
                draw_square(ci, ri, road_color)  # 繪製通道
    turtle.tracer(1)  # 顯示動畫效果
 
 
def draw_sign(ci, ri, word):
    """
    功能:繪製入口和出口標記
    :param ci: 列索引
    :param ri: 行索引
    :param word: 標記文字內容
    :return:
    """
    cx, cy = itoc((ci, ri))  # 將索引位置轉換為座標位置
    sign_t.ht()  # 隱藏海龜遊標
    sign_t.penup()  # 擡筆
    sign_t.goto(cx, cy)  # 移動到標記位置
    sign_t.color('red')  # 設定畫筆為紅色
    sign_t.write(word, font=('黑體', 12, 'normal'))  # 繪製標記文字
 
 
def win_tip():
    """
    功能:製作過關提示
    :return:
    """
    global level
    c_move_to(manual_t, (-150, 0))
    manual_t.color('blue')
    if int(level) == 3:
        manual_t.write('n恭喜您順利通關!', font=('黑體', 20, 'bold'))
        turtle.onkey(turtle.bye, key='Return')  # 監聽按下Enter鍵退出遊戲
    else:
        manual_t.write('n恭喜過關!n按下Enter進入下一關!', font=('黑體', 20, 'bold'))
        level += 1
        manual_t.color('red')
        turtle.onkey(level_init, key='Return')  # 監聽按下Enter鍵
 
 
def manual_move(d):
    """
    功能:手動走迷宮時通用探索並移動函數
    :param d: 向不同方面走時索引的變化規則
    :return:
    """
    dc, dr = d  # 將表示方向的元組分別賦值給兩個變數dc和dr,其中dc為x軸方向,dr為y軸方向
    rici = ctoi(round(manual_t.xcor(), 1) + dc * cell_size, round(manual_t.ycor(), 1) + dr * cell_size)  # 獲取行列索引
    point = mazeList[rici[0]][rici[1]]  # 獲取地圖列表中對應點的值
    print('移動:', rici, point)
    if point == '0':  # 通路
        manual_t.color('red')
        mazeList[rici[0]][rici[1]] = '$'  # 將當前位置標記為已探索
        manual_t.forward(cell_size)  # 向前移動
        print('00')
    elif point == '$':  # 已探索
        manual_t.color(road_color)  # 繪製和通道相同顏色的線,達到擦除痕跡的效果
        mazeList[rici[0] + dr][rici[1] - dc] = '0'  # 將當前位置的前一個點設定為未探索(目的是取消標記)
        manual_t.forward(road_color)  # 向前移動
        manual_t.color('red')
    elif point == 'E':  # 出口
        win_tip()
 
 
def up_move():  # 朝上
    manual_t.setheading(90)  # 設定海龜朝向
    manual_move(direction[2])  # 手動探索並移動
 
 
def down_move():  # 朝下
    manual_t.setheading(270)  # 設定海龜朝向
    manual_move(direction[3])  # 手動探索並移動
 
 
def left_move():  # 朝左
    manual_t.setheading(180)  # 設定海龜朝向
    manual_move(direction[1])  # 手動探索並移動
 
 
def right_move():  # 朝右
    manual_t.setheading(0)  # 設定海龜朝向
    manual_move(direction[0])  # 手動探索並移動
 
 
def manual_path():
    """
    功能:手動走迷宮
    :return:
    """
    manual_t.clear()  # 清除繪圖
    auto_t.ht()  # 隱藏海龜
    auto_t.clear()  # 清除繪圖
    global mazeList  # 定義全域性變數
    mazeList = get_map(txt_path)  # 重新讀取地圖資料
    # print(area_sign['entry_i'][0],area_sign['entry_i'][1])
    c_move_to(manual_t, itoc(area_sign['entry_i']))  # 移動到入口位置
    manual_t.st()  # 顯示手動走迷宮所用的海龜遊標
    manual_t.width(3)  # 設定畫筆粗細為3畫素
    manual_t.color('red')  # 設定畫筆為紅色
    manual_t.getscreen().listen()  # 讓海龜螢幕(TurtleScreen)獲得焦點
    manual_t.getscreen().onkeyrelease(up_move, 'Up')  # 按下向上方向鍵
    manual_t.getscreen().onkeyrelease(down_move, 'Down')  # 按下向下方向鍵
    manual_t.getscreen().onkeyrelease(left_move, 'Left')  # 按下向左方向鍵
    manual_t.getscreen().onkeyrelease(right_move, 'Right')  # 按下向右方向鍵
 
 
def auto_path():
    """
    功能:檢視答案(自動走迷宮)
    :return:
    """
    global mazeList  # 定義全域性變數
    mazeList = get_map(txt_path)  # 重新讀取地圖資料
    manual_t.ht()  # 隱藏海龜
    manual_t.clear()  # 清除繪圖
    auto_t.clear()  # 清除繪圖
    auto_t.pensize(5)  # 設定畫筆粗細
    auto_t.speed(0)  # 繪圖速度
    auto_t.ht()  # 隱藏海龜遊標
    find(mazeList)  # 開始探索
 
 
def find(mazeList):
    """
    功能:開始探索
    :param mazeList: 地圖列表
    :return:
    """
    auto_t.clear()  # 清空幫助
    start_r, start_c = 0, 0
    for ri in range(R):
        for ci in range(C):
            item = mazeList[ri][ci]
            if item == "S":
                start_r, start_c = ri, ci
    auto_t.penup()  # 擡筆
    draw_path(start_c, start_r)
    find_next(mazeList, start_c, start_r)
 
 
def find_next(mlist, ci, ri):
    """
    功能:遞迴搜尋判斷是否為通路
    :param mlist: 地圖列表
    :param ci: 列索引
    :param ri: 行索引
    :return: 布林值,表示是否為通路
    """
    if mlist[ri][ci] == "E":
        imoveto(ci, ri)  # 移動到出口
        return True
    if not (0 <= ci < C and 0 <= ri < R):  # 判斷位置是否不合法
        return False
    if mlist[ri][ci] in ['1', '$']:  # 判斷是否為牆或者已探索過的
        return False
    mlist[ri][ci] = "$"  # 標記已探索過
    for d in direction:  # 嘗試從不同方向探索是否為通路,如果發現一條通路,則不再繼續探索
        dc, dr = d  # # 將索引變化規則的值分別賦值給dc和dr,其中dc為x軸方向,dr為y軸方向
        found = find_next(mlist, ci + dc, ri + dr)  # 遞迴呼叫
        if found:  # 如果是通路則繪製線路
            draw_path(ci, ri)  # 繪製線路
            return True  # 返回True,不再探索
    return False  # 當所有方向都不通時,返回False
 
 
def draw_path(ci, ri, color="green"):  # 自動繪製用
    """
    功能:根據索引位置移動海龜(畫線)
    :param ci: 列索引
    :param ri: 行索引
    :param color: 畫筆顏色
    :return:
    """
    auto_t.st()  # 顯示海龜遊標
    cx, cy = itoc((ci, ri))  # 將索引位置轉換為座標位置
    auto_t.color(color)
    auto_t.goto(cx, cy)
 
 
def level_init():
    """
    功能:關卡初始化
        遊戲規則:
        按下F2鍵開始手動走迷宮;按下F1鍵檢視答案
        按下↑↓←→方向鍵控制小海龜移動,闖關成功後,按Enter進入下一關
    :return:
    """
    manual_t.clear()  # 清除繪圖
    auto_t.clear()  # 清除繪圖
    turtle.clear()  # 清除繪圖
    global txt_path, level, mazeList, R, C  # 定義全域性變數
    if level == 1:  # 第一關的地圖檔案和背景
        txt_path = "map/map1.txt"
        levelbg = 'image/level1.png'
    elif level == 2:  # 第二關的地圖檔案和背景
        txt_path = "map/map2.txt"
        levelbg = 'image/level2.png'
    elif level == 3:  # 第三關的地圖檔案和背景
        txt_path = "map/map3.txt"
        levelbg = 'image/level3.png'
    else:
        turtle.bye()  # 退出程式
        return
    mazeList = get_map(txt_path)  # 獲取地圖資料
    R, C = len(mazeList), len(mazeList[0])
    turtle.setup(width=C * cell_size + 50, height=R * cell_size + 100)  # 根據地圖調整視窗尺寸
    turtle.bgpic(levelbg)  # 設定背景圖片
 
    '''  
    # 如果想要手動繪製關卡數,可以使用下面的兩行程式碼
    cmoveto(turtle, (1 * cellsize - C * cellsize / 2, R * cellsize / 2+10))
    turtle.write('關卡:'+str(int(level)), font=('宋體', 16, 'normal'))    
    '''
    turtle.ht()  # 隱藏海龜遊標
    draw_map(mazeList)  # 繪製地圖

四、效果圖

1.執行程式碼

2.關卡一

這是按住了F1所以才出現路線圖的哦!

3.關卡二

這是按住了F2所以是自己手動在闖關哈!

4.關卡三

以上就是Python+Turtle製作海龜迷宮小遊戲的詳細內容,更多關於Python Turtle迷宮遊戲的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com