hashmap cpp 换为 h
This commit is contained in:
parent
e55eee77a6
commit
e89be5e883
|
@ -37,7 +37,7 @@ HEADERS += \
|
||||||
src/gamescene.h \
|
src/gamescene.h \
|
||||||
src/gameview.h \
|
src/gameview.h \
|
||||||
src/graphicsconst.h \
|
src/graphicsconst.h \
|
||||||
src/hashmap.h \
|
src/hashMap.h \
|
||||||
src/ninechess.h \
|
src/ninechess.h \
|
||||||
src/ninechessai_ab.h \
|
src/ninechessai_ab.h \
|
||||||
src/ninechesswindow.h \
|
src/ninechesswindow.h \
|
||||||
|
|
|
@ -378,7 +378,6 @@
|
||||||
<ClCompile Include="src\gamecontroller.cpp" />
|
<ClCompile Include="src\gamecontroller.cpp" />
|
||||||
<ClCompile Include="src\gamescene.cpp" />
|
<ClCompile Include="src\gamescene.cpp" />
|
||||||
<ClCompile Include="src\gameview.cpp" />
|
<ClCompile Include="src\gameview.cpp" />
|
||||||
<ClCompile Include="src\hashmap.cpp" />
|
|
||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
<ClCompile Include="src\ninechess.cpp" />
|
<ClCompile Include="src\ninechess.cpp" />
|
||||||
<ClCompile Include="src\ninechessai_ab.cpp" />
|
<ClCompile Include="src\ninechessai_ab.cpp" />
|
||||||
|
@ -427,7 +426,8 @@
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
<ClInclude Include="src\config.h" />
|
<ClInclude Include="src\config.h" />
|
||||||
<ClInclude Include="src\graphicsconst.h" />
|
<ClInclude Include="src\graphicsconst.h" />
|
||||||
<ClInclude Include="src\hashmap.h" />
|
<ClInclude Include="src\HashMap.h" />
|
||||||
|
<ClInclude Include="src\HashNode.h" />
|
||||||
<ClInclude Include="src\ninechess.h" />
|
<ClInclude Include="src\ninechess.h" />
|
||||||
<QtMoc Include="src\ninechesswindow.h">
|
<QtMoc Include="src\ninechesswindow.h">
|
||||||
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;debug;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>
|
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include;debug;\include;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\mkspecs\win32-msvc;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtWidgets;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtCore;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtGui;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtANGLE;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtMultimedia;D:\Qt\Qt5.11.0\5.11.0\msvc2017_64\include\QtNetwork;%(AdditionalIncludeDirectories)</IncludePath>
|
||||||
|
|
|
@ -84,9 +84,6 @@
|
||||||
<ClCompile Include="src\ninechessai_ab.cpp">
|
<ClCompile Include="src\ninechessai_ab.cpp">
|
||||||
<Filter>Model</Filter>
|
<Filter>Model</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\hashmap.cpp">
|
|
||||||
<Filter>Model</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="resource.h">
|
<ClInclude Include="resource.h">
|
||||||
|
@ -113,7 +110,10 @@
|
||||||
<ClInclude Include="src\config.h">
|
<ClInclude Include="src\config.h">
|
||||||
<Filter>Control</Filter>
|
<Filter>Control</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\hashmap.h">
|
<ClInclude Include="src\HashNode.h">
|
||||||
|
<Filter>Model</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\HashMap.h">
|
||||||
<Filter>Model</Filter>
|
<Filter>Model</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
#ifndef HASH_NODE_H_
|
||||||
|
#define HASH_NODE_H_
|
||||||
|
|
||||||
|
#include <shared_mutex>
|
||||||
|
namespace CTSL //Concurrent Thread Safe Library
|
||||||
|
{
|
||||||
|
// Class representing a templatized hash node
|
||||||
|
template <typename K, typename V>
|
||||||
|
class HashNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HashNode() : next(nullptr)
|
||||||
|
{}
|
||||||
|
HashNode(K key_, V value_) : next(nullptr), key(key_), value(value_)
|
||||||
|
{}
|
||||||
|
~HashNode()
|
||||||
|
{
|
||||||
|
next = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const K& getKey() const {return key;}
|
||||||
|
void setValue(V value_) {value = value_;}
|
||||||
|
const V& getValue() const {return value;}
|
||||||
|
|
||||||
|
HashNode *next; //Pointer to the next node in the same bucket
|
||||||
|
private:
|
||||||
|
K key; //the hash key
|
||||||
|
V value; //the value corresponding to the key
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//Class representing a hash bucket. The bucket is implemented as a singly linked list.
|
||||||
|
//A bucket is always constructed with a dummy head node
|
||||||
|
template <typename K, typename V>
|
||||||
|
class HashBucket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HashBucket() : head(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~HashBucket() //delete the bucket
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Function to find an entry in the bucket matching the key
|
||||||
|
//If key is found, the corresponding value is copied into the parameter "value" and function returns true.
|
||||||
|
//If key is not found, function returns false
|
||||||
|
bool find(const K &key, V &value) const
|
||||||
|
{
|
||||||
|
// A shared mutex is used to enable mutiple concurrent reads
|
||||||
|
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
|
||||||
|
HashNode<K, V> * node = head;
|
||||||
|
|
||||||
|
while (node != nullptr)
|
||||||
|
{
|
||||||
|
if (node->getKey() == key)
|
||||||
|
{
|
||||||
|
value = node->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Function to insert into the bucket
|
||||||
|
//If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair
|
||||||
|
void insert(const K &key, const V &value)
|
||||||
|
{
|
||||||
|
//Exclusive lock to enable single write in the bucket
|
||||||
|
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
|
||||||
|
HashNode<K, V> * prev = nullptr;
|
||||||
|
HashNode<K, V> * node = head;
|
||||||
|
|
||||||
|
while (node != nullptr && node->getKey() != key)
|
||||||
|
{
|
||||||
|
prev = node;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == node) //New entry, create a node and add to bucket
|
||||||
|
{
|
||||||
|
if(nullptr == head)
|
||||||
|
{
|
||||||
|
head = new HashNode<K, V>(key, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev->next = new HashNode<K, V>(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node->setValue(value); //Key found in bucket, update the value
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Function to remove an entry from the bucket, if found
|
||||||
|
void erase(const K &key)
|
||||||
|
{
|
||||||
|
//Exclusive lock to enable single write in the bucket
|
||||||
|
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
|
||||||
|
HashNode<K, V> *prev = nullptr;
|
||||||
|
HashNode<K, V> * node = head;
|
||||||
|
|
||||||
|
while (node != nullptr && node->getKey() != key)
|
||||||
|
{
|
||||||
|
prev = node;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == node) //Key not found, nothing to be done
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else //Remove the node from the bucket
|
||||||
|
{
|
||||||
|
if(head == node)
|
||||||
|
{
|
||||||
|
head = node->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev->next = node->next;
|
||||||
|
}
|
||||||
|
delete node; //Free up the memory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Function to clear the bucket
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
//Exclusive lock to enable single write in the bucket
|
||||||
|
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
|
||||||
|
HashNode<K, V> * prev = nullptr;
|
||||||
|
HashNode<K, V> * node = head;
|
||||||
|
while(node != nullptr)
|
||||||
|
{
|
||||||
|
prev = node;
|
||||||
|
node = node->next;
|
||||||
|
delete prev;
|
||||||
|
}
|
||||||
|
head = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HashNode<K, V> * head; //The head node of the bucket
|
||||||
|
mutable std::shared_timed_mutex mutex_; //The mutex for this bucket
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -35,7 +35,7 @@ void AiThread::setAi(const NineChess &chess)
|
||||||
ai_ab.setChess(*(this->chess_));
|
ai_ab.setChess(*(this->chess_));
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
ai_ab.clearHashMap();
|
//ai_ab.clearHashMap();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
|
@ -79,6 +79,7 @@ void HashBucket<K, V>::erase(const K &key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Function to clear the bucket
|
// Function to clear the bucket
|
||||||
template <typename K, typename V>
|
template <typename K, typename V>
|
||||||
void HashBucket<K, V>::clear()
|
void HashBucket<K, V>::clear()
|
||||||
|
@ -94,6 +95,7 @@ void HashBucket<K, V>::clear()
|
||||||
}
|
}
|
||||||
head = nullptr;
|
head = nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -5,130 +5,76 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <shared_mutex>
|
#include "HashNode.h"
|
||||||
|
|
||||||
constexpr size_t HASH_SIZE_DEFAULT = 1031; // A prime number as hash size gives a better distribution of values in buckets
|
constexpr size_t HASH_SIZE_DEFAULT = 1031; // A prime number as hash size gives a better distribution of values in buckets
|
||||||
|
|
||||||
namespace CTSL //Concurrent Thread Safe Library
|
namespace CTSL //Concurrent Thread Safe Library
|
||||||
{
|
{
|
||||||
// Class representing a templatized hash node
|
//The class represting the hash map.
|
||||||
template <typename K, typename V>
|
//It is expected for user defined types, the hash function will be provided.
|
||||||
class HashNode
|
//By default, the std::hash function will be used
|
||||||
{
|
//If the hash size is not provided, then a defult size of 1031 will be used
|
||||||
public:
|
//The hash table itself consists of an array of hash buckets.
|
||||||
HashNode() : next(nullptr)
|
//Each hash bucket is implemented as singly linked list with the head as a dummy node created
|
||||||
|
//during the creation of the bucket. All the hash buckets are created during the construction of the map.
|
||||||
|
//Locks are taken per bucket, hence multiple threads can write simultaneously in different buckets in the hash map
|
||||||
|
template <typename K, typename V, typename F = std::hash<K> >
|
||||||
|
class HashMap
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
HashNode(K key_, V value_) : next(nullptr), key(key_), value(value_)
|
HashMap(size_t hashSize_ = HASH_SIZE_DEFAULT) : hashSize(hashSize_)
|
||||||
{
|
{
|
||||||
}
|
hashTable = new HashBucket<K, V>[hashSize]; //create the hash table as an array of hash buckets
|
||||||
~HashNode()
|
}
|
||||||
{
|
|
||||||
next = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const K &getKey() const
|
~HashMap()
|
||||||
{
|
{
|
||||||
return key;
|
delete [] hashTable;
|
||||||
}
|
}
|
||||||
void setValue(V value_)
|
//Copy and Move of the HashMap are not supported at this moment
|
||||||
{
|
HashMap(const HashMap&) = delete;
|
||||||
value = value_;
|
HashMap(HashMap&&) = delete;
|
||||||
}
|
HashMap& operator=(const HashMap&) = delete;
|
||||||
const V &getValue() const
|
HashMap& operator=(HashMap&&) = delete;
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashNode *next; // Pointer to the next node in the same bucket
|
//Function to find an entry in the hash map matching the key.
|
||||||
private:
|
//If key is found, the corresponding value is copied into the parameter "value" and function returns true.
|
||||||
K key; // the hash key
|
//If key is not found, function returns false.
|
||||||
V value; // the value corresponding to the key
|
bool find(const K &key, V &value) const
|
||||||
};
|
{
|
||||||
|
size_t hashValue = hashFn(key) % hashSize ;
|
||||||
|
return hashTable[hashValue].find(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Function to insert into the hash map.
|
||||||
|
//If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair.
|
||||||
|
void insert(const K &key, const V &value)
|
||||||
|
{
|
||||||
|
size_t hashValue = hashFn(key) % hashSize ;
|
||||||
|
hashTable[hashValue].insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
// Class representing a hash bucket. The bucket is implemented as a singly linked list.
|
//Function to remove an entry from the bucket, if found
|
||||||
// A bucket is always constructed with a dummy head node
|
void erase(const K &key)
|
||||||
template <typename K, typename V>
|
{
|
||||||
class HashBucket
|
size_t hashValue = hashFn(key) % hashSize ;
|
||||||
{
|
hashTable[hashValue].erase(key);
|
||||||
public:
|
}
|
||||||
HashBucket() : head(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~HashBucket() //delete the bucket
|
//Function to clean up the hasp map, i.e., remove all entries from it
|
||||||
{
|
void clear()
|
||||||
clear();
|
{
|
||||||
}
|
for(size_t i = 0; i < hashSize; i++)
|
||||||
|
{
|
||||||
|
(hashTable[i]).clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Function to find an entry in the bucket matching the key
|
private:
|
||||||
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
|
HashBucket<K, V> * hashTable;
|
||||||
// If key is not found, function returns false
|
F hashFn;
|
||||||
bool find(const K &key, V &value) const;
|
const size_t hashSize;
|
||||||
|
};
|
||||||
// Function to insert into the bucket
|
|
||||||
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair
|
|
||||||
void insert(const K &key, const V &value);
|
|
||||||
|
|
||||||
// Function to remove an entry from the bucket, if found
|
|
||||||
void erase(const K &key);
|
|
||||||
|
|
||||||
// Function to clear the bucket
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
private:
|
|
||||||
HashNode<K, V> *head; //The head node of the bucket
|
|
||||||
mutable std::shared_timed_mutex mutex_; //The mutex for this bucket
|
|
||||||
};
|
|
||||||
|
|
||||||
// The class represting the hash map.
|
|
||||||
// It is expected for user defined types, the hash function will be provided.
|
|
||||||
// By default, the std::hash function will be used
|
|
||||||
// If the hash size is not provided, then a defult size of 1031 will be used
|
|
||||||
// The hash table itself consists of an array of hash buckets.
|
|
||||||
// Each hash bucket is implemented as singly linked list with the head as a dummy node created
|
|
||||||
// during the creation of the bucket. All the hash buckets are created during the construction of the map.
|
|
||||||
// Locks are taken per bucket, hence multiple threads can write simultaneously in different buckets in the hash map
|
|
||||||
template <typename K, typename V, typename F = std::hash<K> >
|
|
||||||
class HashMap
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HashMap(size_t hashSize_ = HASH_SIZE_DEFAULT) : hashSize(hashSize_)
|
|
||||||
{
|
|
||||||
hashTable = new HashBucket<K, V>[hashSize]; // create the hash table as an array of hash buckets
|
|
||||||
}
|
|
||||||
|
|
||||||
~HashMap()
|
|
||||||
{
|
|
||||||
delete[] hashTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy and Move of the HashMap are not supported at this moment
|
|
||||||
HashMap(const HashMap &) = delete;
|
|
||||||
HashMap(HashMap &&) = delete;
|
|
||||||
HashMap &operator=(const HashMap &) = delete;
|
|
||||||
HashMap &operator=(HashMap &&) = delete;
|
|
||||||
|
|
||||||
// Function to find an entry in the hash map matching the key.
|
|
||||||
// If key is found, the corresponding value is copied into the parameter "value" and function returns true.
|
|
||||||
// If key is not found, function returns false.
|
|
||||||
bool find(const K &key, V &value) const;
|
|
||||||
|
|
||||||
// Function to insert into the hash map.
|
|
||||||
// If key already exists, update the value, else insert a new node in the bucket with the <key, value> pair.
|
|
||||||
void insert(const K &key, const V &value);
|
|
||||||
|
|
||||||
// Function to remove an entry from the bucket, if found
|
|
||||||
void erase(const K &key);
|
|
||||||
|
|
||||||
// Function to clean up the hasp map, i.e., remove all entries from it
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
private:
|
|
||||||
HashBucket<K, V> *hashTable;
|
|
||||||
F hashFn;
|
|
||||||
const size_t hashSize;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
#endif /* HASH_MAP_H_ */
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,6 @@ NineChess::~NineChess()
|
||||||
void NineChess::constructHash()
|
void NineChess::constructHash()
|
||||||
{
|
{
|
||||||
context.hash = 0ull;
|
context.hash = 0ull;
|
||||||
context.hashCheckCode = 0ull;
|
|
||||||
|
|
||||||
context.gameMovingHash = rand64();
|
context.gameMovingHash = rand64();
|
||||||
context.actionCaptureHash = rand64();
|
context.actionCaptureHash = rand64();
|
||||||
|
@ -397,7 +396,6 @@ bool NineChess::setContext(const struct Rule *rule, int maxStepsLedToDraw, int m
|
||||||
memset(context.board, 0, sizeof(context.board));
|
memset(context.board, 0, sizeof(context.board));
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
context.hash = 0ull;
|
context.hash = 0ull;
|
||||||
context.hashCheckCode = 0ull;
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
memcpy(context.board, board, sizeof(context.board));
|
memcpy(context.board, board, sizeof(context.board));
|
||||||
|
@ -557,9 +555,8 @@ bool NineChess::reset()
|
||||||
elapsedMS_1 = elapsedMS_2 = 0;
|
elapsedMS_1 = elapsedMS_2 = 0;
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
// 哈希以及哈希校验码归零
|
// 哈希归零
|
||||||
context.hash = 0;
|
context.hash = 0;
|
||||||
context.hashCheckCode = 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 提示
|
// 提示
|
||||||
|
@ -1324,14 +1321,10 @@ uint64_t NineChess::getHash()
|
||||||
return context.hash;
|
return context.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t NineChess::getHashCheckCode()
|
|
||||||
{
|
|
||||||
return context.hashCheckCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hash函数,对应可重复去子的规则
|
// hash函数,对应可重复去子的规则
|
||||||
uint64_t NineChess::updateHash(int pos)
|
uint64_t NineChess::updateHash(int pos)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
* hashCheckCode 各数据位详解(并无冲突,是算法用到的棋局数据的完全表示)
|
* hashCheckCode 各数据位详解(并无冲突,是算法用到的棋局数据的完全表示)
|
||||||
* 56-63位:空白不用,全为0
|
* 56-63位:空白不用,全为0
|
||||||
|
@ -1342,33 +1335,33 @@ uint64_t NineChess::updateHash(int pos)
|
||||||
* 4-5位(共2位):待去子数,最大为3,用2个二进制位表示即可
|
* 4-5位(共2位):待去子数,最大为3,用2个二进制位表示即可
|
||||||
* 0-3位:player1的手棋数,不需要player2的(可计算出)
|
* 0-3位:player1的手棋数,不需要player2的(可计算出)
|
||||||
*/
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
uint64_t hash = 0ull;
|
uint64_t hash = 0ull;
|
||||||
|
|
||||||
// TODO: 本函数效率低下,啥时调用?
|
|
||||||
for (int i = POS_BEGIN; i < POS_END; i++) {
|
for (int i = POS_BEGIN; i < POS_END; i++) {
|
||||||
// hash ^= context.zobrist[i][pointType]; // TODO: 待完善
|
// hash ^= context.zobrist[i][pointType]; // TODO: 待完善
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t temp = board_[pos] & 0x30 >> 4;
|
uint64_t temp = board_[pos] & 0x30 >> 4;
|
||||||
context.hashCheckCode |= (temp) << ((pos - 8) * 2 + 6);
|
//context.hashCheckCode |= (temp) << ((pos - 8) * 2 + 6);
|
||||||
// TODO: context.hash =
|
// TODO: context.hash =
|
||||||
|
|
||||||
if (context.turn == PLAYER2) {
|
if (context.turn == PLAYER2) {
|
||||||
context.hashCheckCode |= 1ull << 55;
|
//context.hashCheckCode |= 1ull << 55;
|
||||||
context.hash ^= context.player2sTurnHash;
|
context.hash ^= context.player2sTurnHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.action == ACTION_CAPTURE) {
|
if (context.action == ACTION_CAPTURE) {
|
||||||
context.hashCheckCode |= 1ull << 54;
|
//context.hashCheckCode |= 1ull << 54;
|
||||||
context.hash ^= context.actionCaptureHash;
|
context.hash ^= context.actionCaptureHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.hashCheckCode |= (uint64_t)context.nPiecesNeedRemove << 4;
|
//context.hashCheckCode |= (uint64_t)context.nPiecesNeedRemove << 4;
|
||||||
context.hashCheckCode |= context.nPiecesInHand_1;
|
//context.hashCheckCode |= context.nPiecesInHand_1;
|
||||||
// TODO: hash 应该 不需要
|
// TODO: hash 应该 不需要
|
||||||
|
|
||||||
return context.hashCheckCode; // TODO: 返回什么
|
return context.hash; // TODO: 返回什么
|
||||||
}
|
}
|
||||||
#endif /* HASH_MAP_ENABLE */
|
#endif /* HASH_MAP_ENABLE */
|
||||||
|
|
||||||
|
|
|
@ -180,15 +180,9 @@ public:
|
||||||
int board[N_POINTS];
|
int board[N_POINTS];
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
// 局面哈希的校验码(过时)
|
|
||||||
uint64_t hashCheckCode;
|
|
||||||
|
|
||||||
// 局面的哈希值
|
// 局面的哈希值
|
||||||
uint64_t hash;
|
uint64_t hash;
|
||||||
|
|
||||||
// 哈希表中的地址, 为 hash 的后 16 位
|
|
||||||
uint16_t hashAddr;
|
|
||||||
|
|
||||||
// 标记处于走子阶段的哈希
|
// 标记处于走子阶段的哈希
|
||||||
uint64_t gameMovingHash;
|
uint64_t gameMovingHash;
|
||||||
|
|
||||||
|
@ -497,7 +491,6 @@ protected:
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
// hash相关
|
// hash相关
|
||||||
uint64_t getHash();
|
uint64_t getHash();
|
||||||
uint64_t getHashCheckCode();
|
|
||||||
uint64_t updateHash(int pos);
|
uint64_t updateHash(int pos);
|
||||||
#endif /* HASH_MAP_ENABLE */
|
#endif /* HASH_MAP_ENABLE */
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,12 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "ninechessai_ab.h"
|
#include "ninechessai_ab.h"
|
||||||
#include "hashmap.h"
|
#include "hashMap.h"
|
||||||
|
|
||||||
|
using namespace CTSL;
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
static std::unique_ptr<HashMap<NineChessAi_ab::HashValue>> instance;
|
HashMap<uint64_t, NineChessAi_ab::HashValue> hashmap;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NineChessAi_ab::NineChessAi_ab() :
|
NineChessAi_ab::NineChessAi_ab() :
|
||||||
|
@ -638,9 +640,6 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
// 检索 hashmap
|
// 检索 hashmap
|
||||||
uint64_t hashCheckCode = chessTemp.getHashCheckCode();
|
|
||||||
node->hashCheckCode = hashCheckCode;
|
|
||||||
|
|
||||||
uint64_t hash = chessTemp.getHash();
|
uint64_t hash = chessTemp.getHash();
|
||||||
node->hash = hash;
|
node->hash = hash;
|
||||||
|
|
||||||
|
@ -856,12 +855,12 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
int NineChessAi_ab::recordHash(HashValue &hashValue)
|
int NineChessAi_ab::recordHash(const HashValue &hashValue)
|
||||||
{
|
{
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
//hashMapMutex.lock();
|
//hashMapMutex.lock();
|
||||||
//HashMap<HashValue>::insert(hashValue.hash, hashValue);
|
//HashMap<HashValue>::insert(hashValue.hash, hashValue);
|
||||||
|
hashmap.insert(hashValue.hash, hashValue);
|
||||||
//hashMapMutex.unlock();
|
//hashMapMutex.unlock();
|
||||||
#endif // HASH_MAP_ENABLE
|
#endif // HASH_MAP_ENABLE
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "ninechess.h"
|
#include "ninechess.h"
|
||||||
#include "hashmap.h"
|
#include "hashMap.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace CTSL;
|
||||||
|
|
||||||
// 注意:NineChess类不是线程安全的!
|
// 注意:NineChess类不是线程安全的!
|
||||||
// 所以不能在ai类中修改NineChess类的静态成员变量,切记!
|
// 所以不能在ai类中修改NineChess类的静态成员变量,切记!
|
||||||
|
@ -61,7 +62,6 @@ public:
|
||||||
int rand; // 随机数,对于 value 一致的结点随机排序用
|
int rand; // 随机数,对于 value 一致的结点随机排序用
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
uint64_t hash;
|
uint64_t hash;
|
||||||
uint64_t hashCheckCode;
|
|
||||||
bool isHash; // 是否从 Hash 读取
|
bool isHash; // 是否从 Hash 读取
|
||||||
#endif /* HASH_MAP_ENABLE */
|
#endif /* HASH_MAP_ENABLE */
|
||||||
bool pruned; // 是否在此处剪枝
|
bool pruned; // 是否在此处剪枝
|
||||||
|
@ -145,11 +145,6 @@ protected:
|
||||||
// 增加新节点
|
// 增加新节点
|
||||||
struct Node *addNode(Node *parent, int value, NineChess::move_t move, enum NineChess::Player player);
|
struct Node *addNode(Node *parent, int value, NineChess::move_t move, enum NineChess::Player player);
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
|
||||||
// 插入哈希表
|
|
||||||
int recordHash(HashValue &hashValue);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 评价函数
|
// 评价函数
|
||||||
int evaluate(Node *node);
|
int evaluate(Node *node);
|
||||||
|
|
||||||
|
@ -172,6 +167,9 @@ protected:
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
// 查找哈希表
|
// 查找哈希表
|
||||||
HashValue findHash(uint64_t hash);
|
HashValue findHash(uint64_t hash);
|
||||||
|
|
||||||
|
// 插入哈希表
|
||||||
|
int recordHash(const HashValue &hashValue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -219,7 +217,7 @@ private:
|
||||||
char cmdline[32];
|
char cmdline[32];
|
||||||
|
|
||||||
#ifdef HASH_MAP_ENABLE
|
#ifdef HASH_MAP_ENABLE
|
||||||
HashMap<struct HashValue> hashmap;
|
//HashMap<struct HashValue> hashmap;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue