در این مقاله ، بازی Tetris را در Java Swing  آموزش خواهیم داد.

این بازی، یکی از محبوب ترین بازی های کامپیوتری ای تا کنون ایجاد شده اند می باشد. این بازی، توسط یک برنامه نویس روس به نام Alexey Pajitnov در سال 1985 طراحی شده است. از آن زمان تا کنون، Tetris تقریبا بر روی هر پلتفرم کامپیوتر در دسترس است.

 

در بازی Tetris، یک سری بلوک، با رنگ و اشکال مختلف، در حال سقوط میباشند.
در بازی ای که ما طراحی کردیم، هفت شکل مختلف به نام های Square-shape، S-shape، Z-shape، T-shape، L-shape ،Line-shape و MirroredL-shape وجود دارد که هر یک از این اشکال با چهار مربع تشکیل شده اند.

بازی بلافاصله پس از راه اندازی، شروع می شود.
در هر لحظه یکی از این اشکال به طور تصادفی در حال سقوط در Board هستند.
این بلوک ها توسط کلید های جهت نما، توانایی حرکت و چرخیدن را دارند، تا از این طریق بتوان هر بلوک را در بهترین و بصرفه ترین حالت ممکن، در Board نشاند.
بافشردن کلید P بازی متوقف میشود.

کلید Space قطعه را بلافاصله به پایین رها میکند.کلید d نیز برای سرعت بخشیدن به حرکتِ قطعه بلوکِ در حالِ سقوط، خواهدبود.

هرگاه موفق به تشکیل یک ردیف شویم (بطوریکه هیچ فضای خالی ای در آن ردیف وجود نداشته باشد)، تمامی قطعه هایی که همرنگ با قطعات موجود در ردیف مذکور و همچنین، در تماس با آنها باشند، از Board حذف خواهند شد و لذا قطعاتی که روی این بلوک ها وجود داشتند، به همان تعداد ردیفِ حذف شده، به پایین خواهند آمد.
تا زمانی که ارتفاع برج به ارتفاع برد نرسیده باشد، بازی ادامه خواهد داشت.

در این بازی، هیچ تصویری نخواهیم داشت وبلوک های مذکوررا با استفاده از API های Swing drawing رسم می کنیم. برای ایجاد چرخهای برای تکرار حضور بلوک ها درBoard،  از یک کلاسTimer  استفاده میکنیم.  با توضیحات فوق، کار را شروع میکنیم.
پروژه ی جدیدی در NeatBeans ایجاد می کنیم و پکیجی به نام Tetris  در آن قرار می دهیم و سپس به ایجاد کلاس های مورد نیاز در این پکیج می پردازیم.

ابتدا کلاسی تحت عنوان shape ، برای پیاده سازی اشکال ، ایجاد می کنیم:

 

 

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

– در enum Tetrominoes، هفت شکلِ مختلفی را که در ابتدای توضیحات ذکر شد را معرفی و ذخیره می کنیم (شکل خالی  را نیز با نام NoShape  معرفی می کنیم).

تابع فوق،تابع سازنده ی کلاسShape  می باشد.

آرایه ی coords، مختصات واقعی هر یک از قطعات Tetris را در خود نگه می دارد.

 

 

-به متد setShape توجه میکنیم:

آرایه ی coordsTable، تمام مقادیر ممکن برای مختصات قطعه های Tetris  را درخود نگه میدارد. این یک الگویی است که تمام قطعات، مختصاتشان را از آن می گیرند.

در حلقه ی تکرار زیر

 

یک ردیف از مقادیر مختصات coordsTable رادر آرایه ی coords هرقطعه، قرار می دهیم.

استفاده از آرایه مختصات، بسیار بهینه است. به عنوان مثال، اعداد {0، -1 }، { 0، 0 }، { -1 ، 0 }، { -1 ، 1}، نشان دهنده یک چرخش S شکل میباشند. نمودار در شکل زیر نشان داده شده است:

 

1

با فشردن کلیدهای جهت نمای چپ (راست) قطعه به سمت چپ (راست)board حرکت می کند.
با فشردن کلید جهت نمای بالا (پایین)، قطعه در جهت راست (چپ) می چرخد.

 

کد زیر، قطعه ها را به سمت چپ می چرخاند.

 

با نگاهی به تصویر قبل، متوجه چگونگی چرخش قطعات می شویم.

-تابع rotateRight() نیز عملکرد مشابهی، برای چرخاندن قطعات به سمت راست دارد.

 

 

 

حال به سراغ کلاس Board  می رویم، جایی که منطق بازی در آن پیاده سازی شده است:

 

در ابتدا متغیرهای موردنیاز را تعریف، و در صورت لزوم، مقدار دهی می کنیم:

-متغیرهای BoardWidth وBoardHeight  به ترتیب عرض و ارتفاع مربع هایی که اشکال با آنها ساخته شده اند را مشخص می کنند.

-متغیر isFallingFinished تعیین می کنید که اگر قطعه بلوکی که در حال  سقوط می باشد، در Board نشانده شد، نیاز به ایجاد یک شکل جدید داریم.

-متغیرnumLinesRemoved تعداد خطوطی که تا کنون حذف شده اند را می شمارد.-متغیرهای curX و curY موقعیت واقعی قطعه بلوکی که درحال سقوط است را تعیین میکند.

-متد setFocusable(true)  را فراخوانی می کنیم تا Board، ورودی های صفحه کلید را در اختیار بگیرد.

 

-در قطعه کد فوق، تایمر،متد actionPerformed()  را هر 400 میلی ثانیه ،فراخوانی می کند.

 

-متد actionPerformed()، بررسی می کند که آیا سقوط به پایان رسیده است یا خیر. اگر سقوط انجام شده باشد، قطعه دیگری از Tetris ایجاد می کند و اگر خیر، قطعه فعلی یک ردیف پایین تر می آید.

-درون متد Paint()، تمامی اشیائی که در Board هستند را رسم می کنیم، که این کشیدن دو مرحله دارد:

 

در گام اول، همه ی بلوک و یا باقی مانده ای از بلوک ها را که  درBoard ظاهر می شوند را تا قبل از نشاندن، رسم میکنیم (یعنی بلوک را ظاهر می کنیم و به سمت پایین برد حرکت می دهیم).

و در گام دوم، بلوک را زمانی که سقوط انجام شده، رسم می کنیم(یعنی همان بلوکی را که در مرحله قبل رسم کرده بودیم وبه پایین  Board حرکت داده بودیم را، در این مرحله می نشانیم).

 

 

– متد dropDown() برای پیاده سازی عملکرد کلید  Spaceمی باشد.
به این شکل که وقتی کلید Space فشرده می شود، قطعه در همان راستا، باسرعت به پایین سقوط می کند.

-متد clearBoard()، Board را ازشکل های خالی (NoSpapes ) پر می کند، که در تشخیص برخورد استفاده می شود.

 

 

– متد pieceDropped () قطعه در حال سقوط را در آرایه board قرار می دهد. بار دیگر، Board دارای همه مربع های بلوک ها، یا قطعاتی از هر بلوک که باقیمانده است می باشد. هنگامی که قطعه های در حال سقوط به پایان رسیدند، زمان بررسی آن است که می توانیم برخی از خطوط را از Board حذف کنیم یا خیر! که این کارِمتد removeFullLines()  است.

درپایان این متد هم با بررسی اینکه بلوک در Board نشانده شده است یا خیر، یک قطعه جدید ایجاد می کنیم.

 

 

 

– متد newPiece ()  یک قطعه Tetris جدید ایجاد می کند. قطعه، شکل تصادفی ای از اشکالی که در ابتدا ذکر شد، به خود می گیرد. سپس مقادیر اولیه curX و curY محاسبه میشوند. اگر نتوانیم از این موقعیت مکانی تغییر مکان دهیم(حرکت کنیم)، بازی تمام است. لذاتایمر متوقف می شود و متن “game over” را درقسمت وضعیت قرار می دهیم.

 

 

– متد tryMove()، سعی میکند که قطعات را حرکت دهد.
اگر  بلوکِ در حال سقوط، فراتراز مرزهای Board بخواهد حرکتی داشته باشد، و یا اینکه به موقعیتی از Board که خالی نیست (یعنی قطعه ای ازبلوک ها در آن موقعیت قرار گرفته باشد)، این متد false  را برمیگرداند (به این معنا که حرکت به آن قسمت، مجاز نیست).

 

 

– درمتد removeFullLines()، چک می کنیم که آیا در میان همه ی ردیف ها، ردیفی وجود دارد که کامل باشد. در صورتی که حداقل یک ردیف کامل وجود دارد، آن ردیف، به نحوی که در ابتدای توضیحات ارائه شد، حذف می شود و بعد از آن، یک واحد به شمارنده اضافه می کنیم و همه ی قطعه هایی که روی ردیف کامل وجود داشتند را، یک ردیف پایین تر می آوریم.

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

 

همانطور که گفته شد، هر قطعه Tetris دارای چهار مربع است. هر یک از مربع ها، توسط متد drawSquare() کشیده می شوند.

 

برای شبیه سازی سه بعدی لبه ها، دو طرف چپ و بالای مربع ها با یک رنگ روشن تر کشیده شده اند. به طور مشابه، دو طرف پایین و راست مربع ها، با رنگ تیره تری کشیده شده است.

-عملکرد باقی متدهای این کلاس (مثل متد pause()) کاملا روشن است، لذا از بیانِ آن خودداری می کنیم.

حال کلاس حاوی main  را ایجاد می کنیم:

2

برنامه آماده اجراست.
تصویری از بازی را درشکل زیر می بینیم:

 

3

 

 

ozviiiiiiiat

 

دانلود فایل پروژه