- clone
git clone https://github.com/chaseungjoon/DavincicodeCPP.git
cd DavincicodeCPP
- Build (❗Make sure you have CMake (>= 3.31) and a C++20-compatible compiler installed)
mkdir build
cd build
cmake ..
make
- Run
./DavincicodeCPP
Define card by "sequence"
Cards in Davinci Code follows a specific sequence layout;
(Black 0 -> White 0 -> Black 1 -> White 1 -> ... -> Black 11 -> White 11)
Therefore, each card's color can be defined as
(seq % 2) ? Black : White
and each card's number is
seq / 2
boolean attribute "shown" indicates if card is shown
boolean attribute "newlyDrawn" indicates if card is newly drawn (for printing purposes & sorting purposes)
There are only two instances of Player class;
- human
- computer
hand attribute is the card hand of either player
std::vector<Card> hand
For the computer's guessing algorithm, a probability vector exists as an attribute
struct probData{
std::string color;
std::vector<int> values;
};
std::vector<probData> prob;
Indicating cards that has been shown/known, a sequence vector exists as an attribute.
std::vector<int> seqVec;
For the computer's guessing algorithm, the following functions are implemented
void initializeProb(const std::vector<Card>& hand);
void updateProb(const std::vector<Card>& hand);
void adjustProb(const std::vector<Card>& hand);
Take care of initialization, printing card layouts and checking winning situations.
-
Draw card
-
Update the probability vector of opponent's cards
-
Choose the highest probable guess (smallest probability vector)
-
Repeat until win
Create a sequence vector that contains the sequence of cards that is shown at the moment -> non-candidate cards
For the opponent's each concealed card, create probability data as below (probData)
struct probData{
std::string color;
std::vector<int> values;
};
color is the color of the card, values are what the card's numbers can be.
values can only be picked if not included in the sequence vector
For all the opponent's cards, Create a prob vector of these probData.
If the opponent has n black cards, the 0th card's value can be 0,1, ..., 11-(n-1)
with the same principle, the (n-1)th card's value can be (n-1),n, ..., 11
for N black cards, the ith (i<n) black card's value vector is;
{i, i+1, ..., 11-(n-1)}
Firstly, create probData with the same principle as black cards
for N white cards, the ith (i<n) white card's value vector is;
{i, i+1, ..., 11-(n-1)}
if the number of black cards is greater than zero, we must put into account the value vector of near black cards.
for each white card, find left_closest_black and right_closest_black cards.
Delete values from the white card's values vector that is;
- Smaller than min(left_closest_black.values)
- Larger than max(right_closest_black.values)
If there are no left_closest_black or right_closest_black cards, ignore this process.
Same as what we did with the white cards, for black cards too;
if the number of white cards is greater than zero, we must put into account the value vector of near white cards.
for each black card, find left_closest_white and right_closest_white cards.
Delete values from the black card's values vector that is;
- Smaller than min(left_closest_white.values)
- Larger than max(right_closest_white.values)
If there are no left_closest_white or right_closest_white cards, ignore this process.
For cards that is shown=true
, collapse the probData.values
into the single value.
probData.values = {3};
{Propagation}
Using the rules we implemented for initializing the probability vector, fix the neighboring probData.values
vectors.
The collapsed probData being prob[n]
The order of fixing must be
prob[n-1]
andprob[n+1]
prob[n-2]
andprob[n+2]
~
Just how a "propagation" would work.
Based on the left nearest card and right nearest card, create probData.values
vector as follows;
probData.values = {min(left_nearest_card)+1, ..., max(right_nearest_card)-1}
If the new card is the leftmost/rightmost card, put min=0/max=11
- All guessings are done to cards that is
shown=false
In the prob
vector, choose an index that has the smallest probData.values
vector
→ Highest possibility of a correct guess
Choose a random index of the probData.values
vector, and submit the guess.
If the guess is correct, set the card shown=true
.
Then update probability vector.
If the initial guessing is incorrect, additional guessing is not allowed.
For strategic reasons, additional guessing is only initiated when there is a definite-sized vector
- definite-sized vector :
sizeof(probData.values) <= 2
The additional guessing is looped until;
- Incorrect guess
- No definite-sized vector available
- Game over