有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何为TictaToe游戏创建HashMap

我正在创建一个Tictatcoe游戏,有两个棋盘,用户只能玩一个。如果用户单击网格1上的单元格[2][3],将在网格1和网格2上的单元格[2][3]上绘制令牌。我在考虑使用HashMap为每个单元格分配索引。与单元格[2][3]和单元格[2][3]一样,每个单元格都将被分配到索引9。我该如何实现这是我的代码?我会用Hashmap来做我想做的事情吗?我不熟悉这个概念,所以我可能只是想得太多了。 注:单元格[]是网格1的单元格,单元格[]是网格2的单元格。单元格[][]中有随机索引,因此可以将其随机分配给电路板

编辑:如果我想链接单元格(2)(3)和单元格(2)(3),我会在初始化hashmap时将整数改为单元格。然后我会做HMap。把(单元格[2][3],单元格[2][3])放对了吗

代码:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.border.LineBorder;
import java.util.Random;
import java.util.HashMap;
public class Bull extends JFrame{
   private char currentPlayer = ' ';
   // Creates array of cells called Cell[][] cell
   private Cell[][] cell = new Cell[3][3];
   // Creates array of cells called Sale[][] cells
   private Cells[][] cells = new Cells[3][3];
   // Creates a boolean array
   private boolean t[][] = new boolean[3][3];
   // Creates index array
   private int z[] = new int[8];
   //Initializes Random
   Random rand = new Random();
   // Initializes variables which will be used to create random ints
   int f;
   int g;
   // Initializes JlblStatus
   private JLabel jlblStatus = new JLabel(" ");
   private JLabel jlblIndex = new JLabel(" ");
   // Method that builds the JFrame and JPanels
   public Bull(){
      // Do I change Integer to array?
      HashMap<Integer, Integer> HMap = new HashMap<Integer, Integer>();
      // Title of the JFrame
      JFrame frame = new JFrame("Shadow Tic Tac Toe Game");
      // Makes the JFrame full screen
      frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
      // If x button is clicked than the JFrame closes
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      // Initializes JPanel1
      JPanel panel1 = new JPanel();
      // Initializes JPanel2
      JPanel panel2 = new JPanel();

      // Adds panel1 which will hold the first TicTacToe game.
      panel1.setLayout(new GridLayout(3,3,0,0));
      for(int d = 0; d < 3; d++){
         for(int c = 0; c < 3; c++){
            panel1.add(cell[d][c] = new Cell());
            // Sets size of the cells in JPanel1
            cell[d][c].setPreferredSize(new Dimension(250,250));
         }
      }




      panel2.setLayout(new GridLayout(3,3,0,0));
      int n = 0;
      while(n < 9){
      f=rand.nextInt(3);
      g=rand.nextInt(3);
      while(t[f][g] == false){
         t[f][g] = true;
         panel2.add(cells[f][g] = new Cells());
         cells[f][g].setPreferredSize(new Dimension(250,250));
         System.out.println(f);
         System.out.println("\t" + g);
         n++;

        }
       }








      // Adds Panel1 to the JFrame
      frame.add(panel1, BorderLayout.WEST);
      // Adds Panel2 to the JFrame
      frame.add(panel2, BorderLayout.EAST);
      // Updates the status of the game here (win/lose/draw/whose turn it is
      frame.add(jlblStatus, BorderLayout.SOUTH);
      // Sets size of the message area at the bottom of the frame
      jlblStatus.setPreferredSize(new Dimension(100,100));
      // Shows the Instructions of the game
      Instructions();
      // Calls method Chose() which allows the player to chose which token they will play as
      Chose();
      frame.pack();
      // Sets it so the JFrame is visible to the user
      frame.setVisible(true);
   }


