Update:1 ==> 27/12/98
توی این آموزش میخوام که بهتون روش ساختن یه برنامه برای پیدا کردن جواب های بازی آمیرزا و بازی های مشابه رو بهتون یاد بدم . کار سختی نیست واقعا و با یک ماه تجربه ی برنامه نویسی پایتون هم میشه (یکماه من البته ==> روزی 5 - 6 ساعت تمرین) .
تذکرات :
اول : متاسفانه این مقاله رو فقط بر اساس سیستم عامل ویندوز مینویسم چون اگه بخوام لینوکس یا مک رو هم اضافه کنم خیلی خیلی زیاد میشه و هم خودم و هم شما سر در گم میشیم، پس بهتره کسایی که سیستم عامل های دیگه ای دارن ، معادل هر نرم افزار یا دستور در powershell و cmd رو خودشون پیدا کنن ، البته خیلی سخت نیست و با یه سرچ خیلی ساده توی گوگل پیدا میکنین .
دوم : بعضی از قسمت ها رو مجبورم لینک های آموزشی رو قرار بدم چون برای یادگیری حرفه ای و کاملشون نیاز به یه مقاله ی جدا و خیلی زیاده . البته سعی کردم بهترین ها رو براتون پیدا کنم که مجبور به سرچ کردن نباشین و بعضی رو هم یه مختصر براتون نوشتم.
سوم : اگه کاربر حرفه ای در برنامه نویسی و پایتون هستین یا اینکه حال و حوصله خوندن این همه ندارین و یهو میخواین برین سراغ کد ها ، برین به این لینک یا اینکه کل نصبیجات و آموزشی ها رو رد کنین و برین به قسمت اصلی .
چهارم : همه فایل هایی که توی مقاله استفاده میشن توی لینک بالا هستن .
خب یه عالمه چیز میز هست که باید قبل از شروع به کار نصبشون کنین ، اگه جایگزین بعضی برنامه ها رو دارین ، اشکالی نداره و خیلی مهم نیست(اگه از قبل نصبشون کردین مستقیم برین به قسمت اول)
از این لینک آخرین یا هر نسخه ای از پایتون(البته نسخه تون حتما با 3 شوع بشه) که دوست دارین رو دانلود کنین .
بعد از دانلود وقتی فایل رو باز میکنین تیک add to path رو بزنین .
این گزینه یعنی add to path باعث میشه که از هرجایی از هارد کامپیوترمون که بودیم بتونیم پایتون رو فقط با python صداش کنیم .
یکی از بهترین IDE ها برای پایتون محسوب میشه و یه عالمه ابزار خوب بهتون میده البته میتونین نسخه ی رایگان(community) رو از سایت سازنده یا نسخه کامل رو از این سایت دانلود و نصب کنین .
اگه نمیتونین نرم افزار بالا رو نصب کنین (جا ندارین ، کامپیوترتون نمیکشه یا هر دلیل دیگه) این هم میتونه یه نرم افزار خوب باشه ، از این لینک دانلود کنین .
با pyinstaller میتونیم کد های پایتونمون رو که با پسوند py ذخیره شدن به پسوند exe تبدیل کنیم تا توی بقیه ی کامپیوتر هایی که حتی پایتون رو هم نصب ندارن اجرا بشه .
برای نصب cmd یا powershell رو در حالت administator باز کنین و بنویسین :
pip install PyInstaller
در واقع Qt به ما کمک میکنه که یک GUI یا رابط کاربری گرافیکی برای برنامه هامون بسازیم و pyqt مخصوصا برای پایتون نوشته شده . در همون cmd یا powershell بنویسین :
Pip install PyQt5 Pip install pytq5-tools
اگه تازه وارد برنامه نویسی شدین یا اینکه با زبان پایتون هنوز آشنایی کامل ندارین ، این قسمت رو بخونین ولاغیر از قسمت پایین رد بشین.
انواع داده یا شی در پایتون : قسمت یک - قسمت دو
دستورات شرطی : با if ، else و elif (معادل else if در بقیه زبان ها) نوشته میشن و برای کد هامون انواع و اقسام شروط رو میزارن برای آشنایی کامل به این لینک مراجعه کنین .
تابع: به بلاکی از دستورات گفته میشه که برای اجرا شدنشون باید اونا رو فراخوانی کرد البته میشه بیشتر از یک بار هم اینکار رو انجام داد. تابع میتونه هنگام فراخوانی مقادیری دریافت کنه و اگه نیاز باشه مقدار یا مقادیری رو هم به عنوان نتیجه برگردونه . آموزش هم اینجاست.
کلاس : یکی از مفهومی ترین قسمت یادگیری زبان های برنامه نویسی هست و همین باعث میشه که فقط یه مثال براتون بزنم : یه کارخونه ی بزرگ خودروسازی رو یک کلاس در نظر بگیرین ، که هر قسمت این کارخونه برای یه کاری هست ، یه قسمت برای سیستم چرخ ها ، سیستم سوخت و ... (البته هر کلاس میتونه کلاس های کوچکتری هم داخل خودش داشته باشه) . هر کلاسی از اشیایی که داخل قرار داره به موجودیت پیدا میکنه ، پس با ایجاد کردن هر نمونه از کلاس کارخونه ، یک شی یا موجودیت جدید ایجاد میهش که مثل کارخونه اصلی ، تمام ویژگی ها و اشیای داخلش رو داره . شی یا اشیا رو خودرو ها در نظر بگیرید . ==> برای بهتر فهمیدن این غول بهتره به این لینک مراجعه کنین .
ارث بری : از ویژگی های شی گراییه و باعث میشه که یک کلاس از یک کلاس دیگه بتونه استفاده بکنه بدون اینکه مجبور باشیم همه ی کد ها رو بهش اضافه کنیم . (لینک بالا این رو هم نوشته)
کتابخونه : مجموعه کدهایی که برای انجام کاری مشخص، از قبل نوشته شدن و در یک جایی ذخیره شدن. برای استفاده از اون ها، فقط باید اون ها رو در درون کدهای خود فراخوانی کنیم.
دیزاینر PyQt5 : در واقع این یه نرم افزار گرافیکی برای استفاده از pyqt بدون اینکه مجبور باشیم یه عالمه کد بزنیم هست . آدرس محلی که پایتون رو نصب کردین رو باز کنین و به این پوشه وارد بشین و designer.exe رو باز کنین:
"where you installed python" ==> \Lib\site-packages\pyqt5_tools\Qt\bin
قراره برنامه مون چند حرف گرفته و تمامی حالت های ممکن رو باهاشون کلمه بسازه و بره و توی دیتابیس دیشکنری کلمات فارسی که بهش میدیم بگرده و معنی دار ها رو جدا کنه و در آخر بهمون نشونشون بده .
باید معذرت خواهی کنم که چرا کد ها رو به صورت عکس قرار میدم ، خب چون وقتی میخوام کد ها رو توی ویرگول کپی کنم به شدت بد میشن و مجبور برای اینکه فاصله ها و تب ها مشخص باشه ، عکس بگیرم ولی شما میتونین از لینکی که اول گفتم کد ها رو دانلود کنین و استفاده کنین .
اول از همه پروژه ای توی IDE خودتون بسازین ، زبان پایتون رو انتخاب کنین ، فایلی به نام Amirza.py بسازین و شروع کنین به برنامه نویسی در اون فایل .
خط 1 تا 11 : اول از همه باید کتابخونه هایی که توی برنامه قراره ازشون استفاده کنیم رو ایمپورت کنیم ، پس طبق خط یک و دو واردشون میکنیم (بعدا توضیح میدم اینا چی ان)
توی خط 5 کلاس برنامه مون رو تعریف میکنیم ، بعد هم تابع اصلی برنامه مون . این تابع قراره اول از همه یک text بگیره ، خط فاصله رو تبدیل به کاراکتر فاصله ، دوفاصله رو تبدیل به یک فاصله کنه و بعد بعد اون رو تبدیل به لیست کنه (با split بر اساس کاراکتر فاصله اون رو به لیست تبدیل کنه) ، البته شما میتونین قسمت تبدیل خط فاصله به کاراکتر فاصله رو ننویسین و بجاش ، و با split رشته رو با کاراکتر - از هم جدا کنین .
شاید جای سوال باشه که اون char و i ماله چیه ؟ خب باید بگم که char مقدار اولیه برای تعداد حروفی که میخوایم در برنامه استفاده باشه ، معمولا در بازی آمیرزا حداقل از 3 حرف در کلمه استفاده میشه . اون i هم شمارنده ست که بعدا میگم ماله چیه .
لیستی که در خط 11 به نام lister دارین میبین قراره تمام حالت های ممکن رو برامون ذخیره کنه ، حتما میگین حالت های ممکن برای چی ؟
ببینین مثلا برای ساخت کلمه با حروف (گ خ ل ا م ن) ، میتونیم صداها جور حروف رو بقل هم بچینیم و باهاشون کلمه بسازیم ، از سه حرفی گرفته تا شش حرفی ==> پس این لیست میاد و تمام حالت های سه حرفی رو در اولین عضو ذخیره میکنه ، تمامی حالت های چهار حرفی رو در عضو دوم و همینطور تا آخر ، اوکی ؟ پس به طور پیش فرض عضو هاش رو میزاریم default چون نمیدونیم که چند حرف کاربر به برنامه میده (البته روش های خلاقه و بهتری هم برای اینکار وجود داره ، خوبه که فکر کنین و خودتون کشفشون کنین)
خط 13 تا 16 : اولا از همه باید در مورد permutations توضیح بدم ، این تابع درونی ، یک لیست و یک عدد میتونه بگیره و بر اساس اون عدد ، تمام حالت هایی ممکن رو با اعضای لیست بسازه ، مثلا :
میخوایم با حروف a b c d تمامی حالت هایی که میتونن کنار همدیگه قرار بگیرن رو بسازیم . پس :
باید بدونین که باید permutations رو به لیست تبدیل کنین که قابل پرینت باشه.
خروجی که بهمون میده خیلی زیاده ، این یه بخشی ازش :
حالا اگه بهش یه عدد هم اضافه کنیم چی میشه ؟
متوجه شدین؟ دفعه قبل با هر چهارتاشون حالت های ممکن رو میساخت ، الان با دو تا میسازه .
بریم سراغ کد خودمون ، خط 13 تا 16 میگه ، تا وقتی که char کوچکتر مساوی تعداد کاراکتر ها توی textlist هست ، بیا و تمامی حالت های ممکن رو با textlist بساز و بزارشون توی یک عضو از lister ، یکبار چک کنیم :
مثال : حروف "ا ب ت خ ن و" رو توی لیست بهش میدیم ، اون میاد و اول از همه که char برابر 3 هست ، تمامی حالت های سه حرفی ها رو میسازه و توی عضو اول(ایندکس لیست ها از صفر شروع میشن پس [0]lister) قرار میده . بعد یکی به char و یکی به i اضافه میکنه تا دفعه ی بعد چهار حرفی ها (char=4) رو توی عضو دوم (i=1) قرار بده و ...
الان اگه lister رو پرینت کنین ، میبینین که که چندین لیست توی یک لیست قاتی پاتی شدن و هیچی ازش سر در نمیارین :)))) خب اشکالی نداره ، بعدا درست میشه .
ادامه :
توی این قسمت از کدهامون ، یک لیست جدید تعریف میکنیم و یک دستور for تا مقادیر default رو از lister قدیمی حذف کنه و بقیه رو بریزه توی lister_new (از خط 18 تا 22)
حالا یک متغییر تعریف میکنیم تا مقدار نهایی رو برامون ذخیره کنه ، اینکه چرا از self اولش استفاده میکنیم ، دلیلش اینه که شاید بعدا بخوایم این مقدار رو توی فایل(کلاس و ...) دیگه استفاده کنیم .
خط 26 تا 28 : این قسمت ماله اینه که بگیم هر کدوم از قسمت ها(i) رو از lister جدا کن (مثلا : سه حرفی ها ، چهار حرفی ها و ...) ، بعد بیا و هر مقدار(k) رو از قسمت ها جدا کن و حروفش رو به هم دیگه بچسبون و در آخر بریزشون توی self.ultimList
تابع join برای تبدیل لیست یا تاپل به رشته استفاده میشه ، اول کاراکتری رو میگیره که باید بین عضو های لیست یا تاپل باشه ، بعد خود لیست رو ؛ البته میشه کاراکتر رو وارد نکرد که به هم دیگه بچسبن.
حالا ممکنه که حروف تکراری در اول برنامه وارد کرده باشیم و برای همین کلمه های تکراری هم ساخته شده باشن (میگین نه ؟ حروف رو بدین "ب ا ب ا" تا ببینین که چهار تا "بابا" براتون میاره :/) ولی اگه خط 30 رو اضافه کنیم ، دیگه این مشکل پیش نمیاد .
تابع اول و دوم مربوط به بخش sqlite هست(همون که اول از همه ایمپورت کردیم) و دقیقا از داکیومنت sqlite کپی کردم ، شما هم میتونین این کارو انجام بدین فقط باید یه توضیح در مورد خط 39 بدم :
اینکه با هر نرم افزاری که دوست دارین مثلا navicad فایل Moin.db رو باز کنین:
میبینین که mdx اسم جدول و entry اسم ستونه ، پس اگه از دیتابیس دیگه ای استفاده میکنین باید اونا رو وارد کنین .
خط 42 تا 44 : این قسمت میاد و یک متغییر self.diclist میسازه و برای هر ردیف مقدار بدون پرانتز و ویرگول رو واردش میکنه (اگه متوجه نشدین یه بار بدون [row[0 وارد کنین و diclist رو پرینت کنین تا ببینین چه شکلی میشه .
خط 49 و 50 که مشخصه ، یه ابجکت از کلاس میسازیم و مقدار دهی هم میکنیم ،
خط 52 و 53 هم مربوط به دیتابیس مون هست ، فقط حواستون باشه اگه دیتابیس دیگه ای دارین اسم اون رو وارد کنین.
خط 55 تا آخر : یک لیست جدید میسازیم که جواب رو بهمون نشون بده ، یعنی جواب بدون تکرار ، از دیتابیس گذشته ، سر و سامون گرفته و ... ، پس میگیم که بیا و به ازای هر مقدار ultimList_undup که توی diclist هم بوده ، به لیست answers اضافه کن .
در آخر هم که answers رو پرینت میکنیم.
البته میتونین به جای اینکه حروف رو مستقیما بهش بدین ، حروف رو با ()input از کاربر بگیرین .
قسمت دوم و سوم فقط برای تبدیل ظاهر ترمینال به یه ظاهر گرافیکی هست و اگه ظاهر گرافیکی نمیخواین میتونین از این دو قسمت عبور کنین.
خب Qt designer رو باز کنین(توی آموزشی گفتم کجاست):
یک فایل جدید باز کنین . اندازه و رنگ و صد جور چیز دیگه توی قسمت سمت راستتون میتونین ببنین و تنظیمشون کنین .
از قسمت چپ هم میتونین انواع ویجت ها رو وارد برنامه تون کنین .
این مرحله رو به خودتون میسپارم که هم دستتون راه بیفته ، هم دیگه خیلی آسونه همه چی واضحه دیگه .
فقط چند تا چیز رو رعایت کنین که برای برنامه تون حتما سه تا checkbox ، دو pushbutton ، یک textbrowser ، یک lineEdit و حداقل یک label برای نشون دادن ارور در نظر بگیرید . اگه دوست دارین یک progressbar هم اضافه کنین تا بفهمیم برنامه کجای کاره. (میتونین اضافه نکنین و توی قسمت بعدی هم کد هاش رو ننویسین)
اگه توی این مرحله موفق بشین باید یه همچین چیزی داشته باشین :
الان یک پوشه(دایرکتوری) جدید به اسم ProgramFile توی پوشه ای که برنامه ی اصلیتون(پروژتون) وجود داره بسازین و فایلتون رو اونجا save کنین .
الان میخوایم این فایل با پسوند ui رو به کد های پایتون تبدیل کنیم .
خیلی ساده با powershell به دایرکتوری ProgramFile برین و بزنید :
Pyuic5 -x -o Amirza_ui.py Amirza_ui.ui یا python -m PyQt5.uic.pyuic -x Amirza_ui.ui -o Amirza_ui.py
اول اسم فایلی رو که میخواین بهش تبدیل بشه و دوم هم اسم فایل اصلی با پسوند ui رو وارد کنین . الان یدونه Amirza_ui.py برای ما ساخته شد که بتونیم ازش استفاده کنیم .
تمام ، الان فقط کافیه بریم سراغ قسمت بعدی تا برنامه ها رو سر هم کنیم .
این قسمت با قسمت اول یکم فرق میکنه چون اولا باید یه بخشی از کد ها قبل رو تغییر بدیم (که بهتون میگم) دوما اینکه کارکرد برنامه به یه شکل دیگه ست و باید یه جور دیگه برنامه مون رو تنظیم کنیم .
خب روش کار اینه که کاربر توی lineEdit چند حرف رو با کاراکتر فاصله یا - وارد میکنه ، با انتخاب یک یا چند تا از checkbox ها میگه که کلمات چند حرفی میخواد ،با زدن go این حروف وارد برنامه ای که توی قسمت اول نوشتیم میشن و جوابشون دوباره برمیگرده ،بعدش تعداد جواب ها وارد progresbar میشن و بعد هر بار که کلمه توی database چک میشن ، progresbar پیشرفت میکنه . اگه کاربر وسط کار برنامه cancel رو فشار بده برنامه قطع بشه ، چند تا شورتکات اضافه میشه و چند تا شرایط خاص هم مد نظر هست که ارور خودشون رو برگردونن .
اول از همه باید فایل py قبلی رو به پوشه ProgramFile که ساختیم انتقال بدیم ، و در پوشه ی اصلی یک فایل compiler.py بسازیم ، داخل دایرکتوری اصلی :
داخل ProgramFile :
اون فایل آیکون چیز خاصی نیست ، بعدا که خروجی exe خواستیم بگیریم ازش استفاده میکنیم .
خب یه بخش زیادی رو باید تغییر بدیم ، اگه برین توی سایت گیت ، فایل amirza.py فایلی هست که باید استفاده کنیم و فایل amirza_virgool.py فقط برای قسمت اوله .
تغییراتی که باید بدیم اینجا ها باید باشه :
متغییر جدید number برای دریافت عدد checkbox هست .
گفتیم سه تا checkbox میزاریم ، اولی برای سه حرفی ها (عددش رو هم سه میزاریم) ، دومی برای چهار حرفی ها (عدد 4) و آخری هم برای 5 و بیشتر (عدد 5) .
حالا اگه دو تا یا سه تا از checkbox ها انتخاب شده بودن باید چیکار کنیم ؟ یه راه اینه که عددشون رو با هم جمع کنیم و یه حالت جدید بنویسیم .
مثلا checkbox3 و checkbox4 با همدیگه انتخاب شدن ، پس جمعشون میشه 7 و number عدد هفت رو بهمون میده .
البته باید بهتون بگم که این گرفتن شماره checkbox و جمع کردن و ... توی فایل compiler قرار میدیم نه اینجا.
مثلا این یه نمونه از کد ، که میگه اگه number عدد 12 باشه ، یعنی همه ی checkbox ها انتخاب شدن و :
بقیه رو هم میسپارم به خودتون ، یکم خلاقیت به کار ببندین و انواع کد ها رو امتحان کنین ولی یه تقلب کوچولو :
بریم سراغ اصل کار .
اول از همه کتابخونه هایی که pyqt نیاز داره رو ایمپورت میکنیم بعد هم که Amirza و Amirza_ui رو .
خط 6 و 8 فقط برای اینه که مانیتورهای (high dpi (4k برنامه مون رو ساپورت کنن و کوچیک نشه ، مثل این:
تو قسمت بعدی ، کلاس اصلی برنامه رو تعریف میکنیم و از کلاس Ui_MainWindows که داخل Amirza_ui بود سابکلاس میگیریم .
خط 12به معنی اینه که هر چی در تابع اصلی بوده رو اینجا هم استفاده کن . خط 13 برای کلید cancel هست که اگه false باشه یعنی روش کلیک نشده و true یعنی روش کلیک شده .
خط 14 برای نگه داشتن همون number قسمت قبل هست .
خط 18 و 19 که برای اضافه کردن شورتکات برای کلید go هست ، یعنی وقتی Enter روی صفحه کلید فشرده شد ، همون کار انجام بده .
تابع number_adder_func برای اضافه کردن مقدار به number هست که بعدا ازش استفاده میکنیم
تابع checkbox_checker_func برای اینه که اول از همه انتخاب شدن هر کدوم از checkbox ها رو بررسی میکنه و بعد هر کدومش که انتخاب شده بود رو یه عدد میفرسته به تابع number_adder_func تا به عدد num اضافه کنه .
خط 38 : اگه هیچ کدوم از اون ها انتخاب نشده بودن ، قراره رنگ متن در ErrorLable رو قرمز کنه و پیام خطا نشون بده (که یعنی یکی از اون ها رو انتخاب کن ، همینجوری که نمیشه ...)
خط 42 : اگه حداقل یکی از اونها انتخاب شده بود ، برو به تابع بعدی .
این تابع قراره چک کنه که متنی که وارد شده خالی نباشه ، اگه خالی بود ، متن ارور رو نشون بده ولاغیر بره به تابع بعدی .
قبل از اینکه بریم سراغ تابع اصلی برنامه ، یه تابع دیگه هم اضافه میکنیم که چک کنه ببینه حتما ما داریم حروف فارسی وارد برنامه میکنیم یا یه زبان دیگه :
خط 64 : اگه اشتباه وارد کنیم ، کلید go رو غیرفعال میکنه .
این یکی کد مهم در برنامه مونه ، اگه این تیکه نباشه ، در حین اینکه داره این حلقه انجام میشه ، هیچکار دیگه ای نمیشه با برنامه انجام داد و هنگ میکنه ولی این باعث میشه که بازم بشه با برنامه کار کرد(مثلا cancel رو زد یا یه حرف دیگه وارد کرد)
ادامه:
وقتی go فشرده میشه ، خط 74 تا 87 که به شدت واضحن ، اجرا میشن ، ادامه :
خط 90، مقدار ماکزیمم (آخرین درجه) برای progressbar رو بر اساس تعداد جوابی که Amirza میده ، تنظیم میکنه .
تابع cancel که واضحه ، خط 96 هم که میگه وقتی cancel فشرده شد برو به تابع cancel .
خط 99: به ازای هر مقدار در ultimList_undup ، یکی به اندازه ی progressbar اضافه کن ، اگه اون مقدار در دیتابیس بود بیا و در answers اضافه کن .
خط 103 هم چک میکنه اگه cancel زده شده باشه ، دیگه حلقه رو ادامه نده و بزنه بیرون ازش .
خط 105: امتحان کن که خط 106 باز هم چک میکنه که کلمه ی تکراری توی لیستمون نباشه .
خط 107 : تابع join یک یا چند کرکتر رو با یک لیست اقدام میکنه و بین هر عضو لیست ، اون کاراکتر ها رو قرار میده .
خط 110 : اگه خطوط 106 تا 108 ناموفق بود ، ارور رو نشون بده و wrong رو هم بزار true (یعنی یه مشکل توی برنامه پیدا شد)
خط 114 : اگه مشکلی توی برنامه وجود نداشت (wrong == False) قسمت آخر یعنی finish رو نشون بده .
از 120 تا 122 و 130 تا 131 ماله خود Qt هست و بزارین سر جاش بمونه ،
خط 123 و 124 : هم واضحه
خط 126 : هر دفعه که lineEdit ادیت میشه (یه چیزی توش وارد میشه یا پاک میشه) ، کانکت میشه به اون تابع .
خط 127 : هر موقع هم که کلید go فشرده شد ، وصل شو به اون تابع .
تمام . اگه یکم گیج شدین اشکالی نداره ، دوباره بخونین ، حتما میفهمین .
مقاله های من :
پر بازدید ترین :
بقیه مقاله ها :
telegram : @bestmadi2
instagram : @bestmahdi2