Kahibaro
Discord Login Register

فهرست کارها (To-Do List)

طراحی پروژهٔ «فهرست کارها»

در این پروژه یک برنامهٔ خط فرمان (Command Line) می‌سازیم که به ما کمک کند کارهای روزانه‌مان را مدیریت کنیم. ایده این است:

در این پروژه از مهارت‌هایی استفاده می‌کنیم که در فصل‌های قبلی یاد گرفته‌اید:

در این فصل خودِ پروژه را گام به گام می‌سازیم.


طرح کلی برنامه

قبل از کدنویسی، رفتار کلی برنامه را مشخص می‌کنیم.

کاربر وقتی برنامه را اجرا می‌کند، یک منوی ساده می‌بیند:

  1. نمایش فهرست کارها
  2. افزودن کار جدید
  3. علامت‌زدن کار به عنوان انجام‌شده
  4. حذف یک کار
  5. خروج از برنامه

هر کار می‌تواند این اطلاعات را داشته باشد:

برای نگه‌داشتن کارها از یک لیست استفاده می‌کنیم که هر عضو آن یک دیکشنری است؛ مثلاً:

python
{"title": "مطالعهٔ ۳۰ دقیقه پایتون", "done": False}

پس ساختار کلی داده‌ها چیزی شبیه این است:

python
tasks = [
    {"title": "مطالعهٔ ۳۰ دقیقه پایتون", "done": False},
    {"title": "پیاده‌روی", "done": True},
]

پیاده‌سازی نسخهٔ ساده (بدون فایل)

اول یک نسخهٔ درون‌حافظه‌ای می‌سازیم که فقط تا وقتی برنامه باز است کار می‌کند. بعد آن را با فایل ترکیب می‌کنیم.

۱. ساخت منوی اصلی

def show_menu():
    print("========== فهرست کارها ==========")
    print("1. نمایش فهرست کارها")
    print("2. افزودن کار جدید")
    print("3. علامت‌زدن کار به عنوان انجام‌شده")
    print("4. حذف یک کار")
    print("5. خروج")
    print("================================")

و حلقهٔ اصلی برنامه:

def main():
    tasks = []  # فهرست کارها در حافظه
    while True:
        show_menu()
        choice = input("یک گزینه را انتخاب کنید: ")
        if choice == "1":
            show_tasks(tasks)
        elif choice == "2":
            add_task(tasks)
        elif choice == "3":
            mark_task_done(tasks)
        elif choice == "4":
            delete_task(tasks)
        elif choice == "5":
            print("خداحافظ!")
            break
        else:
            print("گزینه نامعتبر است. دوباره تلاش کنید.")
if __name__ == "__main__":
    main()

در این مرحله فقط منو و اسکلت برنامه را داریم. حالا توابع مربوط به مدیریت کارها را می‌نویسیم.


۲. نمایش فهرست کارها

می‌خواهیم فهرست را با شماره و وضعیت نمایش دهیم، مثلاً:

def show_tasks(tasks):
    if not tasks:
        print("هیچ کاری در فهرست نیست.")
        return
    print("\nفهرست کارها:")
    for index, task in enumerate(tasks, start=1):
        status = "[x]" if task["done"] else "[ ]"
        print(f"{status} {index}. {task['title']}")
    print()

نکته‌ها:

۳. افزودن کار جدید

کاربر متن کار را وارد می‌کند و ما آن را به لیست اضافه می‌کنیم:

def add_task(tasks):
    title = input("عنوان کار جدید را وارد کنید: ").strip()
    if not title:
        print("عنوان کار نمی‌تواند خالی باشد.")
        return
    task = {"title": title, "done": False}
    tasks.append(task)
    print("کار جدید اضافه شد.")

چند نکته:

۴. علامت‌زدن کار به عنوان انجام‌شده

ابتدا فهرست را نشان می‌دهیم، سپس از کاربر می‌خواهیم شمارهٔ کار را وارد کند:

def mark_task_done(tasks):
    if not tasks:
        print("هیچ کاری برای انجام‌دادن وجود ندارد.")
        return
    show_tasks(tasks)
    choice = input("شمارهٔ کاری که انجام شده را وارد کنید: ")
    if not choice.isdigit():
        print("باید یک عدد وارد کنید.")
        return
    index = int(choice) - 1  # چون شمارش ما از 1 است ولی اندیس لیست از 0
    if 0 <= index < len(tasks):
        tasks[index]["done"] = True
        print("کار به عنوان انجام‌شده علامت خورد.")
    else:
        print("شمارهٔ وارد شده معتبر نیست.")

اینجا:

۵. حذف یک کار از فهرست

مشابه علامت‌زدن، اما این بار کار را حذف می‌کنیم:

def delete_task(tasks):
    if not tasks:
        print("هیچ کاری برای حذف وجود ندارد.")
        return
    show_tasks(tasks)
    choice = input("شمارهٔ کاری که می‌خواهید حذف کنید را وارد کنید: ")
    if not choice.isdigit():
        print("باید یک عدد وارد کنید.")
        return
    index = int(choice) - 1
    if 0 <= index < len(tasks):
        removed = tasks.pop(index)
        print(f"کار «{removed['title']}» حذف شد.")
    else:
        print("شمارهٔ وارد شده معتبر نیست.")

