2015-09-06 149 views
0

我正在用java編寫一個簡單的TicTacToe遊戲。 基本實現完成。 Player vs Player是完美無缺的。模擬鼠標點擊板內(JPanel)

但現在,當我實施AI時,我遇到了一個問題。 我已經計算了計算機的移動,但是我無法讓計算機單擊JPanel上的[使用(x,y)座標]位置。

我見過機器人類,但它沒有點擊所需的地方,似乎點擊窗外。

下面是代碼,它借鑑了JPanel中板:

private class Board extends JPanel{ 
     /** 
     * 
     */ 
     private static final long serialVersionUID = 1L; 

     public Board(){ 
      this.setSize(new Dimension(board_width, board_height)); 
      this.setPreferredSize(new Dimension(board_width, board_height)); 
      this.setBackground(new Color(0x84ACFF));    
      this.setOpaque(true); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      //g.setColor(new Color(0xf9d1af)); 
      g.setColor(Color.white); 
      g.drawLine((board_width/3), 0, (board_width/3), board_height); 
      g.drawLine((board_width/3)*2, 0, (board_width/3)*2, board_height); 
      g.drawLine(0, (board_height/3), (board_width), (board_height/3)); 
      g.drawLine(0, (board_height/3)*2, (board_width), (board_height/3)*2); 
      g.finalize(); 
     } 
    } 

而這裏的MouseListener我與JPanel的使用:

@Override 
public void mousePressed(MouseEvent e) { 
    Graphics g = this.getGraphics(); 

    int X = e.getX(); 
    int Y = e.getY(); 

    //JOptionPane.showMessageDialog(null, e.getXOnScreen()+":"+e.getYOnScreen()); 

    int block_x = board_width/3; 
    int block_y = board_height/3; 

    X = X/block_x; 
    Y = Y/block_y; 

    //For array Assignment 
    Click_X = Y; 
    Click_Y = X; 

    //Keep copy of the originals 
    Orig_X = X; 
    Orig_Y = Y; 

    //------------------------------------------ 
    //   Assign to array & Draw 
    //------------------------------------------ 
    if (computer){ 
     if (start.equals("Computer")){ 
      if (game_board[Click_X][Click_Y] != ' ') return; 
      moves++; 
      game_board[Click_X][Click_Y] = Cross; 
      drawCross(((X+1)*block_x)+25, ((Y+1)*block_y)+25, 50, 50, g); 
      dcsn = new Decision(game_board, moves); 
     } 
     else{ 
      if (game_board[Click_X][Click_Y] != ' ') return; 
      moves++; 
      game_board[Click_X][Click_Y] = Nought; 
      drawNought(((X+1)*block_x), ((Y+1)*block_y), 50, 50, g); 
      dcsn = new Decision(game_board, moves); 
     } 
    } 
    else{ 
     if (start.equals("Human")){ 
      if (game_board[Click_X][Click_Y] != ' ') return; 
      moves++; 
      game_board[Click_X][Click_Y] = Cross; 
      drawCross(((X+1)*block_x)+25, ((Y+1)*block_y)+25, 50, 50, g); 
      dcsn = new Decision(game_board, moves); 
     } 
     else{ 
      if (game_board[Click_X][Click_Y] != ' ') return; 
      moves++; 
      game_board[Click_X][Click_Y] = Nought; 
      drawNought(((X+1)*block_x), ((Y+1)*block_y), 50, 50, g); 
      dcsn = new Decision(game_board, moves); 
     } 
    } 

    switch (dcsn.gameOver()){ 
    case "X": 
     JOptionPane.showMessageDialog(null,"X has won!"); 
     break; 
    case "O": 
     JOptionPane.showMessageDialog(null,"O has won!"); 
     break; 
    case "draw": 
     JOptionPane.showMessageDialog(null,"Draw!"); 
     break; 
    case " ": 
     break; 
    } 

    switchTurn(); 
} 

現在我該如何使電腦點擊計算的位置? 任何想法?

這裏是鏈接到完整的源代碼: Download Source

否則很難重現的情況。

+1

1)你爲什麼不只需添加一個MouseListener的每一個細胞?會讓事情變得更容易和更清晰(你不需要機器人類)。 2)請考慮發佈[MCVE](http://stackoverflow.com/help/mcve)(或[SSCCE](http://sscce.org/)),我無法重現您的問題。 3)不應該'Click_X = Y; Click_Y = X;'是'Click_X = X; Click_Y = Y;'? –

+0

你可以創建一個'assignToArrayAndDraw()'方法,你可以通過'mousePressed()'方法或者你的AI調用。 –

+0

@LuxxMiner:不,Click_X = Y是可以的,因爲我需要[(00),(01),(02)]格式的內容,用於存儲十字節/十進制數組。 – Priyabrata

回答

3

我想給你舉例說明如何做到這一點,就像我在評論中所建議的那樣。 (「爲什麼不爲每個單元格添加MouseListener」,「你不需要機器人類」)當然,你不必這樣做,但我認爲它只是更易於編碼&瞭解。現在計算機只是選擇隨機單元,沒有重新啓動/贏/輸,我只是想告訴你這個概念。 我不會用機器人類在這種情況下,程序不應該能夠採取控制光標;)

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.Random; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.border.LineBorder; 

public class TicTacToe { 

    Cell[][] cells = new Cell[3][3]; 
    boolean humanTurn = true; 

    public TicTacToe() { 

     JFrame frame = new JFrame("T I C - T A C - T O E"); 

     JPanel panel = new JPanel(new GridLayout(3, 3)); 
     addCells(panel); 

     frame.add(panel); 

     frame.setSize(600, 600); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

     ActionListener actionListener = new ActionListener() { 

      Random r = new Random(); 

      @Override 
      public void actionPerformed(ActionEvent e) { 

       if (!humanTurn) { 
        // Random cell 
        int x = r.nextInt(3); 
        int y = r.nextInt(3); 
        Cell cell = cells[x][y]; 

        if (!cell.clicked) { 

         // Only the computer runs the gameloop, so false 
         cell.human = false; 
         cell.cross = false; 

         cell.repaint(); 

         // Make sure the panel repaints before setting next 
         // booleans 
         EventQueue.invokeLater(new Runnable() { 
          public void run() { 
           humanTurn = true; 
           cell.clicked = true; 
          } 
         }); 
        } 
       } 

      } 
     }; 
     Timer gameloop = new Timer(10, actionListener); 
     gameloop.start(); 

    } 

    private void addCells(JPanel panel) { 

     for (int y = 0; y < 3; y++) { 
      for (int x = 0; x < 3; x++) { 

       Cell cell = new Cell(); 
       cell.setBorder(new LineBorder(Color.BLACK)); 

       cells[x][y] = cell; 

       panel.add(cell); 

      } 
     } 
    } 

    public static void main(String[] args) { 

     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       new TicTacToe(); 
      } 
     }); 

    } 

    class Cell extends JPanel implements MouseListener { 

     boolean clicked = false; 
     boolean human = true; 
     boolean cross = false; 

     public Cell() { 

      addMouseListener(this); 

     } 

     @Override 
     public void paintComponent(Graphics g) { 

      super.paintComponent(g); 

      Graphics2D gg = (Graphics2D) g; 

      // Makes drawing smooth 
      gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

      // Drawing blue cross (player) 
      if (human && cross) { 
       gg.setColor(Color.BLUE); 
       gg.drawLine(20, 20, getWidth() - 20, getHeight() - 20); 
       gg.drawLine(getWidth() - 20, 20, 20, getHeight() - 20); 
      } 

      // Drawing red circle (computer) 
      else if (!human && !cross) { 
       gg.setColor(Color.RED); 
       gg.drawOval(10, 10, getWidth() - 20, getHeight() - 20); 
      } 

     } 

     @Override 
     public void mouseClicked(MouseEvent arg0) { 

      if (humanTurn && !clicked) { 

       // Only human can click on the panel, so true 
       human = true; 
       cross = true; 

       repaint(); 

       // Make sure the panel repaints before setting next booleans 
       EventQueue.invokeLater(new Runnable() { 
        public void run() { 
         humanTurn = false; 
         clicked = true; 
        } 
       }); 

      } 

     } 

     @Override 
     public void mouseEntered(MouseEvent arg0) { 

     } 

     @Override 
     public void mouseExited(MouseEvent arg0) { 

     } 

     @Override 
     public void mousePressed(MouseEvent arg0) { 

     } 

     @Override 
     public void mouseReleased(MouseEvent arg0) { 

     } 

    } 

}