我如何为Tic Tac Toe游戏创建HashMap

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我如何为Tic Tac Toe游戏创建HashMap相关的知识,希望对你有一定的参考价值。

我正在创建一个有2个板的TicTacToe游戏,只有一个可以玩用户。如果用户点击网格1上的单元格[2] [3],将在网格1和网格2上的单元格[2] [3]上绘制一个标记。我正在考虑使用HashMap为每个单元格分配索引。像单元格[2] [3]和单元格[2] [3]将分别指定为索引9.我将如何实现这是我的代码?我甚至会使用Hashmap来做我想做的事情吗?我不熟悉这个概念所以我可能只是在思考这个问题。注意:Cell [] []是网格1的单元格,Cells [] []是网格2. Cells [] []中有随机索引,因此可以随机分配给板。

编辑:如果我想链接单元格(2)(3)和单元格(2)(3)我会在初始化hashmap时将整数更改为Cell。然后我会做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("	" + 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" + "
This 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. 
But you can win on either board. Lets say you place your token on the center tile at cell(2,3). 
An X will be drawn on that spot on board 1 and on a randomized spot on the second game board at cell(2,3). 
You 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" + "
Please select your token. 
Press 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();
   }
}
答案

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

您可以使用另一个2D数组来执行此操作,该数组存储单元格在其他网格中映射到的索引,但您需要返回包含x和y坐标的点对象。但是这种方法很难跟踪并且有其局限性。

如果你想在一个网格中使用一个HashMap<Point, Point>Point到另一个网格中的Point,那么你必须覆盖hashCode()equals()Point并做这样的事情:

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,也不必跟踪Points映射到Points。


这是我对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;
    }
}

以上是关于我如何为Tic Tac Toe游戏创建HashMap的主要内容,如果未能解决你的问题,请参考以下文章

text Tic-Tac-Toe游戏w / Minimax算法

java 一个类似于tic tac toe的小型Java游戏

python3的tic tac toe

Tic-tac-toe使用python tkinter

我上一次if语句在tic tac toe中检查抽奖有什么问题?我可以使用循环吗?

python tic tac toe记分牌没有更新[关闭]