   // Method that creates the Instructions for the game. Will be shown to the user prior to the user picking his token
   public void Instructions(){
      JOptionPane.showMessageDialog(null,"INSTRUCTIONS" + "\nThis game is called a 'Shadow Tic Tac Toe Game'. In this game there will be two Tic Tac Toe game boards, though only one is playable. \nBut you can win on either board. Lets say you place your token on the center tile at cell(2,3). \nAn X will be drawn on that spot on board 1 and on a randomized spot on the second game board at cell(2,3). \nYou will be able to see the cell indexes before you click on a cell so you can form a strategy");
   }
   // Method that lets the user chose his/her token
   public void Chose(){
      int f = 2;
      // While f == 2 the loop will run
      while(f == 2){
         String input = JOptionPane.showInputDialog("CHOSE" + "\nPlease select your token. \nPress 1 for X and 2 for O.");
         // Reads in the user input. Input put into a variable called pawn
         int pawn = Integer.parseInt(input);
         // If user input 1 his/her token will be X. F will equal 3 so the loop does not run again
         if(input.equals("1")){
            currentPlayer = 'X';
            f = 3;
         // If user input 2 his/her token will be O. F will equal 3 so the loop does not run again
         }else if(input.equals("2")){
            currentPlayer = 'O';
            f = 3;
         // If user does not enter in either a 1 or 2 an error message will appear. f wil equal 2 so the loop runs again and asks the user to chose his/her token again
         }else{
            JOptionPane.showMessageDialog(null,"ERROR INVALID RESPONSE");
            f = 2;
      }
     }
   }
   public class Cells extends JPanel{
      private char tok = ' ';
      public Cells(){
         // Sets the border for the cells to the color black
         setBorder(new LineBorder(Color.black,1));
      }
      public void setTok(char d){
         tok = d;
         repaint();
      }
      public char getTok(){
         return tok;
      }
      protected void Paint(Graphics g){
         super.paint(g);

         if(tok == 'X'){
            g.drawLine(10,10,getWidth() - 10, getHeight()-10);
            g.drawLine(getWidth()-10,10,10,getHeight()-10);
         }else if (tok == 'O'){
            g.drawOval(10,10,getWidth()-20, getHeight()-20);
         }
      }
   }
    public class Cell extends JPanel{
      private char token = ' ';
      public void setToken(char c){
         token = c;
         repaint();
      }
      public char getToken(){
         return token;
      }
      public Cell(){ 
         // Sets the border for the cells to the color black
         setBorder(new LineBorder(Color.black, 1));
         addMouseListener(new MyMouseListener());
      }
       protected void paintComponent(Graphics g) {
         super.paintComponent(g);

         if (token == 'X') {
           g.drawLine(10,10, getWidth() - 10, getHeight() - 10);
           g.drawLine(getWidth() - 10,10,10, getHeight() - 10);
         }
         else if (token == 'O') {
           g.drawOval(10, 10, getWidth() - 20, getHeight() - 20);
         }
      } 
      private class MyMouseListener extends MouseAdapter{
         public void mouseClicked(MouseEvent e){
        // If cell is empty and game is not over
        if (token == ' ' && currentPlayer != ' ') {
          setToken(currentPlayer); // Set token in the cell
          for(int d = 0; d < 3; d++){
            for(int c = 0; c < 3; c++){
               if(cell[d][c].getToken() == 'X'){
                  cells[d][c].setTok('X');
               }else if(cell[d][c].getToken() == 'O'){
                  cells[d][c].setTok('O');
               }else if(cell[d][c].getToken() == ' '){
                  cells[d][c].setTok(' ');
               }
            }
          }
          //setTok(currentPlayer); 
               if(Won(currentPlayer)){
                  jlblStatus.setText("The game is over! " + currentPlayer + " won the game! Congragulations " + currentPlayer + " !");
                  currentPlayer = ' ';
               }else if(Full()){
                  jlblStatus.setText("The game is over, it ends in a draw!");
                  currentPlayer = ' ';
               }else{
                   if(currentPlayer == 'X'){
                     currentPlayer = 'O';
                   }else{
                     currentPlayer = 'X';
                   }

                  jlblStatus.setText("It is " + currentPlayer + " 's turn");  
               }

             }
         }
      }  
   }

   public boolean Full(){
      for(int d = 0; d < 3; d++)
         for(int c = 0; c < 3; c++)
            if(cell[d][c].getToken() == ' ')
               return false;
            return true;

    }

   public boolean Won(char token){
      for(int d = 0; d < 3; d++){
         if(cell[d][0].getToken() == token && cell[d][1].getToken() == token && cell[d][2].getToken() == token){
            return true;
         }
      }
      for(int c = 0; c < 3; c++){
         if(cell[0][c].getToken() == token && cell[1][c].getToken() == token && cell[2][c].getToken() == token){
            return true;
         }
       }
      if(cell[0][0].getToken() == token && cell[1][1].getToken() == token && cell[2][2].getToken() == token){
         return true;
      }
      if(cell[0][2].getToken() == token && cell[1][1].getToken() == token && cell[2][0].getToken() == token){
         return true;
      }
      return false;
   }
     public static void main(String [] args){
      new Bull();
   }
}

共 (1) 个答案

  1. # 1 楼答案

    所以本质上你想把一个网格上的一个单元格(玩家可以玩)映射到另一个网格上的某个单元格(阴影网格)

    可以使用另一个2D数组来实现这一点,该数组存储单元映射到另一个网格中的索引,但需要返回一个包含x和y坐标的点对象。但这种方法有点烦人,而且有其局限性

    如果你想用一个网格中的一个PointHashMap<Point, Point>替换另一个网格中的Point,那么你必须重写hashCode()equals(){}并执行如下操作:

    HashMap<Point, Point> mapPointToPoint = new HashMap<>();
    
    // (0,0) maps to shadow grid (1,2)
    mapPointToPoint.put(new Point(0,0), new Point(1,2));
    mapPointToPoint.put(new Point(0,1), new Point(2,1));
    // ... more mappings for all the cells
    
    // to get 
    Point pointInPlayableGrid = new Point(0,0);
    Point pointInShadowGrid = mapPointToPoint.get(pointInPlayableGrid);
    // pointInShadowGrid == (1,2) since that's what it was mapped to
    

    然而,如果你想有多个阴影网格,那么你需要有一个从可播放网格中的点到每个阴影网格中的点的贴图

    因此,既然已经有了Cell类,为什么不让每个Cell存储它映射到的所有单元格的List<Cell>。这也是非常灵活的,因为你甚至可以将一个可播放的Cell映射到一个阴影网格中的多个单元格,在可播放的Cell上悬停,你可以浏览它映射到的阴影Cells列表,并将其高亮显示

    public class Cell extends JPanel{
        private Cell shadowCell;
        public void setCellThisMapsTo(Cell otherCell){ this.shadowCell = otherCell; }
        public Cell getCellThisMapsTo(){ return shadowCell; }
        // ... all the other stuff
    }
    
    // ... wherever you initialize the playable and shadow grid
    // get a list of the shadow Cells, randomized order
    Cell[][] shadowGrid; // however you init this
    Cell[][] playableGrid; // however you init this
    
    LinkedList<Cell> shadowCells = new LinkedList<>();
    for(int x = 0; x < 3; x++){
        for(int y = 0; y < 3; y++){
            shadowCells.add(shadowGrid[x][y]);
        }
    }
    Collections.shuffle(shadowCells);
    
    for(int x = 0; x < 3; x++){
        for(int y = 0; y < 3; y++){
            Cell playableCell = playableGrid[x][y];
            Cell shadowCell = shadowCells.removeFirst();
            playableCell.setCellThisMapsTo(shadowCell );
        }
    }
    
    // Now all the playable cells map to a random shadow cell
    Cell playableCell = playableGrid[0][0];
    Cell shadowCell = playableCell.getCellThisMapsTo();
    

    阴影Cells不会映射到任何其他单元格,因此shadowCell.getCellThisMapsTo()将返回null。但这种方法可以很容易地将可播放单元映射到阴影单元并跟踪它们,甚至不需要使用HashMap或跟踪PointPoint的映射


    以下是我对Point的定义。如果您想根据其值(而不是对象引用)将某个内容放入哈希映射中,那么重写hashCode()equals()是很重要的:

    class Point {
        public final int x;
        public final int y;
        public Point(int x, int y){
            this.x = x;
            this.y = y;
        }
    
        // !!! OVERRIDE hashCode() and equals() so  you can use this properly in a HashMap !!!
        @Override
        public int hashCode() {
            int hash = 7;
            hash = 71 * hash + this.x;
            hash = 71 * hash + this.y;
            return hash;
        }
    
         @Override
        public int equals(Object o) {
            if (obj == null)
                return false;
            if (this == obj)
                return true;
            if (getClass() != o.getClass())
                return false;
            Point p = (Point) o;
            return this.x == p.x && this.y == p.y;
        }
    }