سلام دوستان و همکاران آینده اخیراً برای شرکت در یک پروژه واقعی آزمایش دادم، آن را قبول کردم، اما اتفاقی افتاد که به دلیل شرایط شخصی نتوانستم در خود RP شرکت کنم. پس از مشکلات جالبی مانند آزمون RP، مسائل معمول دروس به سرگرمی کمتر جذابی تبدیل شدند، به خصوص که من قبلاً اکثر آنها را حل کرده بودم. بنابراین، برای اینکه استعدادم برای ادامه یادگیری هدر نرود، تصمیم گرفتم یک وب بازی چند نفره بسازم. لینک بازی های دیگر:
Tic Tac Toe برای من ساده ترین بازی به نظر می رسید، بنابراین تصمیم گرفتم این کار را به تعدادی زیرکار تقسیم کنم:
اولین الگوریتم بررسی کل فیلد است
- نرم افزار کنسول برای تست منطق بازی
- چند نفره
- پیوست کردن پایگاه داده پخش کننده به یک برنامه کنسول
- ایجاد طراحی جلویی، نوشتن قالب های صفحه، رابط بازی
- همه اش را بگذار کنار هم
- رشته
- دو بازیکن که به نوبت می آیند، یکی صلیب می گذارد، دیگری صفر. ساده است.
String[][] strings = {{"O", "O", "_"},
{"_", "X", "O"},
{"X", "X", "X"},
for (String [] ss : strings){
for (String s : ss) System.out.print(s + " ");
System.out.println(); //для перевода строки
}
صفحه نمایش نشان می دهد:
O O _
_ X O
X X X
اما علاوه بر نمایش، مقایسه مقادیر نیز داریم و در اینجا گزینه هایی از قبل امکان پذیر است. میتوانید رشتهها را مقایسه کنید، میتوانید یک کلاس شمارش ویژه ( enum
) ایجاد کنید، اما من ترجیح میدهم اعداد را با هم مقایسه کنیم و فقط زمانی که روی صفحه نمایش داده میشوند، «X» و «O» را جایگزین آنها کنم. بگذارید مثلاً 1 - "X"، 2 - "O"، 0 - "_" باشد. بنابراین، چگونه یک فیلد را برای تطابق سه گانه X یا O بررسی می کنید؟
اولین الگوریتم بررسی کل فیلد است
int[][] canvas = {{00, 01, 02},
{10, 11, 12},
{20, 21, 22}}
ترکیب های برنده:
00-01-02, 10-11-12, 20-21-22, 00-10-20, 01-11-21, 02-12-22, 00-11-22, 20-11-02 — всего 8.
بررسی با مقایسه اعداد، اما معلوم می شود که باید هر بار کل فیلد، هر 8 ترکیب را بررسی کنید. البته این خیلی زیاد نیست، این جستجوی اعداد آرمسترانگ در محدوده 0 تا 1 میلیارد نیست، در اینجا کمی بیش از هیچ محاسباتی وجود ندارد، اما شما هنوز چیزی بهینه تر از بررسی کل فیلد می خواهید. ایده دومی که به ذهنم رسید این بود که فقط سلولی را که در حرکت قبلی مشخص شده بود بررسی کنم، بنابراین ما همچنان می توانیم برنده را تعیین کنیم، زیرا می دانیم چه کسی این حرکت را انجام داده است. بنابراین، به جای هر 8 ترکیب، بسته به سلول، فقط 2، 3 یا 4 ترکیب دریافت می کنیم، تصویر را ببینید: اکنون باید بفهمیم که چگونه تعیین کنیم کدام ترکیب باید راه اندازی شود؟ اینجاست که متوجه شدم استفاده از آرایه دو بعدی خیلی راحت نیست. تصمیم گرفتم گزینه های دیگری را در نظر بگیرم. در ابتدا به این فکر افتادم که فیلد را می توان در یک عدد نه رقمی نگه داشت، مثلاً همان فیلدی را که روی صفحه نمایش می دهیم می توان اینگونه نوشت: 220012111، من در انگشتانم توضیح می دهم که چیست. است... کد یکسان است، 1 - "X", 2 - "O" , 0 - " "، که به معنی 220012111 = "OO__XOHX" است، یا اگر بعد از هر رقم سوم یک شکست خط وارد کنید و برای آن فاصله اضافه کنید. وضوح:
О О _
_ Х О
Х Х Х
در اینجا دوباره، برای ذخیره سازی راحت، دستگاهی برای نمایش اختراع شد، اما برای مقایسه ناخوشایند! راه حل وقتی پیدا شد که سلول ها را 1-9 شماره گذاری کردم، سپس فکر کردم، زیرا در برنامه نویسی شمارش معکوس از 0 شروع می شود و آن را مانند تصویر شماره گذاری می کنم. آیا شما به ویژگی خاصی توجه نکردید؟ اگر به تصویر بالا نگاه کنید، مشخص می شود که راه حل های دارای 2 ترکیب دارای شماره سریال فرد هستند، 4 ترکیب دارای شماره سریال 4 و 3 ترکیب دارای مابقی هستند. بنابراین من به این نتیجه رسیدم که باید زمین بازی را در یک آرایه منظم از اعداد نگه دارید: تکرار ساده بین اعداد، توانایی مقایسه با توجه به الگوریتم انتخاب شده، خروجی ساده روی صفحه نمایش. در مورد خود الگوریتم مقایسه. بیایید به ترتیب برویم: در همه گزینه ها یک بررسی از سطر و ستون وجود دارد، ما فقط آنها را بررسی می کنیم. اگر جستجو به نتیجه نرسید، شماره سلول را برای زوج/فرد بررسی می کنیم، اگر فرد است، سپس به بازی برمی گردیم، بررسی بیشتر فایده ای ندارد، اگر زوج باشد، بررسی می کنیم که آیا این سلول روی مورب سمت چپ، اعداد این مورب وقتی بر 4 تقسیم می شوند، باقیمانده 0 هستند. اگر دروغ باشد، مطابقت را بررسی می کنیم، اگر مطابقت پیدا نشد، سپس عدد 4 را بررسی می کنیم، اگر نه، به بازی برمی گردیم، اگر بله، کد را بیشتر می کنیم و نتیجه بررسی آخرین قطر را برمی گردانیم. احتمالاً برای یک فرد ناآماده درک این موضوع پس از خواندن مجموعه حروف بالا دشوار است، اما ممکن است کسی بگوید که حروف زیادی در خود کد وجود دارد که می تواند ساده تر باشد، خوشحال می شوم در این مورد بحث کنم. ما زمینه را مرتب کرده ایم، اکنون باید با دو کاربر که به نوبت انجام می دهند و هر کدام علامت مخصوص به خود را دارند، X یا O سروکار داریم. در مرحله اول، ما هیچ عملکرد چند کاربره نداریم، بنابراین ساده ترین راه این است که از نمادها یک به یک استفاده کنید. X همیشه اولین حرکت را انجام می دهد، O همیشه حرکت دوم را انجام می دهد، سپس X دوباره و غیره. التماس میکند ( درست/نادرست ) بررسی شود ، و اگر درست باشد - بازیکن فعلی X است، اگر نادرست است - سپس O و در ابتدای هر حرکت flag=!flag باقی میماند که به نحوی سیگنالی از بازیکنان دریافت کنیم که در مورد آن سلولی که انتخاب می کنند در اینجا ما به BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
بازیکنان فراموش نشدنی خود نیاز خواهیم داشت که شماره سلول ها را وارد کنسول می کنند و با فشار دادن Enter حرکتی انجام می شود. سلول مربوط به عدد وارد شده بسته به وضعیت فعلی چک باکس که در پاراگراف بالا توضیح داده شد، مقدار خود را از 0 به 1 یا 2 تغییر می دهد. اینجاست که مهم است که ورودی را تایید کنیم تا وقتی سلول از قبل پر شده است، هیچکس نتواند X را به O تغییر دهد :) پخش کننده چه چیزی را می تواند وارد کنسول کند؟
- خط خالی
- حروف، علائم نگارشی، پرانتز... در یک کلمه، غیر اعداد
- اعداد نادرست - منفی یا خارج از اندازه آرایه، سلول های اشغال شده.
Integer.parseInt("2");
یک استثنا ایجاد می کند.ما می توانیم با قطع این استثنا، از دو نقطه اول محافظت کنیم. NumberFormatException
برای نکته سوم، من متد دیگری ایجاد می کنم که مقدار وارد شده را بررسی می کند، اما صحیح ترین آن است که درخواست رشته را به یک متد جداگانه منتقل کنیم که در آن اعتبارسنجی انجام می شود و فقط یک عدد را برمی گرداند. به طور خلاصه، یک فیلد ایجاد کردیم، روشی ساختیم که آن را نمایش میدهد، روشی ساختیم که «آیا این بازیکن یک ساعت برنده شد؟» را بررسی میکند و اعداد وارد شده را اعتبارسنجی میکند. کار بسیار کمی باقی مانده است، برای قرعه کشی بررسی کنید - یک روش جداگانه که در آرایه اجرا می شود و 0 را جستجو می کند و نتایج بازی را نشان می دهد. این همه است، کد آماده است، بازی کوچک است، فقط یک کلاس، بنابراین کپی پاسترهای سخت می توانند بدون درک، همه چیز را در پروژه خود کپی کنند و آن را به تنهایی اجرا کنند، من خودم اینطور بودم، اما اکنون سعی می کنم این کار را نکنم و به کسی توصیه نمی کنم :) برای همه در یادگیری جاوا موفق باشید! ps بقیه نکات - چند نفره و دیتابیس بعدا میاد، من قبلا شروع کردم به مطالعه مطالب :)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class GameField {
static int [] canvas = {0,0,0,
0,0,0,
0,0,0};
//012, 345, 678, 036, 147, 258, 048, 246
public static void main(String[] args){
boolean b;
boolean isCurrentX = false;
do {
isCurrentX = !isCurrentX;
drawCanvas();
System.out.println("mark " + (isCurrentX ? "X" : "O"));
int n = getNumber();
canvas[n] = isCurrentX ? 1 : 2;
b = !isGameOver(n);
if (isDraw()){
System.out.println("Draw");
return;
}
} while (b);
drawCanvas();
System.out.println();
System.out.println("The winner is " + (isCurrentX ? "X" : "O") + "!");
}
static int getNumber(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
try {
int n = Integer.parseInt(reader.readLine());
if (n >= 0 && n < canvas.length && canvas[n]==0){
return n;
}
System.out.println("Choose free cell and enter its number");
} catch (NumberFormatException e) {
System.out.println("Please enter the number");
} catch (IOException e) {
}
}
}
static boolean isGameOver(int n){
// 0 1 2
// 3 4 5
// 6 7 8
//поиск совпадений по горизонтали
int row = n-n%3; //номер строки - проверяем только её
if (canvas[row]==canvas[row+1] &&
canvas[row]==canvas[row+2]) return true;
//поиск совпадений по вертикали
int column = n%3; //номер столбца - проверяем только его
if (canvas[column]==canvas[column+3])
if (canvas[column]==canvas[column+6]) return true;
//мы здесь, значит, первый поиск не положительного результата
//если meaning n находится на одной из граней - возвращаем false
if (n%2!=0) return false;
//проверяем принадлежит ли к левой диагонали meaning
if (n%4==0){
//проверяем есть ли совпадения на левой диагонали
if (canvas[0] == canvas[4] &&
canvas[0] == canvas[8]) return true;
if (n!=4) return false;
}
return canvas[2] == canvas[4] &&
canvas[2] == canvas[6];
}
static void drawCanvas(){
System.out.println(" | | ");
for (int i = 0; i < canvas.length; i++) {
if (i!=0){
if (i%3==0) {
System.out.println();
System.out.println("_____|_____|_____");
System.out.println(" | | ");
}
else
System.out.print("|");
}
if (canvas[i]==0) System.out.print(" " + i + " ");
if (canvas[i]==1) System.out.print(" X ");
if (canvas[i]==2) System.out.print(" O ");
}
System.out.println();
System.out.println(" | | ");
}
public static boolean isDraw() {
for (int n : canvas) if (n==0) return false;
return true;
}
}
GO TO FULL VERSION