JavaRush /Java блогу /Random-KY /Жаңы баштагандар үчүн Java оюну
timurnav
Деңгээл

Жаңы баштагандар үчүн Java оюну

Группада жарыяланган
Салам достор жана келечектеги кесиптештер! Жаңы баштагандар үчүн Java оюну - 1Жакында эле мен чыныгы долбоорго катышуу үчүн тесттен өтүп, андан өттүм, бирок жеке жагдайлардан улам КПнын өзүнө катыша албай калдым. RP тести сыяктуу кызыктуу маселелерден кийин, адаттагы курстук маселелер көңүл ачууга айланды, айрыкча мен алардын көбүн чечип койгондуктан. Ошондуктан, талантым текке кетпеши үчүн окууну улантуу үчүн, мен көп оюнчу веб оюнун түзүүнү чечтим. Башка оюндарга шилтемелер:
  1. бул макаланын уландысы
  2. 2048
Tic Tac Toe мага эң жөнөкөй оюндай көрүндү, ошондуктан мен тапшырманы бир нече кошумча тапшырмаларга бөлүүнү чечтим:
  1. Оюн логикасын текшерүү үчүн консолдук колдонмо
  2. Көп оюнчу
  3. Оюнчу маалымат базасын консолдук тиркемеге тиркөө
  4. Front-end дизайнын түзүү, баракчанын шаблондорун жазуу, оюн интерфейси
  5. Баарын чогултуу
Мени ушундай ырааттуулук үчүн урушуп коюшу мүмкүн жана бардык олуттуу долбоорлор такыр башка ырааттуулукта курулган, мен дароо жооп берем, бул жөнүндө "жаңыдан баштагандар үчүн" пост жазыңыз, ошондо баары (анын ичинде мени да) муну үйрөнө алабыз :) Келгиле, консолдук тиркемени жаза баштайлы! Мен 20-деңгээлдеги чоң тапшырмалардагыдай кадамдарды жасайм. Тик-так-тое оюнунда эмне бар?!
  1. талаа
  2. эки оюнчу кезектешип, бири кайчылаш, экинчиси нөл коёт. баары оңой.
Талааны стандарттуу 3x3 талаасына айландырабыз. Мындай талааны кантип сактоого болот? биринчи параметр эки өлчөмдүү массив болуп саналат. Бул массив кандай элементтерди камтышы керек? Жооп, биз бул элементтер менен эмне кылаарыбызды ойлонушубуз керек, бул жеңүүчүнү табуу үчүн көрсөтүү жана салыштыруу. Эгерде биз аларды экранда гана көрсөткөн болсок, анда аларды сап катары сактоо логикалык жактан туура болмок, анда массивдин өзү жана аны экранда циклде көрсөтүү төмөнкүдөй болмок:
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 - "Х", 2 - "О", 0 - "_" болсун. Ошентип, үчтүк X же О дал келген талааны кантип текшерсе болот?
Эң биринчи алгоритм бүт талааны текшерүү
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 гана комбинацияны алабыз, сүрөттү карагыла: Жаңы баштагандар үчүн Java оюну - 2Эми биз кайсы комбинацияны ишке киргизүү керектигин кантип аныкташыбыз керек? Бул жерде мен эки өлчөмдүү массивди колдонуу абдан ыңгайлуу эмес экенин түшүндүм. Мен башка варианттарды карап көрүүнү чечтим. Адегенде мен талааны тогуз орундуу санда сактоого болот деген ойго келдим, мисалы, биз экранда көрсөткөн талааны мындай жазууга болот: 220012111, мен манжаларым менен түшүндүрөм бул... Код бирдей, 1 - “X”, 2 - “O” , 0 – " ", бул 220012111 = "OO__XOXXX" дегенди билдирет, же ар бир үчүнчү сандан кийин сап үзүлүшүн киргизип, боштуктарды кошсоңуз ачыктык:
О О _
_ Х О
Х Х Х
Бул жерде дагы, сактоо үчүн ыңгайлуу, дисплей үчүн түзүлүш ойлоп табылган, бирок салыштыруу үчүн ыңгайсыз! Чечим уячаларды 1-9га чейин номерлегенде табылды, анан ойлондум, анткени программалоодо артка санак 0дөн башталып, сүрөттөгүдөй номерленген.Эч Жаңы баштагандар үчүн Java оюну - 3кандай өзгөчөлүктү байкаган жоксузбу? эгерде сиз жогорудагы сүрөттү карасаңыз, анда 2 комбинациялуу чечимдер так сериялык номерге ээ, 4 комбинацияда 4 сериялык номер, 3 комбинацияда калганы бар экени айкын болот. Ошентип, мен оюн талаасын сандардын кадимки массивинде сактоо керек деген тыянакка келдим: сандар ортосундагы жөнөкөй итерация, тандалган алгоритмге ылайык салыштыруу, экранга жөнөкөй чыгаруу. Ал эми салыштыруу алгоритминин өзүнө келсек. Тартип менен кетели: бардык варианттарда сап жана мамычаны текшерүү бар, биз аларды гана текшеребиз. эгер издөө натыйжа бербесе, уячанын номерин жуп/так экенин текшеребиз, эгер так болсо, анда биз оюнга кайтабыз, андан ары текшерүүнүн кереги жок, эгер ал жуп болсо, бул уячанын бетинде жайгашканын текшеребиз. сол диагоналда, бул диагоналдын сандары 4кө бөлүнгөндө 0 калды. Ал жалган болсо, дал келүүлөрдү текшеребиз, эгер дал келүү табылбаса, анда 4 санын текшеребиз, эгер жок болсо, оюнга кайтабыз, эгерде ооба, биз codeдон ары өтүп, акыркы диагоналды текшерүүнүн жыйынтыгын кайтарабыз. Балким, даярдыгы жок адам үчүн, жогорудагы тамгалардын топтомун окугандан кийин түшүнүү кыйын, бирок кимдир бирөө codeдун өзүндө көп тамгалар бар деп айтышы мүмкүн, бул жөнөкөйрөөк болушу мүмкүн, мен муну талкуулоого кубанычта болом. Биз талааны иреттеп алдык, эми биз кезектешип турган эки колдонуучу менен иштешибиз керек жана алардын ар биринин өзүнүн X же О белгиси бар. Биринчи этапта бизде көп колдонуучу функциясы жок, андыктан эң оңой жолу иконаларды бирден колдонуу. X ар дайым биринчи кыймылды жасайт, О ар дайым экинчи кыймылды жасайт, андан кийин дагы X ж.б.у.с. Аны текшерүүнү суранат ( чын/жалган ), эгер чын болсо – анда учурдагы оюнчу X, эгерде жалган болсо – анда O жана ар бир кыймылдын башында flag=!flag Бул кандайдыр бир жол менен оюнчулардан кайсынысы жөнүндө сигнал алуу үчүн калат. алар тандашат. Бул жерде бизге эстен кеткис BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); Оюнчулар керек болот, консолго уюлдук номерлерди киргизет жана Enter баскычын басуу кыймылды жасайт. Киргизилген санга туура келген уяча жогорудагы абзацта талкууланган кутучанын учурдагы абалына жараша анын маанисин 0дөн 1ге же 2ге өзгөртөт. Бул жерде уяча толуп турганда Xти эч ким O деп өзгөртө албашы үчүн киргизүүнү текшерүү маанилүү. :) Оюнчу консолго эмне киргизе алат?
  1. бош линия
  2. тамгалар, тыныш белгилери, кашаалар... бир сөз менен, сандар эмес
  3. туура эмес сандар - терс же массив өлчөмүнөн тышкары, ээлеген клеткалар.
Саптан цифраны алуунун стандарттык ыкмасы Integer классынын статикалык parseInt ыкмасы болуп саналат. Эгерде ал берилген саптан цифраны ала албаса, Integer.parseInt("2");өзгөчө кырдаалды жаратат . Бул өзгөчөлүктү кармап, биз биринчи эки чекиттен коргоону камсыздай алабыз. NumberFormatExceptionҮчүнчү пункт үчүн, мен киргизилген маанини текшерген башка ыкманы түзмөкмүн, бирок сап өтүнүчүн валидация жүргүзүлө турган өзүнчө ыкмага жылдыруу эң туура болмок жана ал санды гана кайтарат. Жыйынтыктап айтканда, биз талаа түздүк, аны көрсөтүүчү ыкманы жасадык, “бул оюнчу бир саатка уттубу?” дегенди текшерүүчү ыкманы жасап, киргизилген сандарды ырастадык. Эч нерсеге аз калды, чүчүкулакты текшериңиз - массивди аралап өтүп, 0 издеген жана оюндун жыйынтыгын көрсөткөн өзүнчө ыкма. Болду, code даяр, оюн кичинекей болуп чыкты, бир гана класс, ошондуктан катаал копи-пастерлер түшүнбөстөн, баарын өз долбооруна көчүрүп алып, өз алдынча иштете алышат, мен өзүм да ошондой болчумун, бирок азыр мен андай кылбаганга аракет кылам жана эч кимге сунуш кылбайм :) JAVA үйрөнүүдө баарына ийгorк! 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;
    }
}
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION