برنامه نویسی: پیداکردن جواب های بازی آمیرزا با پایتون3 (و PyQt5)

Amirza hacker هکر آمیرزاUpdate:1 ==> 27/12/98سلام خدمت دوستان تازه واردِ برنامه نویسی ، تازه واردِ پایتون ، سنیور های برنامه نویسی و ... توی این آموزش میخوام که بهتون روش ساختن یه برنامه برای پیدا کردن جواب های بازی آمیرزا و بازی های مشابه رو بهتون یاد بدم . کار سختی نیست واقعا و با یک ماه تجربه ی برنامه نویسی پایتون هم میشه (یکماه من البته ==> روزی 5 - 6 ساعت تمرین) .تذکرات : اول : متاسفانه این مقاله رو فقط بر اساس سیستم عامل ویندوز مینویسم چون اگه بخوام لینوکس یا مک رو هم اضافه کنم خیلی خیلی زیاد میشه و هم خودم و هم شما سر در گم میشیم، پس بهتره کسایی که سیستم عامل های دیگه ای دارن ، معادل هر نرم افزار یا دستور در powershell و cmd رو خودشون پیدا کنن ، البته خیلی سخت نیست و با یه سرچ خیلی ساده توی گوگل پیدا میکنین . دوم : بعضی از قسمت ها رو مجبورم لینک های آموزشی رو قرار بدم چون برای یادگیری حرفه ای و کاملشون نیاز به یه مقاله ی جدا و خیلی زیاده . البته سعی کردم بهترین ها رو براتون پیدا کنم که مجبور به سرچ کردن نباشین و بعضی رو هم یه مختصر براتون نوشتم. سوم : اگه کاربر حرفه ای در برنامه نویسی و پایتون هستین یا اینکه حال و حوصله خوندن این همه ندارین و یهو میخواین برین سراغ کد ها ، برین به این لینک یا اینکه کل نصبیجات و آموزشی ها رو رد کنین و برین به قسمت اصلی .چهارم : همه فایل هایی که توی مقاله استفاده میشن توی لینک بالا هستن . https://github.com/bestmahdi2/AmirzaHacker https://vrgl.ir/DSpJJ نصبیجات:خب یه عالمه چیز میز هست که باید قبل از شروع به کار نصبشون کنین ، اگه جایگزین بعضی برنامه ها رو دارین ، اشکالی نداره و خیلی مهم نیست(اگه از قبل نصبشون کردین مستقیم برین به قسمت اول)نصب پایتون :از این لینک آخرین یا هر نسخه ای از پایتون(البته نسخه تون حتما با 3 شوع بشه) که دوست دارین رو دانلود کنین .بعد از دانلود وقتی فایل رو باز میکنین تیک add to path رو بزنین .add to pathاین گزینه یعنی add to path باعث میشه که از هرجایی از هارد کامپیوترمون که بودیم بتونیم پایتون رو فقط با python صداش کنیم .نصب pycharm :یکی از بهترین IDE ها برای پایتون محسوب میشه و یه عالمه ابزار خوب بهتون میده البته میتونین نسخه ی رایگان(community) رو از سایت سازنده یا نسخه کامل رو از این سایت دانلود و نصب کنین .نصب notepad++ :اگه نمیتونین نرم افزار بالا رو نصب کنین (جا ندارین ، کامپیوترتون نمیکشه یا هر دلیل دیگه) این هم میتونه یه نرم افزار خوب باشه ، از این لینک دانلود کنین .نصب pyinataller :با pyinstaller میتونیم کد های پایتونمون رو که با پسوند py ذخیره شدن به پسوند exe تبدیل کنیم تا توی بقیه ی کامپیوتر هایی که حتی پایتون رو هم نصب ندارن اجرا بشه .برای نصب cmd یا powershell رو در حالت administator باز کنین و بنویسین :pip install PyInstallerنصب PyQt5 , pyqttools :در واقع Qt به ما کمک میکنه که یک GUI یا رابط کاربری گرافیکی برای برنامه هامون بسازیم و pyqt مخصوصا برای پایتون نوشته شده . در همون cmd یا powershell بنویسین :Pip install PyQt5 Pip install pytq5-toolsاگه تازه وارد برنامه نویسی شدین یا اینکه با زبان پایتون هنوز آشنایی کامل ندارین ، این قسمت رو بخونین ولاغیر از قسمت پایین رد بشین.آموزشی برای خیلی مبتدی :انواع داده یا شی در پایتون : قسمت یک - قسمت دو دستورات شرطی : با if ، else و elif (معادل else if در بقیه زبان ها) نوشته میشن و برای کد هامون انواع و اقسام شروط رو میزارن برای آشنایی کامل به این لینک مراجعه کنین .تابع: به بلاکی از دستورات گفته میشه که برای اجرا شدنشون باید اونا رو فراخوانی کرد البته میشه بیشتر از یک بار هم اینکار رو انجام داد. تابع می‌تونه هنگام فراخوانی مقادیری دریافت کنه و اگه نیاز باشه مقدار یا مقادیری رو هم به عنوان نتیجه برگردونه . آموزش هم اینجاست.کلاس : یکی از مفهومی ترین قسمت یادگیری زبان های برنامه نویسی هست و همین باعث میشه که فقط یه مثال براتون بزنم : یه کارخونه ی بزرگ خودروسازی رو یک کلاس در نظر بگیرین ، که هر قسمت این کارخونه برای یه کاری هست ، یه قسمت برای سیستم چرخ ها ، سیستم سوخت و ... (البته هر کلاس میتونه کلاس های کوچکتری هم داخل خودش داشته باشه) . هر کلاسی از اشیایی که داخل قرار داره به موجودیت پیدا میکنه ، پس با ایجاد کردن هر نمونه از کلاس کارخونه ، یک شی یا موجودیت جدید ایجاد میهش که مثل کارخونه اصلی ، تمام ویژگی ها و اشیای داخلش رو داره . شی یا اشیا رو خودرو ها در نظر بگیرید . ==> برای بهتر فهمیدن این غول بهتره به این لینک مراجعه کنین .ارث بری : از ویژگی های شی گراییه و باعث میشه که یک کلاس از یک کلاس دیگه بتونه استفاده بکنه بدون اینکه مجبور باشیم همه ی کد ها رو بهش اضافه کنیم . (لینک بالا این رو هم نوشته)کتابخونه : مجموعه کدهایی که برای انجام کاری مشخص، از قبل نوشته شدن و در یک جایی ذخیره شدن. برای استفاده از اون ها، فقط باید اون ها رو در درون کدهای خود فراخوانی کنیم.دیزاینر PyQt5 : در واقع این یه نرم افزار گرافیکی برای استفاده از pyqt بدون اینکه مجبور باشیم یه عالمه کد بزنیم هست . آدرس محلی که پایتون رو نصب کردین رو باز کنین و به این پوشه وارد بشین و designer.exe رو باز کنین:&quotwhere you installed python&quot ==> \Lib\site-packages\pyqt5_tools\Qt\bin https://vrgl.ir/CWo9g روش کار برنامه:قراره برنامه مون چند حرف گرفته و تمامی حالت های ممکن رو باهاشون کلمه بسازه و بره و توی دیتابیس دیشکنری کلمات فارسی که بهش میدیم بگرده و معنی دار ها رو جدا کنه و در آخر بهمون نشونشون بده .خیلی خب دیگه مقدمه بسه و بریم سراغ کد ها.باید معذرت خواهی کنم که چرا کد ها رو به صورت عکس قرار میدم ، خب چون وقتی میخوام کد ها رو توی ویرگول کپی کنم به شدت بد میشن و مجبور برای اینکه فاصله ها و تب ها مشخص باشه ، عکس بگیرم ولی شما میتونین از لینکی که اول گفتم کد ها رو دانلود کنین و استفاده کنین .قسمت اول ، کد های پایتون :الف)ایمپورت کردن کتابخانه ها و تعریف کلاس و تابع amirzafunc :first stepاول از همه پروژه ای توی 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باید بدونین که باید permutations رو به لیست تبدیل کنین که قابل پرینت باشه.خروجی که بهمون میده خیلی زیاده ، این یه بخشی ازش :listحالا اگه بهش یه عدد هم اضافه کنیم چی میشه ؟ add a numberlistمتوجه شدین؟ دفعه قبل با هر چهارتاشون حالت های ممکن رو میساخت ، الان با دو تا میسازه .بریم سراغ کد خودمون ، خط 13 تا 16 میگه ، تا وقتی که char کوچکتر مساوی تعداد کاراکتر ها توی textlist هست ، بیا و تمامی حالت های ممکن رو با textlist بساز و بزارشون توی یک عضو از lister ، یکبار چک کنیم :مثال : حروف "ا ب ت خ ن و" رو توی لیست بهش میدیم ، اون میاد و اول از همه که char برابر 3 هست ، تمامی حالت های سه حرفی ها رو میسازه و توی عضو اول(ایندکس لیست ها از صفر شروع میشن پس [0]lister) قرار میده . بعد یکی به char و یکی به i اضافه میکنه تا دفعه ی بعد چهار حرفی ها (char=4) رو توی عضو دوم (i=1) قرار بده و ...الان اگه lister رو پرینت کنین ، میبینین که که چندین لیست توی یک لیست قاتی پاتی شدن و هیچی ازش سر در نمیارین :)))) خب اشکالی نداره ، بعدا درست میشه .ادامه :30 - 18توی این قسمت از کدهامون ، یک لیست جدید تعریف میکنیم و یک دستور for تا مقادیر default رو از lister قدیمی حذف کنه و بقیه رو بریزه توی lister_new (از خط 18 تا 22)حالا یک متغییر تعریف میکنیم تا مقدار نهایی رو برامون ذخیره کنه ، اینکه چرا از self اولش استفاده میکنیم ، دلیلش اینه که شاید بعدا بخوایم این مقدار رو توی فایل(کلاس و ...) دیگه استفاده کنیم .خط 26 تا 28 : این قسمت ماله اینه که بگیم هر کدوم از قسمت ها(i) رو از lister جدا کن (مثلا : سه حرفی ها ، چهار حرفی ها و ...) ، بعد بیا و هر مقدار(k) رو از قسمت ها جدا کن و حروفش رو به هم دیگه بچسبون و در آخر بریزشون توی self.ultimList تابع join برای تبدیل لیست یا تاپل به رشته استفاده میشه ، اول کاراکتری رو میگیره که باید بین عضو های لیست یا تاپل باشه ، بعد خود لیست رو ؛ البته میشه کاراکتر رو وارد نکرد که به هم دیگه بچسبن.حالا ممکنه که حروف تکراری در اول برنامه وارد کرده باشیم و برای همین کلمه های تکراری هم ساخته شده باشن (میگین نه ؟ حروف رو بدین "ب ا ب ا" تا ببینین که چهار تا "بابا" براتون میاره :/) ولی اگه خط 30 رو اضافه کنیم ، دیگه این مشکل پیش نمیاد .ب) ساختن کانکشن دیتابیس و ذخیره کردن کردن داده ها در diclist :44 - 32تابع اول و دوم مربوط به بخش sqlite هست(همون که اول از همه ایمپورت کردیم) و دقیقا از داکیومنت sqlite کپی کردم ، شما هم میتونین این کارو انجام بدین فقط باید یه توضیح در مورد خط 39 بدم :اینکه با هر نرم افزاری که دوست دارین مثلا navicad فایل Moin.db رو باز کنین:navicadمیبینین که mdx اسم جدول و entry اسم ستونه ، پس اگه از دیتابیس دیگه ای استفاده میکنین باید اونا رو وارد کنین .خط 42 تا 44 : این قسمت میاد و یک متغییر self.diclist میسازه و برای هر ردیف مقدار بدون پرانتز و ویرگول رو واردش میکنه (اگه متوجه نشدین یه بار بدون [row[0 وارد کنین و diclist رو پرینت کنین تا ببینین چه شکلی میشه .پ) اجرا :60 - 49خط 49 و 50 که مشخصه ، یه ابجکت از کلاس میسازیم و مقدار دهی هم میکنیم ، خط 52 و 53 هم مربوط به دیتابیس مون هست ، فقط حواستون باشه اگه دیتابیس دیگه ای دارین اسم اون رو وارد کنین.خط 55 تا آخر : یک لیست جدید میسازیم که جواب رو بهمون نشون بده ، یعنی جواب بدون تکرار ، از دیتابیس گذشته ، سر و سامون گرفته و ... ، پس میگیم که بیا و به ازای هر مقدار ultimList_undup که توی diclist هم بوده ، به لیست answers اضافه کن .در آخر هم که answers رو پرینت میکنیم.البته میتونین به جای اینکه حروف رو مستقیما بهش بدین ، حروف رو با ()input از کاربر بگیرین .قسمت دوم و سوم فقط برای تبدیل ظاهر ترمینال به یه ظاهر گرافیکی هست و اگه ظاهر گرافیکی نمیخواین میتونین از این دو قسمت عبور کنین.قسمت دوم ، فقط PyQt5 :خب Qt designer رو باز کنین(توی آموزشی گفتم کجاست):Qt designerیک فایل جدید باز کنین . اندازه و رنگ و صد جور چیز دیگه توی قسمت سمت راستتون میتونین ببنین و تنظیمشون کنین . از قسمت چپ هم میتونین انواع ویجت ها رو وارد برنامه تون کنین .این مرحله رو به خودتون میسپارم که هم دستتون راه بیفته ، هم دیگه خیلی آسونه همه چی واضحه دیگه .فقط چند تا چیز رو رعایت کنین که برای برنامه تون حتما سه تا checkbox ، دو pushbutton ، یک textbrowser ، یک lineEdit و حداقل یک label برای نشون دادن ارور در نظر بگیرید . اگه دوست دارین یک progressbar هم اضافه کنین تا بفهمیم برنامه کجای کاره. (میتونین اضافه نکنین و توی قسمت بعدی هم کد هاش رو ننویسین)اگه توی این مرحله موفق بشین باید یه همچین چیزی داشته باشین :amirza_ui.uiالان یک پوشه(دایرکتوری) جدید به اسم ProgramFile توی پوشه ای که برنامه ی اصلیتون(پروژتون) وجود داره بسازین و فایلتون رو اونجا save کنین .الان میخوایم این فایل با پسوند ui رو به کد های پایتون تبدیل کنیم .روش تبدیل ui به py :خیلی ساده با 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 بسازیم ، داخل دایرکتوری اصلی :Main directoryداخل ProgramFile :ProgramFile directoryاون فایل آیکون چیز خاصی نیست ، بعدا که خروجی exe خواستیم بگیریم ازش استفاده میکنیم .تغییرات قسمت اول :خب یه بخش زیادی رو باید تغییر بدیم ، اگه برین توی سایت گیت ، فایل amirza.py فایلی هست که باید استفاده کنیم و فایل amirza_virgool.py فقط برای قسمت اوله .تغییراتی که باید بدیم اینجا ها باید باشه :newمتغییر جدید number برای دریافت عدد checkbox هست .گفتیم سه تا checkbox میزاریم ، اولی برای سه حرفی ها (عددش رو هم سه میزاریم) ، دومی برای چهار حرفی ها (عدد 4) و آخری هم برای 5 و بیشتر (عدد 5) .حالا اگه دو تا یا سه تا از checkbox ها انتخاب شده بودن باید چیکار کنیم ؟ یه راه اینه که عددشون رو با هم جمع کنیم و یه حالت جدید بنویسیم .مثلا checkbox3 و checkbox4 با همدیگه انتخاب شدن ، پس جمعشون میشه 7 و number عدد هفت رو بهمون میده .البته باید بهتون بگم که این گرفتن شماره checkbox و جمع کردن و ... توی فایل compiler قرار میدیم نه اینجا.مثلا این یه نمونه از کد ، که میگه اگه number عدد 12 باشه ، یعنی همه ی checkbox ها انتخاب شدن و :if clausesبقیه رو هم میسپارم به خودتون ، یکم خلاقیت به کار ببندین و انواع کد ها رو امتحان کنین ولی یه تقلب کوچولو :if clauseبریم سراغ اصل کار .فایل compiler.py :8 - 1اول از همه کتابخونه هایی که pyqt نیاز داره رو ایمپورت میکنیم بعد هم که Amirza و Amirza_ui رو .خط 6 و 8 فقط برای اینه که مانیتورهای (high dpi (4k برنامه مون رو ساپورت کنن و کوچیک نشه ، مثل این:ببینین چی شد اصلا :|تو قسمت بعدی ، کلاس اصلی برنامه رو تعریف میکنیم و از کلاس Ui_MainWindows که داخل Amirza_ui بود سابکلاس میگیریم .خط 12به معنی اینه که هر چی در تابع اصلی بوده رو اینجا هم استفاده کن . خط 13 برای کلید cancel هست که اگه false باشه یعنی روش کلیک نشده و true یعنی روش کلیک شده .خط 14 برای نگه داشتن همون number قسمت قبل هست .MainClassخط 18 و 19 که برای اضافه کردن شورتکات برای کلید go هست ، یعنی وقتی Enter روی صفحه کلید فشرده شد ، همون کار انجام بده .تابع number_adder_func برای اضافه کردن مقدار به number هست که بعدا ازش استفاده میکنیم checkbox_checker_funcتابع checkbox_checker_func برای اینه که اول از همه انتخاب شدن هر کدوم از checkbox ها رو بررسی میکنه و بعد هر کدومش که انتخاب شده بود رو یه عدد میفرسته به تابع number_adder_func تا به عدد num اضافه کنه .خط 38 : اگه هیچ کدوم از اون ها انتخاب نشده بودن ، قراره رنگ متن در ErrorLable رو قرمز کنه و پیام خطا نشون بده (که یعنی یکی از اون ها رو انتخاب کن ، همینجوری که نمیشه ...)خط 42 : اگه حداقل یکی از اونها انتخاب شده بود ، برو به تابع بعدی .empty_entrance_funcاین تابع قراره چک کنه که متنی که وارد شده خالی نباشه ، اگه خالی بود ، متن ارور رو نشون بده ولاغیر بره به تابع بعدی .قبل از اینکه بریم سراغ تابع اصلی برنامه ، یه تابع دیگه هم اضافه میکنیم که چک کنه ببینه حتما ما داریم حروف فارسی وارد برنامه میکنیم یا یه زبان دیگه :language_checker_funcخط 64 : اگه اشتباه وارد کنیم ، کلید go رو غیرفعال میکنه .مهم ؛ خط 65 و 70 : این یکی کد مهم در برنامه مونه ، اگه این تیکه نباشه ، در حین اینکه داره این حلقه انجام میشه ، هیچکار دیگه ای نمیشه با برنامه انجام داد و هنگ میکنه ولی این باعث میشه که بازم بشه با برنامه کار کرد(مثلا cancel رو زد یا یه حرف دیگه وارد کرد)ادامه:pushB_clickedوقتی go فشرده میشه ، خط 74 تا 87 که به شدت واضحن ، اجرا میشن ، ادامه :108-89خط 90، مقدار ماکزیمم (آخرین درجه) برای progressbar رو بر اساس تعداد جوابی که Amirza میده ، تنظیم میکنه .تابع cancel که واضحه ، خط 96 هم که میگه وقتی cancel فشرده شد برو به تابع cancel .خط 99: به ازای هر مقدار در ultimList_undup ، یکی به اندازه ی progressbar اضافه کن ، اگه اون مقدار در دیتابیس بود بیا و در answers اضافه کن .خط 103 هم چک میکنه اگه cancel زده شده باشه ، دیگه حلقه رو ادامه نده و بزنه بیرون ازش .116-105خط 105: امتحان کن که خط 106 باز هم چک میکنه که کلمه ی تکراری توی لیستمون نباشه .خط 107 : تابع join یک یا چند کرکتر رو با یک لیست اقدام میکنه و بین هر عضو لیست ، اون کاراکتر ها رو قرار میده .خط 110 : اگه خطوط 106 تا 108 ناموفق بود ، ارور رو نشون بده و wrong رو هم بزار true (یعنی یه مشکل توی برنامه پیدا شد)خط 114 : اگه مشکلی توی برنامه وجود نداشت (wrong == False) قسمت آخر یعنی finish رو نشون بده .قسمت آخر و لذت بخش کدمون :131-119از 120 تا 122 و 130 تا 131 ماله خود Qt هست و بزارین سر جاش بمونه ، خط 123 و 124 : هم واضحهخط 126 : هر دفعه که lineEdit ادیت میشه (یه چیزی توش وارد میشه یا پاک میشه) ، کانکت میشه به اون تابع .خط 127 : هر موقع هم که کلید go فشرده شد ، وصل شو به اون تابع .تمام . اگه یکم گیج شدین اشکالی نداره ، دوباره بخونین ، حتما میفهمین .خب اگه سوالی داشتین یا نظری در مورد اینکه جایی از مقاله ناقص هست یا اشتباهه حتما کامنت کنید . اگه دوست داشتین و به دردتون خورد حتما لایک کنید .مقاله های من :پر بازدید ترین : https://virgool.io/@Bestmahdi2/%D9%86%D8%B5%D8%A8-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%B1%D9%88%DB%8C-%DA%AF%D9%88%D8%B4%DB%8C-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF%D8%AA%D9%88%D9%86-%D8%A8%D8%A7-%D8%B1%D9%88%D8%AA-%D8%A8%D8%AF%D9%88%D9%86-%D8%AA%D8%B1%D9%85%D9%88%DA%A9%D8%B3-oyglehw8nbrn بقیه مقاله ها : https://virgool.io/@Bestmahdi2 telegram : @bestmadi2instagram : @bestmahdi2