تابع pop عنصر را از لیست برمی‌دارد و خودش را برمی‌گرداند تا بتوانیم عنوان آن را چاپ کنیم.


افزودن ذخیره‌سازی در فایل

نسخه‌ای که تا الان ساختیم، بعد از بستن برنامه همهٔ کارها را از دست می‌دهد. می‌خواهیم کارها در فایلی مثل tasks.txt ذخیره شوند تا دفعهٔ بعد هم در دسترس باشند.

اینجا یک روش ساده را استفاده می‌کنیم:

مثال محتویات فایل:

text
0;مطالعهٔ ۳۰ دقیقه پایتون
1;پیاده‌روی

۱. بارگذاری کارها از فایل

وقتی برنامه شروع می‌شود، تلاش می‌کنیم فایل را بخوانیم. اگر موجود نبود، از یک لیست خالی شروع می‌کنیم.

FILENAME = "tasks.txt"
def load_tasks():
    tasks = []
    try:
        with open(FILENAME, "r", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue  # خط خالی را رد کن
                status_str, title = line.split(";", 1)
                done = True if status_str == "1" else False
                tasks.append({"title": title, "done": done})
    except FileNotFoundError:
        # اگر فایل وجود نداشت، فهرست خالی برمی‌گردانیم
        pass
    return tasks

نکته‌ها:

۲. ذخیره‌کردن کارها در فایل

هر بار که تغییری در فهرست می‌دهیم (افزودن، حذف، تغییر وضعیت)، می‌توانیم کل فهرست را دوباره در فایل بنویسیم.

def save_tasks(tasks):
    with open(FILENAME, "w", encoding="utf-8") as f:
        for task in tasks:
            status_str = "1" if task["done"] else "0"
            line = f"{status_str};{task['title']}\n"
            f.write(line)

اینجا:

۳. اتصال بارگذاری و ذخیره به برنامهٔ اصلی

حالا باید:

def main():
    tasks = load_tasks()  # بارگذاری از فایل
    while True:
        show_menu()
        choice = input("یک گزینه را انتخاب کنید: ")
        if choice == "1":
            show_tasks(tasks)
        elif choice == "2":
            add_task(tasks)
            save_tasks(tasks)
        elif choice == "3":
            mark_task_done(tasks)
            save_tasks(tasks)
        elif choice == "4":
            delete_task(tasks)
            save_tasks(tasks)
        elif choice == "5":
            print("خداحافظ!")
            break
        else:
            print("گزینه نامعتبر است. دوباره تلاش کنید.")

به این شکل، هر تغییری بلافاصله در فایل ذخیره می‌شود و اگر برنامه قطع شود، اطلاعات از بین نمی‌رود.


بهبودهای اختیاری

اگر دوست دارید برنامه را کمی حرفه‌ای‌تر کنید، می‌توانید چند ویژگی اضافه کنید.

۱. فیلتر کردن کارها (فقط انجام‌نشده‌ها یا فقط انجام‌شده‌ها)

مثلاً زیرمنو برای نمایش:

ایدهٔ ساده:

def show_tasks_filtered(tasks, only_done=None):
    filtered = []
    for task in tasks:
        if only_done is None:
            filtered.append(task)
        elif only_done and task["done"]:
            filtered.append(task)
        elif (only_done is False) and (not task["done"]):
            filtered.append(task)
    if not filtered:
        print("کاری برای نمایش وجود ندارد.")
        return
    for index, task in enumerate(filtered, start=1):
        status = "[x]" if task["done"] else "[ ]"
        print(f"{status} {index}. {task['title']}")

و در منو گزینه‌های جدید برای این نمایش‌ها قرار دهید.

۲. ویرایش عنوان یک کار

امکانی برای تغییر متن یک کار:

def edit_task(tasks):
    if not tasks:
        print("هیچ کاری برای ویرایش وجود ندارد.")
        return
    show_tasks(tasks)
    choice = input("شمارهٔ کار برای ویرایش را وارد کنید: ")
    if not choice.isdigit():
        print("باید یک عدد وارد کنید.")
        return
    index = int(choice) - 1
    if 0 <= index < len(tasks):
        new_title = input("عنوان جدید را وارد کنید: ").strip()
        if not new_title:
            print("عنوان نمی‌تواند خالی باشد.")
            return
        tasks[index]["title"] = new_title
        print("کار ویرایش شد.")
    else:
        print("شمارهٔ وارد شده معتبر نیست.")

بعد از ویرایش، فراموش نکنید save_tasks(tasks) را صدا بزنید.


جمع‌بندی پروژهٔ فهرست کارها

در این پروژه:

این پروژه، نمونه‌ای کوچک اما واقعی از یک برنامهٔ کاربردی است. می‌توانید این برنامه را مطابق نیاز خود گسترش دهید؛ برای مثال:

ایدهٔ اصلی این فصل این است که ببینید با مفاهیم ساده‌ای که تا اینجا یاد گرفته‌اید، می‌توانید یک ابزار مفید واقعی برای خودتان بسازید.

Views: 6

Comments

Please login to add a comment.

Don't have an account? Register now!