* Упражнение за структура от данни Queue
Публикувано на 16 май 2023 в раздел УКИ.
Ще надградим проекта, в който се упражняваше структурата от данни стек, като реализираме по-разширен вариант на играта Война. При нея вместо картите да се премахват от тестетата на играчите, всяка спечелена ръка се връща най-отдолу в тестето на този, който е спечелил. Засега за опростяване на играта ще се отклоним от пълния ѝ вариант, като при равенство (когато получим карти с една и съща стойност) ще приемем, че битката печели чрез цвета във възходящ ред: спатия, каро, купа, пика (в истинската игра не е така). Ще печели играчът, който прибере всички карти. Ще използваме оригиналният дизайн със съвсем леки модификации - dealsValue вече ще започва да брои от 0 и ще се увеличава нагоре, като този брояч вече ще има смисъл на „колко на брой хода са направени от началото на играта“.
Първото нещо, което ще направим, е да променим типа на член-променливите. Двете купчини с карти на играчите ще станат съответно от тип структура от данни Queue по следния начин:
Queue<Integer> leftCards = new LinkedList<>(); Queue<Integer> rightCards = new LinkedList<>();
Промяната в метода на инициализиращото събитие ще е минимална:
private void formWindowOpened(java.awt.event.WindowEvent evt) { for(int i=0; i<52; i++){ deck.add(i); } Collections.shuffle(deck); for(int i=0; i<26; i++){ leftCards.add(deck.get(i)); rightCards.add(deck.get(i+26)); } leftCardPlayed.setText(" "); rightCardPlayed.setText(" "); }
Модификацията за кода на метода на бутона е следната:
private void dealButtonActionPerformed(java.awt.event.ActionEvent evt) { // Краят на играта вече настъпва когато едно от двете тестета свърши if(leftCards.size()==0 || rightCards.size()==0){ message.setText("Играта завърши"); leftCardPlayed.setVisible(false); rightCardPlayed.setVisible(false); dealButton.setEnabled(false); return; } Integer left = leftCards.poll(); Integer right = rightCards.poll(); leftCardPlayed.setIcon(new ImageIcon(getClass().getResource("/CardsWarGame/images/"+left+".png"))); rightCardPlayed.setIcon(new ImageIcon(getClass().getResource("/CardsWarGame/images/"+right+".png"))); if((left)%13 > (right)%13){ leftPlayerScore.setText(""+(Integer.parseInt(leftPlayerScore.getText())+1)); message.setText(" Точка за левия "); // Връщаме картите в началото на левия списък leftCards.add(left); leftCards.add(right); } else if((left)%13 < (right)%13){ rightPlayerScore.setText(""+(Integer.parseInt(rightPlayerScore.getText())+1)); message.setText(" Точка за десния "); // Връщаме картите в началото на десния списък rightCards.add(right); rightCards.add(left); } else{ // При равенство проверяваме кой е по-силния цвят - той ще спечели ръката // Възползваме се, че при именоването на файловете са подредени по големина на цветовете if(left > right){ leftPlayerScore.setText(""+(Integer.parseInt(leftPlayerScore.getText())+1)); message.setText(" Точка за левия "); leftCards.add(left); leftCards.add(right); } else{ rightPlayerScore.setText(""+(Integer.parseInt(rightPlayerScore.getText())+1)); message.setText(" Точка за десния "); rightCards.add(right); rightCards.add(left); } } dealsValue.setText(""+(Integer.parseInt(dealsValue.getText())+1)); // При край на играта вече скриваме гърба на картите само на загубилия if(leftCards.size()==0){ leftDeck.setVisible(false); dealButton.setText("Край"); } if(rightCards.size()==0){ rightDeck.setVisible(false); dealButton.setText("Край"); } }
Ще забележите, че при този вариант играта става много по-продължителна. Може да се наложи да извършвате над 200 хода и дори много повече, преди да се стигне до изчерпване на една от двете конкурентни опашки. Обърнете също внимание, че играта приключва точно тогава, когато единият играч е натрупал точно 26 точки повече от другия.
Нека се възползваме от това и да променим броячите така, че да отразяват текущия броя карти в тестето на съответния играч. Началната стойност на тези броячи трябва да е 26. След това вместо да ги увеличаваме с единица, просто в края на всеки ход ще ги променяме с текст, който отразява текущия брой елементи в опашката. Промените ще са следните:
private void dealButtonActionPerformed(java.awt.event.ActionEvent evt) { if(leftCards.size()==0 || rightCards.size()==0){ message.setText("Играта завърши"); leftCardPlayed.setVisible(false); rightCardPlayed.setVisible(false); dealButton.setEnabled(false); return; } Integer left = leftCards.poll(); Integer right = rightCards.poll(); leftCardPlayed.setIcon(new ImageIcon(getClass().getResource("/CardsWarGame/images/"+left+".png"))); rightCardPlayed.setIcon(new ImageIcon(getClass().getResource("/CardsWarGame/images/"+right+".png"))); if((left)%13 > (right)%13){ //leftPlayerScore.setText(""+(Integer.parseInt(leftPlayerScore.getText())+1)); message.setText(" Точка за левия "); leftCards.add(left); leftCards.add(right); } else if((left)%13 < (right)%13){ //rightPlayerScore.setText(""+(Integer.parseInt(rightPlayerScore.getText())+1)); message.setText(" Точка за десния "); rightCards.add(right); rightCards.add(left); } else{ if(left > right){ //leftPlayerScore.setText(""+(Integer.parseInt(leftPlayerScore.getText())+1)); message.setText(" Точка за левия "); leftCards.add(left); leftCards.add(right); } else{ //rightPlayerScore.setText(""+(Integer.parseInt(rightPlayerScore.getText())+1)); message.setText(" Точка за десния "); rightCards.add(right); rightCards.add(left); } } dealsValue.setText(""+(Integer.parseInt(dealsValue.getText())+1)); leftPlayerScore.setText(""+leftCards.size()); rightPlayerScore.setText(""+rightCards.size()); // При край на играта вече скриваме гърба на картите само на загубилия if(leftCards.size()==0){ leftDeck.setVisible(false); dealButton.setText("Край"); } if(rightCards.size()==0){ rightDeck.setVisible(false); dealButton.setText("Край"); } }
Задача за упражнение: За пълната версия на играта Война ще е нужно кода да се модифицира така, че при равенство картите да се запазят на масата и да се изтеглят нови. Това може да се реализира като текущите карти на масата се натрупват в стек. Би било добро упражнение за комбинация между двете разгледани структури. Реализацията обаче няма да е толкова проста, особено ако се вземе решение да се отчете и малко вероятната, но все пак възможна „патова“ игра (поредица от 26 равни и няма нито един победител).
Добави коментар