* Упражнение за структура от данни 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 равни и няма нито един победител).

Добави коментар