| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1057 人关注过本帖
标题:人机对战算法
只看楼主 加入收藏
simpley
Rank: 1
等 级:新手上路
帖 子:262
专家分:0
注 册:2005-2-23
收藏
 问题点数:0 回复次数:7 
人机对战算法
这是电脑报上的一题:
有个25棋子,两人轮流拿,一次最多拿3个,拿完后,谁得到的棋子总数为偶数的胜.找出必胜策略,实现人机对战.让电脑必能取胜.

算法很简单,但要找到不容易,至少我是这样.
搜索更多相关主题的帖子: 人机 算法 
2005-11-28 13:24
Howdy
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2005-11-27
收藏
得分:0 
????????????
2005-11-28 13:25
lisypro
Rank: 4
等 级:业余侠客
威 望:3
帖 子:695
专家分:216
注 册:2005-9-25
收藏
得分:0 
我以前做过,忘了,不过你的问题描述可能有问题,

长期承接管理系统
代做各种vb/ / vc小程序
QQ:82341763
手机:13623290828
群号 11619730
2005-11-29 15:00
simpley
Rank: 1
等 级:新手上路
帖 子:262
专家分:0
注 册:2005-2-23
收藏
得分:0 
描述非常准确.
提示:后拿者必胜.

myQQ::445750010
2005-12-01 17:58
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 

以前用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;
}


我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2005-12-02 17:56
simpley
Rank: 1
等 级:新手上路
帖 子:262
专家分:0
注 册:2005-2-23
收藏
得分:0 
规则和楼主的有些出入,不过思想差不多。?
规则不一样,思想也完全不一样.

yuki的程序可以这么做;
任意一个数n,正确的拿走数就是:
n-pow(2,n的位数)+1

计算n的位数我只知道这么做,不知道有没有好办法
for(i=14;;i--)
if(n>>i)break;

#include<math.h>
main(){int n,i;
scanf("%d",&n);
for(i=14;;i--)
if(n>>i)break;
printf("%f",n-pow(2,i)+1);getch();}


myQQ::445750010
2005-12-05 14:31
simpley
Rank: 1
等 级:新手上路
帖 子:262
专家分:0
注 册:2005-2-23
收藏
得分:0 

说明:
上面我写的那个程序只是一种算法演示,不包括容错处理.比如,你输入7后,会打出4,这就违反规定,这说明你遇到7时是必败的.即如果有7个数,谁先拿谁败.yuki的程序按照正常的思路很容易推出,而电脑报的题相对来说思路就要灵活一些.


myQQ::445750010
2005-12-05 14:41
simpley
Rank: 1
等 级:新手上路
帖 子:262
专家分:0
注 册:2005-2-23
收藏
得分:0 
我觉得如果把楼上的游戏改为相反的就有趣多了.
游戏说明: 捡石头,玩家一次最多只能取走总数一半的石头,谁拿到最后一块石头,他就胜了.

任意一个数N,要必胜就必须拿走下面程序中得出的数.
main(){int i=14,n;
scanf("%d",&n);n++;
while(!(n>>i--));
if((n>>i)==2)i--;
printf("%d",n-(3<<i));getch();
}
如果打出0,就说明必败.(这时数为3*2^k-1形式.)

myQQ::445750010
2005-12-08 13:33
快速回复:人机对战算法
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.035555 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved