Miért bugos ez a JFrame tic tac toe?
Van itt valaki, aki nagyon unatkozik és segítene kijavítani, mert nekem nagyon nem megy. Számomra véletlenszerűnek tűnően időként nem vállt át az "X" "O"-ra és fordítva.
Úgy vettem észre,hogyha a detectWinner() metódust kilövöm nincs probléma. Az ugyanebben a metódusban meghivott cleanButtonsAfterWinAndAddListener() metódus kilövése után nem szűnt meg a probléma, szóval szerintem az az feletti rész a ludas, de nem értem miért.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class game extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
//creating variables
JButton[] buttons= new JButton[9];
JPanel p=new JPanel(new GridBagLayout());
GridBagConstraints c= new GridBagConstraints();
JButton b1= new JButton("X won:");
JButton b2= new JButton("O won:");
JButton b3= new JButton("Reset");
int gx=0, gy=0;
boolean win=false;
String turn="X";
int XWonNumber=0,
OWonNumber=0;
JMenuBar bar= new JMenuBar();
JMenu tutorial = new JMenu("tutorial");
public static void main(String[] args) {
new game();
}
game() {
super("Tic tac toe game");
addElements();
//basic JFrame stuff
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800,600);
setResizable(false);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
//who won
void detectWinner() {
String s1=buttons[0].getText();
String s2=buttons[1].getText();
String s3=buttons[2].getText();
String s4=buttons[3].getText();
String s5=buttons[4].getText();
String s6=buttons[5].getText();
String s7=buttons[6].getText();
String s8=buttons[7].getText();
String s9=buttons[8].getText();
if (s1.equals("X") && s2.equals("X") && s3.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s4.equals("X") && s5.equals("X") && s6.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s7.equals("X") && s8.equals("X") && s9.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s1.equals("X") && s4.equals("X") && s7.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s2.equals("X") && s5.equals("X") && s8.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s3.equals("X") && s6.equals("X") && s9.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s1.equals("X") && s5.equals("X") && s9.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s3.equals("X") && s5.equals("X") && s7.equals("X")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
XWonNumber++;
win=true;
gameScore();
}
if (s1.equals("O") && s2.equals("O") && s3.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
if (s4.equals("O") && s5.equals("O") && s6.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
if (s7.equals("O") && s8.equals("O") && s9.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
if (s1.equals("O") && s4.equals("O") && s9.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
if (s2.equals("O") && s5.equals("O") && s8.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
if (s3.equals("O") && s6.equals("O") && s9.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
if (s1.equals("O") && s5.equals("O") && s9.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
if (s3.equals("O") && s5.equals("O") && s7.equals("O")) {
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
OWonNumber++;
win=true;
gameScore();
}
cleanButtonsAfterWinAndAddListener();
}
//actionlistener to all the buttons
@Override
public void actionPerformed(ActionEvent e) {
for (JButton jb : buttons) {
if (e.getSource()==jb) {
jb.setText(turn);
jb.setFont(new Font("Arial", Font.PLAIN, 85));
if(turn=="X") jb.setForeground(Color.RED);
if(turn=="O") jb.setForeground(Color.BLUE);
jb.removeActionListener(this);
detectWinner();
changeTurn();
}
}
//reseting everything
if (e.getSource()==b3) {
turn="X";
for (JButton jb : buttons) {
jb.setText("");
jb.addActionListener(this);
}
b1.setText("X won: ");
b2.setText("O won: ");
XWonNumber=0;
OWonNumber=0;
}
}
//change turn
void changeTurn() {
if (turn=="X") turn="O";
else if (turn=="O") turn="X";
}
void addElements() {
//create JButtons and add them
for (int k=0; k<9; k++ ) {
buttons[k]= new JButton();
buttons[k].setText("");
buttons[k].addActionListener(this);
c.weightx=0.5;
c.weighty=0.5;
c.fill=GridBagConstraints.BOTH;
c.gridx=gx;
c.gridy=gy;
buttons[k].setPreferredSize(new Dimension(200, 200));
p.add(buttons[k], c);
gx++;
if(gx==3) {
gy++;
gx=0;
}
}
c.insets = new Insets(0,10,0,0);
c.gridx=3;
c.gridy=0;
b1.setHorizontalAlignment(SwingConstants.LEFT);
b1.setPreferredSize(new Dimension(200, 200));
b1.setFont(new Font("Arial", Font.PLAIN, 36));
p.add(b1,c);
c.gridx=3;
c.gridy=1;
b2.setHorizontalAlignment(SwingConstants.LEFT);
b2.setFont(new Font("Arial", Font.PLAIN, 36));
b2.setPreferredSize(new Dimension(200, 200));
p.add(b2,c);
c.gridx=3;
c.gridy=2;
b3.setFont(new Font("Arial", Font.PLAIN, 36));
b3.setPreferredSize(new Dimension(200, 200));
p.add(b3,c);
b3.addActionListener(this);
b1.setEnabled(false);
b2.setEnabled(false);
setJMenuBar(bar);
bar.add(tutorial);
add(p);
}
void gameScore() {
b1.setText("X won: "+XWonNumber);
b2.setText("O won: "+OWonNumber);
}
void cleanButtonsAfterWinAndAddListener() {
if (win) {
for (JButton button : buttons) {
button.setText("");
button.addActionListener(this);
}
turn="X";
win=false;
}
}
}
Csak végig futottam , de ha nem vált akkor ő void changeTurn() {
if (turn=="X") turn="O";
else if (turn=="O") turn="X";
}
nem kerül meghívásra több mint valószínű (arról most tekintsük el , hogy feleslegesen vizsgálsz hiszen ha nem X a turn akkor O :"D A detectwinnered is egy bughalmaz forrás. Miért kéred le mindig mi van a textbe ? Nem lenne egyszerűbb egy string tömbbe tárolni és onnan visszakérni illetve csak az aktuális turnbe lévőre vizsgálni ? tehát x körébe hiába nézed az o-kat abba a körbe tuti nem nyerhettek ezzel meg is felezed a hibaforrások okait etcetc. Majd bemásolom eclipsebe és ránézek , de az ilyenekkel valamit csinálhatnál mert sokkal nehezebb átlátni és felesleges vizsgálatok/kódduplikáció.
Uhhhh ettől kompaktabb megoldás nem létezik?
Ezeket miért nem rakod be egy-egy tömbbe?
String s1=buttons[0].getText();
String s2=buttons[1].getText();
String s3=buttons[2].getText();
String s4=buttons[3].getText();
String s5=buttons[4].getText();
String s6=buttons[5].getText();
String s7=buttons[6].getText();
String s8=buttons[7].getText();
String s9=buttons[8].getText();
Közben átírtam. Remélem így már átláthatóbb, hatékonyabb.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class game extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
//creating variables
JPanel p=new JPanel(new GridBagLayout());
JButton[] buttons= new JButton[9];
JButton b1= new JButton("X won:");
JButton b2= new JButton("O won:");
JButton b3= new JButton("Reset");
JMenuBar bar= new JMenuBar();
JMenu tutorial = new JMenu("tutorial");
GridBagConstraints c= new GridBagConstraints();
int gx=0, gy=0;
boolean win=false;
String turn="X";
int XWonNumber=0,
OWonNumber=0;
String s[]= new String[9];
public static void main(String[] args) {
new game();
}
game() {
super("Tic tac toe game");
addElements();
//basic JFrame stuff
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800,600);
setResizable(false);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
void detectWinner() {
for (int k=0; k<9; k++) {
s[k]=buttons[k].getText();
}
if (s[0].equals(turn) && s[1].equals(turn) && s[2].equals(turn)) {
win=true;
}
if (s[3].equals(turn) && s[4].equals(turn) && s[5].equals(turn)) {
win=true;
}
if (s[6].equals(turn) && s[7].equals(turn) && s[8].equals(turn)) {
win=true;
}
if (s[0].equals(turn) && s[3].equals(turn) && s[6].equals(turn)) {
win=true;
}
if (s[1].equals(turn) && s[4].equals(turn) && s[7].equals(turn)) {
win=true;
}
if (s[2].equals(turn) && s[5].equals(turn) && s[8].equals(turn)) {
win=true;
}
if (s[0].equals(turn) && s[4].equals(turn) && s[8].equals(turn)) {
win=true;
}
if (s[2].equals(turn) && s[4].equals(turn) && s[6].equals(turn)) {
win=true;
}
cleanButtonsAfterWinAndAddListener();
}
//actionlistener to all the buttons
@Override
public void actionPerformed(ActionEvent e) {
for (JButton jb : buttons) {
if (e.getSource()==jb) {
jb.setText(turn);
jb.setFont(new Font("Arial", Font.PLAIN, 85));
if(turn=="X") jb.setForeground(Color.RED);
else jb.setForeground(Color.BLUE);
jb.removeActionListener(this);
detectWinner();
changeTurn();
}
}
//reseting everything
if (e.getSource()==b3) {
turn="X";
for (JButton jb : buttons) {
jb.setText("");
jb.addActionListener(this);
}
b1.setText("X won: ");
b2.setText("O won: ");
XWonNumber=0;
OWonNumber=0;
}
}
void changeTurn() {
if (turn=="X") turn="O";
else turn="X";
}
void addElements() {
for (int k=0; k<9; k++ ) {
buttons[k]= new JButton();
buttons[k].setText("");
buttons[k].addActionListener(this);
c.weightx=0.5;
c.weighty=0.5;
c.fill=GridBagConstraints.BOTH;
c.gridx=gx;
c.gridy=gy;
buttons[k].setPreferredSize(new Dimension(200, 200));
p.add(buttons[k], c);
gx++;
if(gx==3) {
gy++;
gx=0;
}
}
c.insets = new Insets(0,10,0,0);
c.gridx=3;
c.gridy=0;
b1.setHorizontalAlignment(SwingConstants.LEFT);
b1.setPreferredSize(new Dimension(200, 200));
b1.setFont(new Font("Arial", Font.PLAIN, 36));
p.add(b1,c);
c.gridx=3;
c.gridy=1;
b2.setHorizontalAlignment(SwingConstants.LEFT);
b2.setFont(new Font("Arial", Font.PLAIN, 36));
b2.setPreferredSize(new Dimension(200, 200));
p.add(b2,c);
c.gridx=3;
c.gridy=2;
b3.setFont(new Font("Arial", Font.PLAIN, 36));
b3.setPreferredSize(new Dimension(200, 200));
p.add(b3,c);
b3.addActionListener(this);
b1.setEnabled(false);
b2.setEnabled(false);
setJMenuBar(bar);
bar.add(tutorial);
add(p);
}
void gameScore() {
b1.setText("X won: "+XWonNumber);
b2.setText("O won: "+OWonNumber);
}
void cleanButtonsAfterWinAndAddListener() {
if (win) {
if (turn=="X") XWonNumber++;
else OWonNumber++;
gameScore();
JOptionPane.showMessageDialog(null, "the winner is: "+turn, "Result", JOptionPane.INFORMATION_MESSAGE);
for (JButton button : buttons) {
button.setText("");
button.addActionListener(this);
}
turn="X";
win=false;
}
}
}
Nem. Egyáltalán nem átláthatóbb.
- Először is osztály nevet nem kezdünk kis betűvel.
- A SOLID elveket össze vissza megsérted. Pl: 'S' mint single responsiblity: Most a 'Game' osztályod egy megjelenítésért felelős Jframe, egy eseményéket feldolgozo ActionListener vagy egy játékot irányító üzleti logikai réteg akar lenni? El kellene dönteni, mert mind három bizony nem lehet.
- serialVersionUID? Minek ez? Tudod egyáltalán mire való, vagy csak esztelenül hagytad, hogy valami oda generálja neked?
- Mik ezek a 'p', 'b1' meg 's' és a többi nevű változók? Normális neveket kellene adni, amik kifjezik, hogy mire használod őket.
- Mi ez a s[0], s[1]...vackok? Ciklusról hallottál már?
- Az actionPerformed metódusod miért egy kilométer hosszú? Egy metódus = 'single-level-of-abstraction', de itt ez csinál mindent és mindent IS.
- Hasonlóan a 'cleanButtonsAfterWinAndAddListener' metódus is tőbb dolgot csinál mint kellene. Mellesleg minek adod hozzá mégegyszer actionListenerként a gombokhoz az osztályt, amit már hozzáadtál egyszer?
- 'if (e.getSource()==b3)' meg 'if(turn=="X")' WTF. Ilyen összehasonlítást nem csinálunk. equals metódus?
- A gombokhoz miért adsz hozzá egy JFramet ActionListener-ként? 'jb.addActionListener(this)'? WTF?
- 'for (int k=0; k<9; k++)' miért 'k' a ciklus változó? Haragszol valamiért a standard 'i' betűre?
az string esetén lévő == most itt kivételesen működik mivel az "X" bekerül a stringpoolba és onnantól kezdve azt fogja előszedni és azt rakja bele mindig btw erről tényleg le kellene szokni ez így vak véletlen :) :D . Sok a bullshit és a több dolgot végző metódus. A külalak gány , de hát ez a legkisebb probléma. A vizsgálatot egy if-el meglehet oldani a vizsgálatot nem kell 8-9-et írni || operátor ha meg túl hosszú kiszervezed őket külön metódusba és nem fog zavarni.Mágikus változók helyett jobb ha kitalálsz valami rendes nevet. A gombok kezelése sem az igazi nem teljesen így kellene, de amúgy működőképesnek tűnik viszont a problémád egy olyan inkonzisztens állapot okozza amibe bele lököd magad a túl sok felesleges vagy nem jól használt dologgal. Őszintén hamarabb megírok egyet tisztán mintsem megtaláljam konkrétan mi a hiba.
Az ilyen serialVersionUID már csak hab a tortán a teljesen felesleges dolgokból. De hát hajrá van rajta mit javítani majd ha letisztulnak a dolgok akkor rájössz mennyire rossz a dolgokhoz a megközelítésed.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!