C, PHP, VB, .NET

Дневникът на Филип Петров


* Играта XO с GUI с NetBeans

Публикувано на 11 януари 2016 в раздел УКИ.

В този урок се запознаваме с GridLayout и работим с що-годе елементарни алгоритми за обхождане на масив. Реализираме играта XO с графична среда.

Отначало създайте нов проект в NetBeans и изберете "GridLayout" за основната рамка. На самия layout задайте 3 реда и 3 колони в неговите properties:

xo0

Така направена, рамката ще има нещо като невидима таблица с три реда и три колони. Когато добавяте обекти в рамката, те ще се вмъкват един по един в клетките на тази таблица.

Добавете 9 jLabel обекта в различните клетки. Променете имената им съответно на l1, l2, ... l9. Текстът на всеки етикет да е с голям шрифт и да е точка ".":

xo1

В началото добавете следните два imports:

import javax.swing.JLabel;
import javax.swing.JOptionPane;

JOptionPane ще ни е нужен когато извеждаме диалогов прозорец при победа на един от двамата играчи. JLabel ще ни трябва за временна променлива (ще видите къде по-надолу.)

След това добавете следните три статични променливи в класа:

private static boolean xTurn = true;
private static char board[][] = new char[3][3];
private static boolean gameFinished = false;

Чрез първата ще указваме кой играч е на ход. Ако xTurn е true, значи X е на ход. Ако e false, значи O е на ход. Board е масив, в който ще записваме ходовете на играчите. Той е двумерен и има 3 реда и 3 колони - точно както е в дъската на играта XO. Този масив е с елементи от тип char, т.е. символи. В неговите клетки ще записваме символите "X" или "O", когато играчът направи ход. Променливата gameFinished ще ни казва кога играта е завършила. Ще я използваме, за да можем да прекратим правенето на ход след приключване на играта.

Сега се върнете на Design View и добавете 9 поредни "mouse clicked" събития за всеки един от вашите етикети. Кодът на всеки един от тях ще е еднотипен:

private void l1MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(0,0,lbl);
} 

private void l2MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(0,1,lbl);
} 

private void l3MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(0,2,lbl);
} 

private void l4MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(1,0,lbl);
} 

private void l5MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(1,1,lbl);
} 

private void l6MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(1,2,lbl);
} 

private void l7MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(2,0,lbl);
} 

private void l8MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(2,1,lbl);
} 

private void l9MouseClicked(java.awt.event.MouseEvent evt) { 
 JLabel lbl = (JLabel) evt.getComponent();
 if(!XOGui.gameFinished) this.turn(2,2,lbl);
}

В първия ред ние намираме кой точно етикет е бил натиснат. На втория ред правим ход, но само ако играта все още не е приключила.

Остава да направим метод turn. Създайте го със следния код (поставили сме подробни коментари с обяснение):

private void turn(int row, int column, JLabel toSwitch) {
 // Ако сме цъкнали с мишката на поле, което вече е заето, не правим нищо
 if (!toSwitch.getText().equals(".")){
    return;
 }
 
 // Проверяваме дали на ход е X или O и го записваме в char
 char labelText = XOGui.xTurn ? 'X' : 'O';
 // Променяме текста на етикета с този символ
 toSwitch.setText("" + labelText);
 // Променяме и стойността на символа в масива
 XOGui.board[row][column] = labelText;
 // Проверяваме дали текущия играч е в печеливша позиция
 // За целта сумираме броя на неговите символи в текущия ред
 // текущата колона, по главния диагонал и по обратния диагонал.
 int columnSum = 0, rowSum = 0, diagSum = 0, reverseDiagSum = 0;
 for (int i = 0; i < 3; i++) {
    if (XOGui.board[row][i] == labelText) columnSum++;
    if (XOGui.board[i][column] == labelText) rowSum++;
    if (XOGui.board[i][i] == labelText) diagSum++;
    if (XOGui.board[i][2 - i] == labelText) reverseDiagSum++;
 }
 // Ако някоя от тези суми е 3, имаме печеливша позиция
 if (rowSum == 3 || columnSum == 3 || diagSum == 3 || reverseDiagSum == 3) {
    JOptionPane.showMessageDialog(this, labelText + " WINS");
    XOGui.gameFinished = true;
 }
 // Обръщаме стойността на променливата така, че другия играч да е на ход
 XOGui.xTurn = !XOGui.xTurn;
}

Допълнителна задача 1. Преработете програмата така, че най-долу да има още един ред. В него най-вдясно да има бутон "Нова Игра", който изчиства полето. До него да се показва статистика за това колко пъти X е побеждавал и колко пъти O. Например ето така (забележете, че за последната клетка сме използвали "Box Layout" с ориентиране по вертикала):

xo2

Допълнителна задача 2. Добавете контроли за съхраняване на статистиката във файл и за зареждане на статистика от файл, както е показано на картинката:

xo3

 



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

Адресът на електронната поща няма да се публикува


*