有个25棋子,两人轮流拿,一次最多拿3个,拿完后,谁得到的棋子总数为偶数的胜.找出必胜策略,实现人机对战.让电脑必能取胜.
算法很简单,但要找到不容易,至少我是这样.
以前用c++写过一个类似的,规则和楼主的有些出入,不过思想差不多。
贴上我的源代码:
//Nim游戏
//游戏说明: 捡石头,玩家一次最多只能取走总数一半的石头,谁拿到最后一块石头,他就输了T_T
//别小看电脑的智商哦。。。。。。
#include <iostream.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
//测试该数字是否为2^a-1,a未知数
bool test(int n);
//刷新随机数种子
void fresh_rand_seed();
//产生指定范围的随机数
int rand_num(int a,int b);
//普通模式AI
int get_method_ordinary_AI(int &total);
//高级模式AI
int get_method_advanced_AI(int &total);
int main()
{
int menu;
cout << "+-------------------+\n";
cout << "|Game of Nim Ver 0.1|\n";
cout << "+-------------------+\n\n";
cout << "0. Normal\n";
cout << "1. Hard\n";
cout << "2. Exit\n";
cout << "Please select the method of game [0..2] ";
cin >> menu;
if (cin.fail())
{
cout << "Do not make joke with me.....\n";
return 1;
}
else if (menu < 0 || menu > 3)
{
cout << "It is not an vailed item index....\n";
return 1;
}
else if (menu == 0 || menu == 1)
{
int total_count;
cout << "Please input total of stones (2 - 32767) :";
cin >> total_count;
if (cin.fail())
{
cout << "What are you thinking of\n?";
return 1;
}
else if(total_count < 2)
{
cout << "Impossible! Use your mind please.\n";
return 1;
}
else
{
fresh_rand_seed();
//随机生成游戏顺序,0 - 玩家先,1 - NPC先
int ply_first = rand_num(0,1);
//游戏难度 0 - Normal 1 - Hard
int level = menu;
bool flag;
if (level == 0 || level == 1)
{
if (ply_first == 0)
{
flag = true; //设定玩家先
}
else
{
flag = false; //设定NPC先
}
while(total_count > 1)
{
int count;
if (flag)
{
cout << "It's your turn!\n";
cout << "How many stones do you want to take away?(1 - " << static_cast<int>(total_count / 2)
<< ") ";
cin >> count;
if (cin.fail())
{
cout << "Oh, I don't wanna play with such a stupid guy!\n";
break;
return 1;
}
else if(count < 1 || count > static_cast<int>(total_count / 2))
{
cout << "Do you want to have a rest?\n";
break;
return 1;
}
else
{
total_count -= count;
cout << "You have smoothly taken away " << count << " stone(s).....\n";
cout << "The rest amount is " << total_count << "\n";
flag = false;
}
}
else
{
if (level == 0)
{
cout << "NPC has smoothly taken away " << get_method_ordinary_AI(total_count) << " stone(s).....\n";
cout << "The rest amount is " << total_count << "\n";
flag = true; //转换为玩家
}
else if(level == 1)
{
cout << "NPC has smoothly taken away " << get_method_advanced_AI(total_count) << " stone(s).....\n";
cout << "The rest amount is " << total_count << "\n";
flag = true;
}
}
if (flag && total_count == 1)
{
cout << "You've lost the game!\n";
break;
return 0;
}
else if(!flag && total_count == 1)
{
cout << "You are win!\n";
break;
return 0;
}
}
}
}
}
else if (menu == 2)
{
cout << "ByeBye!~~" << endl;
return 1;
}
return 0;
}
bool test(int n)
{
int a = 0;
bool r = false;
do
{
a++;
if ((pow(2,a) - 1) == n)
{
r = true;
break;
}
}
while(pow(2,a) - 1 < n);
return r;
}
void fresh_rand_seed()
{
srand(static_cast<int>(time(0)));
}
int rand_num(int a,int b)
{
return a + rand() % (b - a + 1);
}
int get_method_ordinary_AI(int &total)
{
int count = rand_num(1,total / 2);
total -= count;
return count;
}
int get_method_advanced_AI(int &total)
{
int mirror_count = total;
int counter = 0;
if(total == 2 || test(total))
{
total -= 1;
return 1;
}
do
{
mirror_count--;
counter++;
}
while(!test(mirror_count));
total -= counter;
return counter;
}