[五星]程序开发一个石头剪刀布的人机对战程序

除了美化之外,还可以来尝试挑战一下任务
头像
prettysnail
帖子: 198
注册时间: 2007-03-07 9:35

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#16

帖子 prettysnail » 2011-10-19 9:07

:em05 随便瞎折腾了一个,凑个数耍哈,等高手来指点。
把出的数据记录下来,推算当前组合下历史记录中下一个石头,剪刀,布的出再概率,加上适当随机数控制哈。暂时遍历1~5位的组合过程,不过加权数随便折腾了一个值,马马虎虎凑合一下。
低码如下:

代码: 全选

#!/usr/bin/perl -w
use strict;

print "\"s\"=石头,\"j\"=剪子,\"b\"=布,\"exit\"退出!\n";
my %hash_z=("0"=>"j","1"=>"s","2"=>"b");
my %hash_r=reverse %hash_z;
my %hash_txt=("j"=>"剪刀","s"=>"石头","b"=>"布");
my $in_list="j";
my ($win,$eq,$lost)=(0,0,0);
while ((my $in=<STDIN>) ne "exit\n") {
	chomp $in;
	if (($in ne "s") && ($in ne "j") && ($in ne "b")) {
		print "Error Input!\n";
		next;
	}
	my $guess;
	my ($count_J,$count_S,$count_B)=(0,0,0);
	for (my $i=1;$i<6;$i++) {
		my $rul="\\w" x $i;
		if ($in_list=~/($rul)$/) {
			my $tmp=$1; 
			my $j=()=$in_list=~/($tmp)j/g;$count_J+=$j*(1+$i*.25);
			my $s=()=$in_list=~/($tmp)s/g;$count_S+=$s*(1+$i*.25);
			my $b=()=$in_list=~/($tmp)b/g;$count_B+=$b*(1+$i*.25);
		}
	}
	if (($count_J + rand(4) - 2)  >$count_S) {
		$guess=(($count_J + rand(4) - 2)>$count_B) ? "j" : "b";
	} else {
		$guess=(($count_S + rand(4) - 2)>$count_B) ? "s" : "b";
	}
	my $out=$hash_z{($hash_r{$guess} + 1) % 3};
	my $flag = ($hash_r{$out} + 3 - $hash_r{$in}) % 3;
	my $flag_txt;
	if ($flag == 0) {
		$eq++; $flag_txt="平局";
	} elsif ($flag == 1) {
		$lost++; $flag_txt="你输了";
	} else { $win++; $flag_txt="你赢了"; }
	print "$hash_txt{$in}  PK  $hash_txt{$out} ****$flag_txt 赢了$win 次,输了$lost 次,平了$eq 次。\n";
	$in_list .=$in;
};

自己测试了一下,前面容易赢到计算机,到后来时间越长越不容量,偶在50多次以后都输了,偶家小盆友喜欢折腾这些无聊的事,让他试了,在200步后必输。 :em04
头像
懒蜗牛Gentoo
论坛版主
帖子: 7351
注册时间: 2007-03-02 17:36
系统: Linux Mint

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#17

帖子 懒蜗牛Gentoo » 2011-10-19 9:16

在200步后必输
很智能啊!!
虽然世上没有完美的东西,但这并不影响我们追求完美,因为只有偏执狂才TMD能成功。
10.04新手入门——笨兔兔讲述自己的故事
头像
ljj_jjl2008
论坛版主
帖子: 14255
注册时间: 2007-09-16 8:29

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#18

帖子 ljj_jjl2008 » 2011-10-19 10:17

这个我怀疑:开始故意顺序出“石头、剪刀、布”,迷惑计算机,出上几轮,让你的智能学会一个错误的顺序,然后再换过来,成“布、石头、剪刀”,是不是你的智能就会不灵了?
头像
懒蜗牛Gentoo
论坛版主
帖子: 7351
注册时间: 2007-03-02 17:36
系统: Linux Mint

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#19

帖子 懒蜗牛Gentoo » 2011-10-19 10:21

在已知算法的前提下,肯定能够迷惑计算机的。 :em04
虽然世上没有完美的东西,但这并不影响我们追求完美,因为只有偏执狂才TMD能成功。
10.04新手入门——笨兔兔讲述自己的故事
头像
月下叹逍遥
论坛版主
帖子: 33994
注册时间: 2010-10-07 14:23
系统: Archdows10
来自: 某系某星某洲某国某省某市
联系:

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#20

帖子 月下叹逍遥 » 2011-10-19 10:24

好吧,拿C写一个。。。
浮生七十今三十,从此凄惶未可知
头像
prettysnail
帖子: 198
注册时间: 2007-03-07 9:35

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#21

帖子 prettysnail » 2011-10-19 11:42

ljj_jjl2008 写了:这个我怀疑:开始故意顺序出“石头、剪刀、布”,迷惑计算机,出上几轮,让你的智能学会一个错误的顺序,然后再换过来,成“布、石头、剪刀”,是不是你的智能就会不灵了?
故意乱了顺序,不过它会记住你的全部输入,所以会根着你的输入变化慢慢调速,直到适应为止,所以偶发觉在前面好象很容易赢计算机,后面就被它猜准的越来越多,当然一般比例不是很大,在200步左右可能就赢你一点点,但前面它会输很多次哈。

