【编程游戏】划拳机器人,前面一贴的机器人都集中来了,继续PK。谨慎路过。
参考上一贴:【编程游戏】编写一个会划拳的机器人参加擂台赛,规则内详。路过有分。
不过上一帖的楼太高、打开太慢,所以我把那些机器人集中到这PK
打败对手最多的机器人获胜!奖励200分,其余酌情散掉。。。
划拳规则看完了,那我们就开始写一个会划拳的机器人吧!
那么一个会划拳的机器会做什么事情呢?其实就是两件:
第一件、出拳,即:自己出几个手指?自己猜合计是多少。
第二件、知道划拳的结果,即:对方出几个手指,对方猜合计是多少,是否获胜还是平局还是其他。
只要继承Drunkard这个类,重载Come()和Outcome()方法那么你就拥有了一个会划拳的机器人,参与这个游戏了!
【游戏规则】
1、比赛共1000局,即:出现胜负算一局,如出拳100次没有结果也算一局并双方均不得分;
2、赢一局得1分、输不扣分;
3、机器人执行中每出现一次异常,扣100分、对方加1分、记一局;
4、机器人执行中反应超时1000毫秒直接判负,每超时100毫秒,扣1分,超时10次以上直接判负;
5、自己得分高于对手并大于600分判胜;
6、自己得分为正数对手得分为负数判胜;
7、其他情况则判平。
具体执行的过程,算法的过程请参考Drunkery <T1, T2>类的实现
【入门提示】
1、机器人的命名建议是: <自己的id> + <第几个> + "号",如:Zswang一号、Zswang二号,当然你也可以用“长江七号”
注意不用重名,重名会给比赛带来不便
2、不允许修改Drunkard和Drunkery <T1, T2>;
3、机器人必须从Drunkard继承;
4、分析擂主代码是战胜擂主的关键;
5、打擂容易守擂难,大家自由发挥吧!
谢谢关注
先帖调试代码:
- C# code
using System;using System.Collections.Generic;using System.Text;namespace Huaquan{ /// <summary> /// 划拳结果 /// </summary> public enum Result { /// <summary> /// 未知,还没开始判断 /// </summary> Unknown, /// <summary> /// 平局,结果一致 /// </summary> Dogfall, /// <summary> /// 胜,猜中结果 /// </summary> Win, /// <summary> /// 负,对方猜中结果,自己没有猜中 /// </summary> Lost, /// <summary> /// 犯规, /// </summary> Foul, /// <summary> /// 超时,反应时间超出100毫秒 /// </summary> Overtime } /// <summary> /// 酒鬼类 /// </summary> public abstract class Drunkard { /// <summary> /// 出拳 /// </summary> /// <param name="ANumber">出的手指数</param> /// <param name="ASum">猜的合计</param> abstract public void Come(out int AFinger, out int ASum); /// <summary> /// 接收结果 /// </summary> /// <param name="AOtherFinger">对方出的手指数</param> /// <param name="AOtherSum">对方猜的合计</param> /// <param name="AOtherResult">对方划拳的结果</param> /// <param name="ASelfFinger">自己出的手指数</param> /// <param name="ASelfSum">自己猜的合计</param> /// <param name="ASelfResult">自己划拳的结果</param> abstract public void Outcome(int AOtherFinger, int AOtherSum, Result AOtherResult, int ASelfFinger, int ASelfSum, Result ASelfResult); } public class Zswang一号 : Drunkard { public override void Come(out int AFinger, out int ASum) { AFinger = 5; // 每次都出5 ASum = 10; // 每次都猜10 } public override void Outcome(int AOtherFinger, int AOtherSum, Result AOtherResult, int ASelfFinger, int ASelfSum, Result ASelfResult) { /* 这机器人不关心比赛结果 */ } } public class Zswang二号 : Drunkard { private Random random; public Zswang二号() { random = new Random(); } public override void Come(out int AFinger, out int ASum) { ASum = random.Next(10 + 1); //0-10 if (ASum < 5) // 别犯规 AFinger = random.Next(ASum + 1); else AFinger = random.Next(ASum - 5, 5 + 1); } public override void Outcome(int AOtherFinger, int AOtherSum, Result AOtherResult, int ASelfFinger, int ASelfSum, Result ASelfResult) { /* 这机器人也不关心比赛结果 */ } } /// <summary> /// 酒馆类 /// </summary> /// <typeparam name="T1">划拳机器人1</typeparam> /// <typeparam name="T2">划拳机器人2</typeparam> public class Drunkery<T1, T2> where T1 : Drunkard, new() where T2 : Drunkard, new() { /// <summary> /// 东家 /// </summary> private Drunkard eastPlayer; /// <summary> /// 西家 /// </summary> private Drunkard westPlayer; /// <summary> /// 东家积分 /// </summary> private int eastTotal; /// <summary> /// 西家积分 /// </summary> private int westTotal; /// <summary> /// 东家超时次数 /// </summary> private int eastOvertime; /// <summary> /// 西家超时次数 /// </summary> private int westOvertime; /// <summary> /// 划拳次数 /// </summary> public const int comeCount = 1000; /// <summary> /// 超时罚分 /// </summary> public const int overtimePenalty = 1; /// <summary> /// 异常罚分 /// </summary> public const int catchPenalty = 100; /// <summary> /// 开始比赛 /// </summary> public void Play() { #region 初始化 long vEastTick = Environment.TickCount; // 东家初始化的时间 eastPlayer = new T1(); vEastTick = Environment.TickCount - vEastTick; long vWestTick = Environment.TickCount; // 西家初始化的时间 westPlayer = new T2(); vWestTick = Environment.TickCount - vWestTick; eastTotal = 0; westTotal = 0; eastOvertime = 0; westOvertime = 0; #region 超时处理 if (vEastTick > 1000 || vWestTick > 1000) { if (vEastTick > 1000) Console.WriteLine("{0}初始化严重超时", typeof(T1).Name); if (vWestTick > 1000) Console.WriteLine("{0}初始化严重超时", typeof(T2).Name); return; } if (vEastTick > 100) { eastTotal -= overtimePenalty; eastOvertime++; } if (vWestTick > 100) { westTotal -= overtimePenalty; westOvertime++; } #endregion 超时处理 #endregion 初始化 #region 猜拳过程 for (int i = 0; i < comeCount; i++) { for (int j = 0; j < 100; j++) { int vEastFinger = 0, vWestFinger = 0; int vEastSum = 0, vWestSum = 0; Result vEastResult = Result.Unknown; Result vWestResult = Result.Unknown; #region 出拳 bool vEastCatch = false; vEastTick = Environment.TickCount; // 东家出拳的时间 try { eastPlayer.Come(out vEastFinger, out vEastSum); } catch // 出现异常 { vEastCatch = true; } vEastTick = Environment.TickCount - vEastTick; bool vWestCatch = false; vWestTick = Environment.TickCount; // 西家出拳的时间 try { westPlayer.Come(out vWestFinger, out vWestSum); } catch // 出现异常 { vWestCatch = true; } vWestTick = Environment.TickCount - vWestTick; #endregion 出拳 #region 出现异常 if (vEastCatch || vWestCatch) { if (vEastCatch) { eastTotal -= catchPenalty; westTotal++; } if (vWestCatch) { westTotal -= catchPenalty; eastTotal++; } break; } #endregion 出现异常
[解决办法]
这代码也太长了吧 LZ太历害了。。。。我用C#最多也只能写一个简单的小游戏。(爆炸小游戏)现在正在做着。。。还有些问题。。还得想想啊。
[解决办法]
太强大了,佩服
[解决办法]
搞晕了......
[解决办法]
收藏
[解决办法]
晕,这楼一起来就这么高。。。
楼住搞个代码下载吧,顺便改成winform的
复制结果也方便
[解决办法]
好多机器人,评分要麻烦了
[解决办法]
路过,接分哦!喝酒的时候玩过这个哦!
[解决办法]
太多的机器人,评分很麻烦,在想想哦!
[解决办法]
寒~~才十几楼就把滚动条压成硬币了...
[解决办法]
第一款采用多线程的机器人面世了。代码在下面贴出。
程序里单独开了一个线程,在对方演算的时候把主线程挂起1000毫秒,仅动作一次,就会导致对手严重超时而出局。但如果主线程开始挂起的时候双方对战已经结束了(电脑硬件很牛,双方算法很快的情况下),就没有意义了。如果延迟的时间不对(目前只能靠手工填个2,将来也许可以通过在Come和Outcome里计时来掌握这个时间值),就会造成自己被打出局的尴尬场面,这时你只能试着改改那个时间值。理论上可以打败任何算法延时在1毫秒以上的对手,但实际上并不一定会。另外简化了酒彪子一号的算法,确切的说是还原了,主要为了缩短算法时间,但成绩反而有些微小提升。例如能打平剪刀三号。但仍然无法打败yatobiaf_四号等杰出的算法,因为他们的算法耗时0毫秒,我的伎俩完全不起作用。而且我总是会被yatobiaf_四号把致命一击反弹到自己身上,确实佩服。
- C# code
static void Main(string[] args) { new Drunkery<酒彪子二号, Zswang一号>().Play(); new Drunkery<酒彪子二号, Zswang二号>().Play(); new Drunkery<酒彪子二号, zhangenter>().Play(); new Drunkery<酒彪子二号, zhangenter_Killer>().Play(); new Drunkery<酒彪子二号, Zswang三号>().Play(); new Drunkery<酒彪子二号, Yuwenge>().Play(); new Drunkery<酒彪子二号, Linxu一号>().Play(); new Drunkery<酒彪子二号, yunfeng007>().Play(); new Drunkery<酒彪子二号, hhhh>().Play(); new Drunkery<酒彪子二号, ren>().Play(); new Drunkery<酒彪子二号, hhhh2>().Play(); new Drunkery<酒彪子二号, 守擂>().Play(); new Drunkery<酒彪子二号, Linxu二号>().Play(); new Drunkery<酒彪子二号, 专打Linxu二号>().Play(); new Drunkery<酒彪子二号, 守擂二号>().Play(); new Drunkery<酒彪子二号, Linxu三号>().Play(); new Drunkery<酒彪子二号, 守擂三号>().Play(); new Drunkery<酒彪子二号, Linxu四号>().Play(); new Drunkery<酒彪子二号, Zswang三号_2>().Play(); new Drunkery<酒彪子二号, nik_amis>().Play(); new Drunkery<酒彪子二号, linxu五号>().Play(); new Drunkery<酒彪子二号, 专打Zswang三号>().Play(); new Drunkery<酒彪子二号, yunfeng007二号>().Play(); new Drunkery<酒彪子二号, 专打Zlinxu五号>().Play(); new Drunkery<酒彪子二号, 专打Zlinxu四号>().Play(); new Drunkery<酒彪子二号, 擂主4>().Play(); new Drunkery<酒彪子二号, Shunyao一号>().Play(); new Drunkery<酒彪子二号, yatobiaf二号>().Play(); new Drunkery<酒彪子二号, 剪刀一号>().Play(); new Drunkery<酒彪子二号, 专打yunfeng二号>().Play(); new Drunkery<酒彪子二号, yunfeng007二号_2>().Play(); new Drunkery<酒彪子二号, yatobiaf三号>().Play(); new Drunkery<酒彪子二号, ZhangenterCome>().Play(); new Drunkery<酒彪子二号, 剪刀二号>().Play(); new Drunkery<酒彪子二号, ZhangenterCome加强版>().Play(); new Drunkery<酒彪子二号, 剪刀三号>().Play(); new Drunkery<酒彪子二号, yatobiaf_四号>().Play(); new Drunkery<酒彪子二号, yatobiaf_四号修正版>().Play(); new Drunkery<酒彪子二号, xx_一号b>().Play(); new Drunkery<酒彪子二号, ZhangenterCome黄金版>().Play(); }
[解决办法]
路过。
[解决办法]
太强大了!!
学习了!!
[解决办法]
收藏~
[解决办法]
我为编程狂,你青岛的?
[解决办法]
强悍呀,除了佩服还是佩服!!
[解决办法]
在我的机器上酒彪子二号 得分为负数! 呵呵,这个线程的表现在各个机器上不一样啊
[解决办法]
建议楼主修改一个比赛规则,比如每个机器人都有自己的线程!判断的时候用messageQ来做结果接受!这个发挥的空间更大一些
[解决办法]
或者做个走迷宫机器人,或者干脆来个生命游戏,总之加强策略性!
[解决办法]
昨天弄了一晚上,基本上来说,还是随机最难取胜啊,这么快到瓶颈了,很难有发挥了
[解决办法]
这几天太忙了,也没有细看你们的逻辑
乱写了个,先撑下场面,避免大比分落败,嘿嘿-_-!
public class nik_amis2 : Drunkard
{
Random r = new Random(DateTime.Now.Millisecond);
static int n = 0;
public override void Come(out int AFinger, out int ASum)
{
switch (r.Next(3))
{
case 0:
Thread.Sleep(r.Next(2));
int c=DateTime.Now.Millisecond;
AFinger = c / 100; if (AFinger > 5) AFinger -= 5;
ASum = r.Next(0, 6) + AFinger;
break;
case 1:
Thread.Sleep(r.Next(2));
AFinger = r.Next(6);
ASum = r.Next(0, 6) + AFinger;
break;
default:
Thread.Sleep(r.Next(2));
Random m = new Random(r.Next(10000));
int[] f = new int[] { 5, 3, 2, 4, 1, 0 };
AFinger = f[r.Next(0, 120) / 20];
ASum = m.Next(0, 2) * 5 + AFinger;
if (r.Next(1000) > 500) ASum = m.Next(1, 6) + AFinger;
break;
}
}
public override void Outcome(int AOtherFinger, int AOtherSum, Result AOtherResult,
int ASelfFinger, int ASelfSum, Result ASelfResult)
{
}
}
[解决办法]
[解决办法]
过路+接分+UP
[解决办法]
一堆代码,看的晕了。。
[解决办法]
咔咔
[解决办法]
看了下那个东西,随机性太高了吧?通过研究上一个的算法然后写出一个可以打败它的,但是弄不好写到最后一个擂主的时候,它的机器人被第一个机器人打败了也说不准呢~
[解决办法]
支持一下~
[解决办法]
看的头晕,支持一下
[解决办法]
太牛了,
我,还没入门
没看懂
你们都很牛!
[解决办法]
楼主真强,收藏
------解决方案--------------------
强!18楼连出老千都整出来。
[解决办法]
[解决办法]
很好很强大
[解决办法]
都是强人,进来崇拜一下!
[解决办法]
MARK
[解决办法]
收藏,回去研究伴水的精华,:)
[解决办法]
强淫!学习
[解决办法]
收。。。希望以后多有类似这样的帖子。。。感觉不错
[解决办法]
有点晕
[解决办法]
看看,学习
[解决办法]
好强大,收藏了再说
[解决办法]
前几天也想过这个问题,不过没时间搞。还是楼主比较能付诸行动,先向你学习了。不过我对游戏规则有点想法:
1.随机数是否要规定必须用自己的函数生成,而不是调用random(),这样对擂主的挑战会更大点,不然基本靠随机了。
2.可不可以,实时更新最新的擂主是谁,他的代码,这样就不用看完贴才知道是咋回事,毕竟大家都很忙,玩玩而已,不必太累了。
3.提供界面程序。这样趣味性更大。
[解决办法]
晕了,看不明白,以前学的C#都忘了、、、
[解决办法]
新人,都晕了,,
你很厉害啊
[解决办法]
进来祟拜下。。
[解决办法]
占个位置,坐山观虎斗;
[解决办法]
弓虽
[解决办法]
崇拜牛人~学习中!
[解决办法]
是啊
[解决办法]
伴水兄,我在写出千的算法之前,也从道德上谴责了自己一顿。我也认为赢就应该光明正大。
但我写完后就不这么想了,写这个程序,最大的收获就是复习并学习了多线程的用法。我认为,这才是参与擂台的真正目的,提高自己的编程水平,或算数水平。目前算数方面没有什么突破的话,不如试试在编程角度百家争鸣。搞不好会有精彩的编程代码出现。
[解决办法]
mark 5.1放假来玩玩
[解决办法]
up
[解决办法]
有个想法,可惜我的功力不够,希望能看到高人的代码。
在自己的come()结束时更改程序的安全权限,让主程序不允许调用派生的方法,一调用对方的come()就抛异常,从而取胜。
还有就是调用API方法扫描主程序的变量堆栈,修改对方的计时参考值,是对方超时出局,可惜我也写不出来,期待高人!
[解决办法]
不地道不地道,都开始走邪门歪路了,对托管代码做手脚却是比较难...
[解决办法]
如此好贴 要顶
[解决办法]
太强大了,收藏学习。
[解决办法]
[解决办法]
昨天好像csdn上不了。我看了下我的yatobiaf_四号还有两个主要对手,一个是xx_一号b,他利用我代码平局时下一次肯定出一样的拳这点攻击我,我可以稍微修改一下就可以,而且他自身代码也有bug,经常出foul,所以不足为俱,一个是ZhangenterCome黄金版,这是个很强大的对手,他自己出的拳几乎很随机(只是不会出最危险的那一个), 让我不能轻易判断对手是否智能机器人,我现在还没有找到很好的克制办法,除非另外写一个很针对他的新机器人。
[解决办法]
jf
[解决办法]
[解决办法]
mark下,有时间来玩...
[解决办法]
额.. 这个太厉害了..
初学中.... 还有很多看不懂..
[解决办法]
[解决办法]
不知道 现在擂主是谁。。。
[解决办法]
接著崇拜下。很好很强大。
[解决办法]
还没有接触.
[解决办法]
出来实习,做了一个多月劳工后,看此贴感慨,这才是编程,好怀念大2时候DS老师组织的算法大赛啊。
[解决办法]
学习
[解决办法]
LZ请问两个一样的对打的时候,结果怎么都是0呢?
请问^是异或的意思吗?是只有一个犯规才执行的意思吗?
那假如两个人都犯规的情况呢?为什么不用||呢? 我很菜 别笑话俺呵呵
- C# code
#region 有一个人犯规 if (vEastResult == Result.Foul ^ vWestResult == Result.Foul) { #region 如犯规判则对方赢 if (vEastResult == Result.Foul) vWestResult = Result.Win; else if (vWestResult == Result.Foul) vEastResult = Result.Win; #endregion 如犯规判则对方赢 } #endregion 有一个人犯规
[解决办法]
有点意思,闲着可以试试
[解决办法]
ZhangenterCome黄金版得分:1000, Zswang一号得分:0
ZhangenterCome黄金版得分:508, Zswang二号得分:492
ZhangenterCome黄金版得分:880, zhangenter得分:120
ZhangenterCome黄金版得分:514, Zswang三号66楼得分:486
ZhangenterCome黄金版得分:1000, Yuwenge得分:0
ZhangenterCome黄金版得分:610, yunfeng007得分:390
ZhangenterCome黄金版得分:579, hhhh得分:421
ZhangenterCome黄金版得分:1000, ren得分:0
ZhangenterCome黄金版得分:999, hhhh2得分:1
ZhangenterCome黄金版得分:553, 守擂得分:447
ZhangenterCome黄金版得分:568, Linxu二号得分:432
ZhangenterCome黄金版得分:1000, 专打Linxu二号得分:0
ZhangenterCome黄金版得分:540, 守擂二号得分:460
ZhangenterCome黄金版得分:698, Linxu三号得分:302
ZhangenterCome黄金版得分:507, 守擂三号得分:493
ZhangenterCome黄金版得分:1000, Linxu四号得分:0
ZhangenterCome黄金版得分:999, Zswang三号得分:1
ZhangenterCome黄金版得分:1000, nik_amis得分:0
ZhangenterCome黄金版得分:700, linxu五号得分:300
ZhangenterCome黄金版得分:511, 专打Zswang三号得分:489
ZhangenterCome黄金版得分:677, yunfeng007二号得分:323
ZhangenterCome黄金版得分:521, 专打Zlinxu五号得分:479
ZhangenterCome黄金版得分:504, 专打Zlinxu四号得分:496
ZhangenterCome黄金版得分:507, 擂主4得分:493
ZhangenterCome黄金版得分:706, yunfeng007二号210楼得分:294
ZhangenterCome黄金版得分:1000, 剪刀一号得分:0
ZhangenterCome黄金版得分:637, 专打yunfeng二号得分:363
ZhangenterCome黄金版得分:690, yunfeng007二号188楼得分:310
ZhangenterCome黄金版得分:1000, ZhangenterCome得分:0
ZhangenterCome黄金版得分:653, 专打yunfeng二号226楼得分:347
ZhangenterCome黄金版得分:778, 剪刀二号得分:222
ZhangenterCome黄金版得分:542, ZhangenterCome加强版得分:458
ZhangenterCome黄金版得分:531, 酒彪子一号得分:469
ZhangenterCome黄金版得分:670, 剪刀三号得分:330
ZhangenterCome黄金版得分:982, Zswang四号得分:18
ZhangenterCome黄金版得分:850, yatobiaf_四号得分:150
ZhangenterCome黄金版得分:597, xx_一号得分:403
ZhangenterCome黄金版得分:635, yatobiaf_四号修正版得分:365
ZhangenterCome黄金版得分:658, xx_一号b得分:342
25胜14平0败,还有没有人在玩?
[解决办法]
楼上好像是新擂主了
[解决办法]
支持下
[解决办法]
学习
[解决办法]
谢谢LZ的回复
再请教一下
关于那个超时的处理 总共有三处都用到了
初始化的时候为什么要这样初始化
- C# code
long vEastTick = Environment.TickCount; // 东家初始化的时间 eastPlayer = new T1(); vEastTick = Environment.TickCount - vEastTick;
[解决办法]
random 随机函数 在出现的数字(固定数字段)当中有没有一定的概率比.
能否根据此概率比来做一点文章?
比如说,在1000次的比赛过程中,利用概率分析学方面的知识来分析
前100次对方所出招数,得出的结果立刻用来服务于后900次比赛!
(这也是我的一个小小想法,不知怎样^ 大家探讨下)
[解决办法]
- C# code
public class Yangzk008下忍版 : Drunkard { public class DrunkarCommon { public Dictionary<int, int> history = new Dictionary<int,int>(); } private Random random; private int Drunkardcount = 0; private Dictionary<int,DrunkarCommon> ComeOne = null; private int hFinger = 0; public Yangzk008下忍版() { random = new Random(); ComeOne = new Dictionary<int, DrunkarCommon>(); } public override void Come(out int AFinger, out int ASum) { AFinger = random.Next(6); if (this.ComeOne.ContainsKey(hFinger) && this.ComeOne[hFinger].history.Values.Count > 0 ) { int key = 0; int value = 0; Dictionary<int, int>.Enumerator IEnumer = ComeOne[hFinger].history.GetEnumerator(); while(IEnumer.MoveNext()) { if(IEnumer.Current.Value >= value) { key = IEnumer.Current.Key; } } ASum = AFinger + key; if(ASum > 10) { ASum = random.Next(key, 11 - key); AFinger = ASum - key; } } else { ASum = random.Next(AFinger,11); } } //ASum = random.Next(10 + 1); //0-10 //if (ASum < 5) // 别犯规 // AFinger = random.Next(ASum + 1); //else AFinger = random.Next(ASum - 5, 5 + 1); public override void Outcome(int AOtherFinger, int AOtherSum, Result AOtherResult, int ASelfFinger, int ASelfSum, Result ASelfResult) { if (Drunkardcount != 0) { if (!this.ComeOne.ContainsKey(hFinger)) { this.ComeOne.Add(hFinger, new DrunkarCommon()); } if (this.ComeOne[hFinger].history.ContainsKey(AOtherFinger)) { this.ComeOne[hFinger].history[AOtherFinger]++; } else { this.ComeOne[hFinger].history.Add(AOtherFinger, 1); } } hFinger = AOtherFinger; Drunkardcount++; Console.Write("对方出" + AOtherFinger + " 我出" + ASelfFinger + " 对方猜" + AOtherSum + " 我猜" + ASelfSum + " 结果" + ASelfResult + "\n"); } }
[解决办法]
留个名,以后来学习
------解决方案--------------------
路过
刚开始学C#
[解决办法]
路过..............
学习..................
[解决办法]
恩 我发了帖之后也猜是LZ所说的 构造机器人要耗费时间
另外 for (int j = 0; j < 100; j++)这个为什么要呢
Outcome这个抽象方法好象还用不上//
[解决办法]
18L严重范规哈,我们只能让程序走正路哈,如果讲范规的话,二个程序只能独立出来
分二个不同的进程进行比赛,还得搭个平台:)!
[解决办法]
LZ N 强:)
make !!!