Salam dostlar və gələcək həmkarlar! Bu yaxınlarda mən real layihədə iştirak etmək üçün imtahan verdim, ondan keçdim, amma elə oldu ki, şəxsi şəraitə görə RP-nin özündə iştirak edə bilmədim. RP testi kimi maraqlı problemlərdən sonra adi kurs problemləri daha az cəlbedici bir əyləncəyə çevrildi, xüsusən də onların əksəriyyətini artıq həll etdiyim üçün. Buna görə də, öyrənməyə davam etmək üçün istedadımın boşa getməməsi üçün multiplayer veb oyunu yaratmağa qərar verdim. Digər oyunlara keçidlər:
Tic Tac Toe mənə ən sadə oyun kimi görünürdü, ona görə də tapşırığı bir sıra alt tapşırıqlara bölmək qərarına gəldim:
İlk alqoritm bütün sahəni yoxlamaqdır
- Oyun məntiqini yoxlamaq üçün konsol tətbiqi
- Multiplayer
- Oyunçu məlumat bazasının konsol proqramına əlavə edilməsi
- Front-end dizaynının yaradılması, səhifə şablonlarının yazılması, oyun interfeysi
- Hamısını bir yerə yığmaq
- sahə
- növbə çəkən iki oyunçu, biri xaç qoyur, digəri sıfır. bu sadədir.
String[][] strings = {{"O", "O", "_"},
{"_", "X", "O"},
{"X", "X", "X"},
for (String [] ss : strings){
for (String s : ss) System.out.print(s + " ");
System.out.println(); //для перевода строки
}
ekranda göstərilir:
O O _
_ X O
X X X
Ancaq ekrana əlavə olaraq, dəyərlərin müqayisəsi də var və burada seçimlər artıq mümkündür. Siz sətirləri müqayisə edə bilərsiniz, xüsusi nömrələmə sinfi yarada bilərsiniz ( enum
), lakin mən rəqəmləri müqayisə etməyə və onları yalnız ekranda göstərildikdə “X” və “O” ilə əvəz etməyə üstünlük verərdim. Məsələn, 1 - "X", 2 - "O", 0 - "_" olsun. Beləliklə, üçlü X və ya O uyğunluğu üçün bir sahəni necə yoxlamaq olar?
İlk alqoritm bütün sahəni yoxlamaqdır
int[][] canvas = {{00, 01, 02},
{10, 11, 12},
{20, 21, 22}}
Qazanan kombinasiyalar:
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.
Rəqəmləri müqayisə etməklə yoxlanılır, lakin məlum olur ki, hər dəfə BÜTÜN sahəni, bütün 8 kombinasiyanı yoxlamaq lazımdır. Əlbəttə ki, bu çox deyil, bu, 0-dan 1 milyarda qədər olan Armstronq nömrələrinin axtarışı deyil, burada heç bir hesablama yoxdur, amma yenə də bütün sahəni yoxlamaqdan daha optimal bir şey istəyirsən. Mənə gələn ikinci fikir, yalnız əvvəlki hərəkətdə işarələnmiş xananı yoxlamaq idi, ona görə də qalibi hələ də müəyyən edə bilərik, çünki bu hərəkəti kimin etdiyini biləcəyik. Beləliklə, bütün 8 birləşmənin əvəzinə, hüceyrədən asılı olaraq yalnız 2, 3 və ya 4 kombinasiya alırıq, şəklə baxın: İndi hansı kombinasiyanın işə salınması lazım olduğunu necə müəyyənləşdirməliyik? Burada anladım ki, iki ölçülü massivdən istifadə o qədər də rahat deyil. Başqa variantlara baxmağa qərar verdim. Əvvəlcə belə bir fikrə gəldim ki, sahəni doqquz rəqəmli rəqəmdə saxlamaq olar, məsələn, ekranda göstərdiyimiz sahə belə yazıla bilər: 220012111, barmaqlarımda bunun nə olduğunu izah edəcəyəm. Bu... Kod eynidir, 1 - “X”, 2 - “O” , 0 – " ", yəni 220012111 = "OO__XOXXX" deməkdir və ya hər üçüncü rəqəmdən sonra sətir sonu daxil edirsinizsə və boşluq əlavə edirsinizsə aydınlıq:
О О _
_ Х О
Х Х Х
burada yenə saxlama üçün əlverişli, ekran üçün bir cihaz icad edildi, lakin müqayisə üçün əlverişsiz! Həll yolu 1-9 xanalarını nömrələyəndə tapıldı, sonra fikirləşdim, çünki proqramlaşdırmada geri sayım 0-dan başlayır və şəkildəki kimi nömrələnir.Heç bir özəllik görmədiniz? yuxarıdakı şəklə baxsanız, aydın olacaq ki, 2 kombinasiyalı məhlulların tək seriya nömrəsi, 4 kombinasiyanın seriya nömrəsi 4, 3 birləşmənin qalan hissəsi var. Beləliklə, mən belə bir nəticəyə gəldim ki, oyun sahəsini adi nömrələr massivində saxlamaq lazımdır: nömrələr arasında sadə təkrarlama, seçilmiş alqoritmə uyğun olaraq müqayisə etmək imkanı, ekrana sadə çıxış. Müqayisə alqoritminin özünə gəldikdə. Gəlin qaydada gedək: bütün variantlarda satır və sütunun yoxlanışı var, biz yalnız onları yoxlayırıq. axtarış nəticə verməsə, xana nömrəsini cüt/tək olub-olmadığını yoxlayırıq, təkdirsə, oyuna qayıdırıq, əlavə yoxlamağın mənası yoxdur, əgər cütdürsə, bu xananın üzərində olub-olmadığını yoxlayırıq. sol diaqonal, 4-ə bölünəndə bu diaqonalın nömrələri 0-a bərabərdir. Yalandırsa, uyğunluqları yoxlayırıq, uyğunluq tapılmırsa, 4 rəqəminin olub olmadığını yoxlayırıq, yoxsa, oyuna qayıdırıq, əgər bəli, kodu daha da irəliləyirik və sonuncu diaqonalı yoxlamanın nəticəsini qaytarırıq. Yəqin ki, hazırlıqsız bir insan üçün yuxarıdakı hərflər toplusunu oxuduqdan sonra bunu başa düşmək çətindir, amma kimsə deyə bilər ki, kodun özündə çoxlu hərf var, daha sadə ola bilər, bunu müzakirə etməkdən məmnun olaram. Biz sahəni sıraladıq, indi növbə ilə işləyən iki istifadəçi ilə məşğul olmalıyıq və onların hər birinin öz işarəsi var, X və ya O. Birinci mərhələdə bizdə çox istifadəçi funksiyası yoxdur, ona görə də ən asan yol nişanları bir-bir istifadə etmək olardı. X həmişə birinci hərəkəti edir, O həmişə ikincini edir, sonra yenidən X və s. Yoxlanmağı xahiş edir ( doğru/yanlış ) və əgər doğrudursa – o zaman cari oyunçu X-dir, əgər yalansa – onda O və hər hərəkətin əvvəlində bayraq=!bayraq Oyunçulardan hansısa bir şəkildə hansının olması barədə siqnal almaq qalır. seçdikləri hüceyrə. Burada unudulmaz Oyunçularımıza ehtiyacımız olacaq BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
, konsola hüceyrə nömrələrini daxil edəcək və Enter düyməsini basaraq hərəkət edəcək. Daxil edilmiş nömrəyə uyğun gələn xana yuxarıdakı paraqrafda müzakirə edilən qeyd qutusunun cari vəziyyətindən asılı olaraq dəyərini 0-dan 1-ə və ya 2-yə dəyişəcək. Hüceyrə artıq doldurulduqda heç kimin X-i O-ya dəyişdirə bilməməsi üçün girişi təsdiqləmək vacibdir :) Oyunçu konsola nə daxil edə bilər?
- boş xətt
- hərflər, durğu işarələri, mötərizələr... bir sözlə qeyri-rəqəmlər
- səhv nömrələr - mənfi və ya massiv ölçüsündən kənarda, işğal edilmiş hüceyrələr.
Integer.parseInt("2");
istisna atır.Bu istisnanı kəsməklə ilk iki nöqtədən qorunma təmin edə bilərik. NumberFormatException
Üçüncü nöqtə üçün, daxil edilmiş dəyəri yoxlayan başqa bir üsul yaradardım, lakin sətir sorğusunu doğrulamanın aparılacağı ayrı bir metoda köçürmək ən düzgün olardı və o, yalnız bir rəqəm qaytaracaq. Xülasə etmək üçün bir sahə yaratdıq, onu göstərən bir üsul yaratdıq, “bu oyunçunun bir saat qalib olub-olmadığını” yoxlayan bir üsul yaratdıq və daxil edilmiş nömrələri təsdiqlədik. Çox az qalıb, heç-heçəni yoxlayın - massivdən keçən və 0-ı axtaran və oyunun nəticələrini göstərən ayrıca üsul. Hamısı budur, kod hazırdır, oyun kiçik oldu, yalnız bir sinif oldu, buna görə sərt kopirayterlər başa düşmədən hər şeyi öz layihələrinə köçürə və özləri işlədə bilərlər, mən özüm də belə idim, amma indi bunu etməməyə çalışıram və heç kimə tövsiyə etmirəm :) JAVA-nı öyrənməkdə hər kəsə uğurlar! ps qalan məqamlar - multiplayer və verilənlər bazası daha sonra gələcək, mən artıq materialı öyrənməyə başlamışam :)
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