也试过乱输入,不过好象最多就基本平分输赢,没时间仔细考虑,也就将就折腾一下玩吧。
头像
prettysnail
帖子: 198
注册时间: 2007-03-07 9:35

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#22

帖子 prettysnail » 2011-10-19 11:44

懒蜗牛Gentoo 写了:在已知算法的前提下,肯定能够迷惑计算机的。 :em04
:em06 主要是人的智力不能记住所以的输入过程,所以要推出计算机的下一个可能比较难。还有里面有随机数控制,也就是说本身也有一个偏离,就难以推准计算机了。
头像
prettysnail
帖子: 198
注册时间: 2007-03-07 9:35

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#23

帖子 prettysnail » 2011-10-19 11:49

懒蜗牛Gentoo 写了:
在200步后必输
很智能啊!!
这个办法是很呆的办法,主要是根据人都有习惯思维,在某一个比较状态下可能出的下一个状态的不是呈正态分布,总有最容易出现的可能,所以计算机就比较你以前的序列,找出这种组合下你出的最多的下一次输入。综合考了有一步的,两步的……5步的,再多没有考虑了,因为一般人不会连续出再更多的组合输入。

在刚开始运行时计算机是根本找不准的,因为这个分布要很长的输入才可能出现,当数据量多到一定时候,计算机就可以比较容易找到这些数列。如果你后面发生了改变或故意调整,计算机会根据你新输入的数列进行调速不同的加权值,再加上有很少量的随机函数控制,所以在很多步以后就容易命中了。
头像
月下叹逍遥
论坛版主
帖子: 33994
注册时间: 2010-10-07 14:23
系统: Archdows10
来自: 某系某星某洲某国某省某市
联系:

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#24

帖子 月下叹逍遥 » 2011-10-19 12:13

小用了一下啊加权,貌似不太智能 :em06 :em06 :em06
[c]#include"stdio.h"
#include"stdlib.h"
#include"time.h"
void main()
{
int p,c=1,n=0,k,x1=1,x2=1,x3=1;
int t[3][3]={{0,-1,1},{1,0,-1},{-1,1,0}};
float l=0.0;
printf("1,剪刀;2,石头;3,布;0,退出\n");
do
{
printf("请输入你的结果:");
scanf("%d",&p);
srand((unsigned)time(NULL));
c=(int)(rand()%3+1);
c=(int)(c*(1.0*x1+2.0*x2+3.0*x3)/n);
switch(p)
{
case 0:break;break;
case 1:k=t[p-1][c-1];x2++;n++;break;
case 2:k=t[p-1][c-1];x3++;n++;break;
case 3:k=t[p-1][c-1];x1++;n++;break;
default:
printf("输入有误,请重新输入:\n");break;
}
switch(k)
{
case 1:printf("你赢了!\n"),l++;break;
case -1:printf("你输了!\n");break;
case 0:printf("平局!\n");break;
}
}while(p!=0);
printf("一共进行了%d场比赛,胜率为:%f.",n,l/n);
}[/c]
浮生七十今三十,从此凄惶未可知
头像
prettysnail
帖子: 198
注册时间: 2007-03-07 9:35

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#25

帖子 prettysnail » 2011-10-19 15:58

月下叹逍遥 写了:小用了一下啊加权,貌似不太智能 :em06 :em06 :em06
[c]#include"stdio.h"
#include"stdlib.h"
#include"time.h"
void main()
{
int p,c=1,n=0,k,x1=1,x2=1,x3=1;
int t[3][3]={{0,-1,1},{1,0,-1},{-1,1,0}};
float l=0.0;
printf("1,剪刀;2,石头;3,布;0,退出\n");
do
{
printf("请输入你的结果:");
scanf("%d",&p);
srand((unsigned)time(NULL));
c=(int)(rand()%3+1);
c=(int)(c*(1.0*x1+2.0*x2+3.0*x3)/n);
switch(p)
{
case 0:break;break;
case 1:k=t[p-1][c-1];x2++;n++;break;
case 2:k=t[p-1][c-1];x3++;n++;break;
case 3:k=t[p-1][c-1];x1++;n++;break;
default:
printf("输入有误,请重新输入:\n");break;
}
switch(k)
{
case 1:printf("你赢了!\n"),l++;break;
case -1:printf("你输了!\n");break;
case 0:printf("平局!\n");break;
}
}while(p!=0);
printf("一共进行了%d场比赛,胜率为:%f.",n,l/n);
}[/c]

:em20 试着编译了一下,执行时冒出个总线错误?!“这是个神马错误?”
结果如下:
./sjb.out
1,剪刀;2,石头;3,布;0,退出
请输入你的结果:2
总线错误

另外,从代码上看楼主似乎是看对手经常出的结果来加权。感觉这个也成,人都有习惯思维哈。
头像
月下叹逍遥
论坛版主
帖子: 33994
注册时间: 2010-10-07 14:23
系统: Archdows10
来自: 某系某星某洲某国某省某市
联系:

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#26

帖子 月下叹逍遥 » 2011-10-19 16:17

prettysnail 写了:
月下叹逍遥 写了:小用了一下啊加权,貌似不太智能 :em06 :em06 :em06
[c]#include"stdio.h"
#include"stdlib.h"
#include"time.h"
void main()
{
int p,c=1,n=0,k,x1=1,x2=1,x3=1;
int t[3][3]={{0,-1,1},{1,0,-1},{-1,1,0}};
float l=0.0;
printf("1,剪刀;2,石头;3,布;0,退出\n");
do
{
printf("请输入你的结果:");
scanf("%d",&p);
srand((unsigned)time(NULL));
c=(int)(rand()%3+1);
c=(int)(c*(1.0*x1+2.0*x2+3.0*x3)/n);
switch(p)
{
case 0:break;break;
case 1:k=t[p-1][c-1];x2++;n++;break;
case 2:k=t[p-1][c-1];x3++;n++;break;
case 3:k=t[p-1][c-1];x1++;n++;break;
default:
printf("输入有误,请重新输入:\n");break;
}
switch(k)
{
case 1:printf("你赢了!\n"),l++;break;
case -1:printf("你输了!\n");break;
case 0:printf("平局!\n");break;
}
}while(p!=0);
printf("一共进行了%d场比赛,胜率为:%f.",n,l/n);
}[/c]

:em20 试着编译了一下,执行时冒出个总线错误?!“这是个神马错误?”
结果如下:
./sjb.out
1,剪刀;2,石头;3,布;0,退出
请输入你的结果:2
总线错误

另外,从代码上看楼主似乎是看对手经常出的结果来加权。感觉这个也成,人都有习惯思维哈。
母鸡啊。。。VC正常 :em06 :em06
浮生七十今三十,从此凄惶未可知
framnui
帖子: 243
注册时间: 2009-07-19 14:17

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#27

帖子 framnui » 2011-10-19 17:04

某位大神写完了麻烦把源码分享下吧
头像
懒蜗牛Gentoo
论坛版主
帖子: 7351
注册时间: 2007-03-02 17:36
系统: Linux Mint

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#28

帖子 懒蜗牛Gentoo » 2011-10-19 17:08

他们俩不是都分享了么?
虽然世上没有完美的东西,但这并不影响我们追求完美,因为只有偏执狂才TMD能成功。
10.04新手入门——笨兔兔讲述自己的故事
头像
prettysnail
帖子: 198
注册时间: 2007-03-07 9:35

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#29

帖子 prettysnail » 2011-10-20 8:51

月下叹逍遥 写了:
prettysnail 写了:
月下叹逍遥 写了:小用了一下啊加权,貌似不太智能 :em06 :em06 :em06
[c]#include"stdio.h"
#include"stdlib.h"
#include"time.h"
void main()
{
int p,c=1,n=0,k,x1=1,x2=1,x3=1;
int t[3][3]={{0,-1,1},{1,0,-1},{-1,1,0}};
float l=0.0;
printf("1,剪刀;2,石头;3,布;0,退出\n");
do
{
printf("请输入你的结果:");
scanf("%d",&p);
srand((unsigned)time(NULL));
c=(int)(rand()%3+1);
c=(int)(c*(1.0*x1+2.0*x2+3.0*x3)/n);
switch(p)
{
case 0:break;break;
case 1:k=t[p-1][c-1];x2++;n++;break;
case 2:k=t[p-1][c-1];x3++;n++;break;
case 3:k=t[p-1][c-1];x1++;n++;break;
default:
printf("输入有误,请重新输入:\n");break;
}
switch(k)
{
case 1:printf("你赢了!\n"),l++;break;
case -1:printf("你输了!\n");break;
case 0:printf("平局!\n");break;
}
}while(p!=0);
printf("一共进行了%d场比赛,胜率为:%f.",n,l/n);
}[/c]

:em20 试着编译了一下,执行时冒出个总线错误?!“这是个神马错误?”
结果如下:
./sjb.out
1,剪刀;2,石头;3,布;0,退出
请输入你的结果:2
总线错误

另外,从代码上看楼主似乎是看对手经常出的结果来加权。感觉这个也成,人都有习惯思维哈。
母鸡啊。。。VC正常 :em06 :em06
:em06 偶用的gcc编译的,看来估计是哪个库有差异哈。晕,好多年没折腾过VC了。
头像
月下叹逍遥
论坛版主
帖子: 33994
注册时间: 2010-10-07 14:23
系统: Archdows10
来自: 某系某星某洲某国某省某市
联系:

Re: [五星]程序开发一个石头剪刀布的人机对战程序

#30

帖子 月下叹逍遥 » 2011-10-20 8:53

srand拿出循环外,应该就可以了。。。
浮生七十今三十,从此凄惶未可知
回复