# Minimax Algorithm in Game Theory | Set 5 (Zobrist Hashing)

Previous posts on this topic : Minimax Algorithm in Game Theory, Evaluation Function in Game Theory, Tic-Tac-Toe AI â€“ Finding optimal move, Alpha-Beta Pruning.
Zobrist Hashing is a hashing function that is widely used in 2 player board games. It is the most common hashing function used in transposition table. Transposition tables basically store the evaluated values of previous board states, so that if they are encountered again we simply retrieve the stored value from the transposition table. We will be covering transposition tables in a later article. In this article we shall take the example of chess board and implement a hashing function for that.

#### Pseudocode :

// A matrix with random numbers initialized once
Table[#ofBoardCells][#ofPieces]

// Returns Zobrist hash function for current conf-
// iguration of board.
function findhash(board):
hash = 0
for each cell on the board :
if cell is not empty :
piece = board[cell]
hash ^= table[cell][piece]
return hash

Explanation :

The idea behind Zobrist Hashing is that for a given board state, if there is a piece on a given cell, we use the random number of that piece from the corresponding cell in the table.
If more bits are there in the random number the lesser chance of a hash collision. Therefore 64 bit numbers are commonly used as the standard and it is highly unlikely for a hash collision to occur with such large numbers. The table has to be initialized only once during the programs execution.
Also the reason why Zobrist Hashing is widely used in board games is because when a player makes a move, it is not necessary to recalculate the hash value from scratch. Due to the nature of XOR operation we can simply use few XOR operations to recalculate the hash value.

#### Implementation :

We shall try to find a hash value for the given board configuration.

## CPP

 // A program to illustrate Zobrist Hashing Algorithm #include using namespace std;   unsigned long long int ZobristTable[8][8][12]; mt19937 mt(01234567);   // Generates a Random number from 0 to 2^64-1 unsigned long long int randomInt() {     uniform_int_distribution                                  dist(0, UINT64_MAX);     return dist(mt); }   // This function associates each piece with // a number int indexOf(char piece) {     if (piece=='P')         return 0;     if (piece=='N')         return 1;     if (piece=='B')         return 2;     if (piece=='R')         return 3;     if (piece=='Q')         return 4;     if (piece=='K')         return 5;     if (piece=='p')         return 6;     if (piece=='n')         return 7;     if (piece=='b')         return 8;     if (piece=='r')         return 9;     if (piece=='q')         return 10;     if (piece=='k')         return 11;     else         return -1; }   // Initializes the table void initTable() {     for (int i = 0; i<8; i++)       for (int j = 0; j<8; j++)         for (int k = 0; k<12; k++)           ZobristTable[i][j][k] = randomInt(); }   // Computes the hash value of a given board unsigned long long int computeHash(char board[8][9]) {     unsigned long long int h = 0;     for (int i = 0; i<8; i++)     {         for (int j = 0; j<8; j++)         {             if (board[i][j]!='-')             {                 int piece = indexOf(board[i][j]);                 h ^= ZobristTable[i][j][piece];             }         }     }     return h; }   // Main Function int main() {     // Uppercase letters are white pieces     // Lowercase letters are black pieces     char board[8][9] =     {         "---K----",         "-R----Q-",         "--------",         "-P----p-",         "-----p--",         "--------",         "p---b--q",         "----n--k"     };       initTable();       unsigned long long int hashValue = computeHash(board);     printf("The hash value is     : %llu\n", hashValue);       //Move the white king to the left     char piece = board[0][3];       board[0][3] = '-';     hashValue ^= ZobristTable[0][3][indexOf(piece)];       board[0][2] = piece;     hashValue ^= ZobristTable[0][2][indexOf(piece)];         printf("The new hash value is : %llu\n", hashValue);       // Undo the white king move     piece = board[0][2];       board[0][2] = '-';     hashValue ^= ZobristTable[0][2][indexOf(piece)];       board[0][3] = piece;     hashValue ^= ZobristTable[0][3][indexOf(piece)];       printf("The old hash value is : %llu\n", hashValue);       return 0; }

## Java

 // A Java program to illustrate Zobrist Hashing Algorithm   import java.util.*;   public class GFG {     public static List>> ZobristTable = new ArrayList<>();     // mt19937 mt(01234567);   public static void initialise() {     for (int i = 0; i < 8; i++) {       ZobristTable.add(new ArrayList<>());       for (int j = 0; j < 8; j++) {         ZobristTable.get(i).add(new ArrayList<>());         for (int k = 0; k < 12; k++) {           ZobristTable.get(i).get(j).add(0);         }       }     }   }   // Generates a Random number from 0 to 2^64-1   public static long randomLong() {     long min = 0L;     long max = (long) Math.pow(2, 64);     Random rnd = new Random();     return rnd.nextLong() * (max - min) + min;   }     // This function associates each piece with a number   public static int indexOf(char piece)   {     if (piece=='P')       return 0;     if (piece=='N')       return 1;     if (piece=='B')       return 2;     if (piece=='R')       return 3;     if (piece=='Q')       return 4;     if (piece=='K')       return 5;     if (piece=='p')       return 6;     if (piece=='n')       return 7;     if (piece=='b')       return 8;     if (piece=='r')       return 9;     if (piece=='q')       return 10;     if (piece=='k')       return 11;     else       return -1;   }     // Initializes the table   public static void initTable() {     for (int i = 0; i < 8; i++) {       for (int j = 0; j < 8; j++) {         for (int k = 0; k < 12; k++) {           Random rnd = new Random();           ZobristTable.get(i).get(j).set(k, (int) randomLong());         }       }     }   }     // Computes the hash value of a given board   public static int computeHash(List> board) {     int h = 0;     for (int i = 0; i < 8; i++) {       for (int j = 0; j < 8; j++) {         if (board.get(i).get(j) != '-') {           int piece = indexOf(board.get(i).get(j));           h ^= ZobristTable.get(i).get(j).get(piece);         }       }     }     return h;   }     public static void main(String[] args) {     // Main Function     // Uppercase letters are white pieces     // Lowercase letters are black pieces     List> board = new ArrayList<>();     board.add(new ArrayList<>(Arrays.asList('-', '-', '-', 'K', '-', '-', '-', '-')));     board.add(new ArrayList<>(Arrays.asList('-', 'R', '-', '-', '-', '-', 'Q', '-')));     board.add(new ArrayList<>(Arrays.asList('-', '-', '-', 'K', '-', '-', '-', '-')));     board.add(new ArrayList<>(Arrays.asList('-', '-', '-', '-', '-', '-', '-', '-')));     board.add(new ArrayList<>(Arrays.asList('-', 'P', '-', '-', '-', '-', 'p', '-')));     board.add(new ArrayList<>(Arrays.asList('-', '-', '-', '-', '-', 'p', '-', '-')));     board.add(new ArrayList<>(Arrays.asList('-', '-', '-', '-', '-', '-', '-', '-')));     board.add(new ArrayList<>(Arrays.asList('p', '-', '-', '-', 'b', '-', '-', 'q')));     board.add(new ArrayList<>(Arrays.asList('-', '-', '-', '-', 'n', '-', '-', 'k')));         initialise();     initTable();       int hashValue = computeHash(board);     System.out.println("The hash value is     : " + hashValue);       // Move the white king to the left     char piece = board.get(0).get(3);       board.get(0).set(3, '-');       hashValue ^= ZobristTable.get(0).get(3).get(indexOf(piece));       board.get(0).set(2, piece);     hashValue ^= ZobristTable.get(0).get(2).get(indexOf(piece));       System.out.println("The new hash value is     : " + hashValue);       // Undo the white king move     piece = board.get(0).get(2);       board.get(0).set(2, '-');       hashValue ^= ZobristTable.get(0).get(2).get(indexOf(piece));       board.get(0).set(3, piece);     hashValue ^= ZobristTable.get(0).get(3).get(indexOf(piece));       System.out.println("The new hash value is     : " + hashValue);   }   }   // This code is contributed by Vaibhav

## Python3

 # A program to illustrate Zobrist Hashing Algorithm # python code implementation import random   # mt19937 mt(01234567);    # Generates a Random number from 0 to 2^64-1 def randomInt():     min = 0     max = pow(2, 64)     return random.randint(min, max)    # This function associates each piece with # a number def indexOf(piece):     if (piece=='P'):         return 0     elif (piece=='N'):         return 1     elif (piece=='B'):         return 2     elif (piece=='R'):         return 3     elif (piece=='Q'):         return 4     elif (piece=='K'):         return 5     elif (piece=='p'):         return 6     elif (piece=='n'):         return 7     elif (piece=='b'):         return 8     elif (piece=='r'):         return 9     elif (piece=='q'):         return 10     elif (piece=='k'):         return 11     else:         return -1    # Initializes the table def initTable():     # 8x8x12 array     ZobristTable = [[[randomInt() for k in range(12)] for j in range(8)] for i in range(8)]     return ZobristTable    # Computes the hash value of a given board def computeHash(board, ZobristTable):     h = 0     for i in range(8):         for j in range(8):             if (board[i][j] != '-'):                 piece = indexOf(board[i][j])                 h ^= ZobristTable[i][j][piece]     return h    # Main Function # Uppercase letters are white pieces # Lowercase letters are black pieces board = [     "---K----",     "-R----Q-",     "--------",     "-P----p-",     "-----p--",     "--------",     "p---b--q",     "----n--k" ]   ZobristTable = initTable()   hashValue = computeHash(board, ZobristTable) print("The hash value is     : " + str(hashValue))   #Move the white king to the left piece = board[0][3]   board[0] = list(board[0]) board[0][3] = '-' board[0] = ''.join(board[0])   hashValue ^= ZobristTable[0][3][indexOf(piece)]   board[0] = list(board[0]) board[0][2] = piece board[0] = ''.join(board[0]) hashValue ^= ZobristTable[0][2][indexOf(piece)]     print("The new hash value is : " + str(hashValue))   # Undo the white king move piece = board[0][2]   board[0] = list(board[0]) board[0][2] = '-' board[0] = ''.join(board[0])   hashValue ^= ZobristTable[0][2][indexOf(piece)]   board[0] = list(board[0]) board[0][3] = piece board[0] = ''.join(board[0]) hashValue ^= ZobristTable[0][3][indexOf(piece)]   print("The old hash value is : " + str(hashValue))

## C#

 using System; using System.Collections; using System.Collections.Generic; using System.Linq;   // C# program for the above approach // A program to illustrate Zobrist Hashing Algorithm // javascript code implementation     class HelloWorld {       public static List>> ZobristTable = new List>>();       // mt19937 mt(01234567);     public static void initialise(){                       for(int i = 0; i < 8; i++){             ZobristTable.Add(new List>());             for(int j = 0; j < 8; j++){                 ZobristTable[i].Add(new List());                 for(int k = 0; k < 12; k++){                     ZobristTable[i][j].Add(0);                 }             }                    }       }     // Generates a Random number from 0 to 2^64-1     public static int randomInt() {         int min = 0;         int max = (int)Math.Pow(2, 64);         Random rnd = new Random();         return rnd.Next() * (max - min) + min;     }       // This function associates each piece with     // a number     public static int indexOf(char piece)     {         if (piece=='P')             return 0;         if (piece=='N')             return 1;         if (piece=='B')             return 2;         if (piece=='R')             return 3;         if (piece=='Q')             return 4;         if (piece=='K')             return 5;         if (piece=='p')             return 6;         if (piece=='n')             return 7;         if (piece=='b')             return 8;         if (piece=='r')             return 9;         if (piece=='q')             return 10;         if (piece=='k')             return 11;         else             return -1;     }       // Initializes the table     public static void initTable()     {         for (int i = 0; i<8; i++){             for(int j = 0; j < 8; j++){                 for(int k = 0; k < 12; k++){                     Random rnd = new Random();                     ZobristTable[i][j][k] = rnd.Next();                 }             }         }       }       // Computes the hash value of a given board     public static int computeHash(List> board)     {         int h = 0;         for (int i = 0; i<8; i++)         {             for (int j = 0; j<8; j++)             {                 if (board[i][j]!='-')                 {                     int piece = indexOf(board[i][j]);                     h ^= ZobristTable[i][j][piece];                 }             }         }         return h;     }        static void Main() {         // Main Function         // Uppercase letters are white pieces         // Lowercase letters are black pieces         List> board = new List>();         board.Add(new List(){'-', '-', '-', 'K', '-', '-', '-', '-'});         board.Add(new List(){'-', 'R', '-', '-', '-', '-', 'Q', '-'});         board.Add(new List(){'-', '-', '-', 'K', '-', '-', '-', '-'});         board.Add(new List(){'-', '-', '-', '-', '-', '-', '-', '-'});         board.Add(new List(){'-', 'P', '-', '-', '-', '-', 'p', '-'});         board.Add(new List(){'-', '-', '-', '-', '-', 'p', '-', '-', });         board.Add(new List(){'-', '-', '-', '-', '-', '-', '-', '-'});         board.Add(new List(){'p', '-', '-', '-', 'b', '-', '-', 'q'});         board.Add(new List(){'-', '-', '-', '-', 'n', '-', '-', 'k'});           initialise();         initTable();                             int hashValue = computeHash(board);         Console.WriteLine("The hash value is     : " + hashValue);           //Move the white king to the left         char piece = board[0][3];           board[0][3] = '-';           hashValue ^= ZobristTable[0][3][indexOf(piece)];           board[0][2] = piece;         hashValue ^= ZobristTable[0][2][indexOf(piece)];             Console.WriteLine("The new hash value is : " + hashValue);           // Undo the white king move         piece = board[0][2];           board[0][2] = '-';         hashValue ^= ZobristTable[0][2][indexOf(piece)];           board[0][3] = piece;         hashValue ^= ZobristTable[0][3][indexOf(piece)];           Console.WriteLine("The old hash value is : " + hashValue);     } }   // The code is contributed by Nidhi goel.

## Javascript

 // A program to illustrate Zobrist Hashing Algorithm // javascript code implementation   let ZobristTable = new Array(8); for(let i = 0; i < 8; i++){     ZobristTable[i] = new Array(8); } for(let i = 0; i < 8; i++){     for(let j = 0; j < 8; j++){         ZobristTable[i][j] = new Array(12);     } }   // mt19937 mt(01234567);    // Generates a Random number from 0 to 2^64-1 function randomInt() {     let min = 0;     let max = Math.pow(2, 64);     return Math.floor(Math.random() * (max - min) + min); }    // This function associates each piece with // a number function indexOf(piece) {     if (piece=='P')         return 0;     if (piece=='N')         return 1;     if (piece=='B')         return 2;     if (piece=='R')         return 3;     if (piece=='Q')         return 4;     if (piece=='K')         return 5;     if (piece=='p')         return 6;     if (piece=='n')         return 7;     if (piece=='b')         return 8;     if (piece=='r')         return 9;     if (piece=='q')         return 10;     if (piece=='k')         return 11;     else         return -1; }    // Initializes the table function initTable() {     for (let i = 0; i<8; i++)       for (let j = 0; j<8; j++)         for (let k = 0; k<12; k++){             ZobristTable[i][j][k] = randomInt();         }             }    // Computes the hash value of a given board function computeHash(board) {     let h = 0;     for (let i = 0; i<8; i++)     {         for (let j = 0; j<8; j++)         {             if (board[i][j]!='-')             {                 let piece = indexOf(board[i][j]);                 h ^= ZobristTable[i][j][piece];             }         }     }     return h; }    // Main Function // Uppercase letters are white pieces // Lowercase letters are black pieces let board = [     "---K----",     "-R----Q-",     "--------",     "-P----p-",     "-----p--",     "--------",     "p---b--q",     "----n--k" ];   initTable();   let hashValue = computeHash(board); console.log("The hash value is     : " + hashValue);   //Move the white king to the left let piece = board[0][3];   board[0] = board[0].split(''); board[0][3] = '-'; board[0] = board[0].join("");   hashValue ^= ZobristTable[0][3][indexOf(piece)];   board[0] = board[0].split(''); board[0][2] = piece; board[0] = board[0].join(""); hashValue ^= ZobristTable[0][2][indexOf(piece)];     console.log("The new hash value is : " + hashValue);   // Undo the white king move piece = board[0][2];   board[0] = board[0].split(''); board[0][2] = '-'; board[0] = board[0].join("");   hashValue ^= ZobristTable[0][2][indexOf(piece)];   board[0][3] = piece; hashValue ^= ZobristTable[0][3][indexOf(piece)];   console.log("The old hash value is : " + hashValue);   // The code is contributed by Nidhi goel.

#### Output :

The hash value is     : 14226429382419125366
The new hash value is : 15124945578233295113
The old hash value is : 14226429382419125366

If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.