轻松编写自己的拖拉机算法,进行算法大战

算法

  拖拉机游戏是一个广泛流传的拖拉机游戏,有的地区又叫做升级或者双抠(也有人说升级和拖拉机有所不同),拖拉机游戏在基本的规则上改变,主要是增加游戏的趣味性,比如有的地区可以一J到底,将庄家从J一下拉到2,也有的可以从A拉到J,Q到6等玩法。

  拖拉机大战是采用dotnet framework开发的一款拖拉机游戏,它实现了拖拉机游戏的基本规则,剔除了2是常主的功能,增加了一些亮主、流局的规则设置,还有一些扣底算法的选择、必打数字的设定、购到底的规则选择等,还可以使用机器人帮助您打牌,显示目前的进度情况等。

  在界面方面,拖拉机大战提供了牌面牌背制作功能,您只需轻点几下鼠标,就可以将您机器中喜爱的数码照片制作成牌面牌背,也可以在打牌的时候享受音乐的乐趣。

  对于dotnet程序开发者来说,您还可以利用拖拉机大战的插件机制,开发您自己的出牌算法插件。您只需实现一个算法接口,这个算法接口定义了两个方法,您只需实现这两个算法,就可以完成您自己的认为比较厉害的出牌算法。有趣的是,你还可以和其他人进行算法比赛,以决出谁的算法更为优秀。

  下面将介绍这个接口,以及一个简单的而且不太合法的算法实现。

  如果您要准备写一个拖拉机的算法,您就需要引入Kuaff.Tractor.Plugins.dll这个配件,它包含了Kuaff.Tractor.Plugins. IuserAlgorithm接口。

  这个接口的定义为:

using System;
using System.Collections;
using System.Text;

namespace Kuaff.Tractor.Plugins
{
    public interface IUserAlgorithm
    {
        /// <summary>
        /// 算法作者
        /// </summary>
        string Author
        {
            get;
        }
        /// <summary>
        /// 算法作者的email地址
        /// </summary>
        string Email
        {
            get;
        }
        /// <summary>
        /// 算法名称
        /// </summary>
        string Name
        {
            get;
        }
        /// <summary>
        /// 算法介绍
        /// </summary>
        string Description
        {
            get;
        }
 
        /// <summary>
        /// 首先出牌的算法。
        /// </summary>
        /// <param name="who">当前用户是谁,1为南家,2为北家,3为西家,4为东家</param>
        /// <param name="suit">当前主牌的花色,1为红心,2为黑桃,3为方片,4为梅花,5为王(无主)</param>
        /// <param name="rank">当前打几,0为打2,1为打3,2为打4........11为打K,12为打A,53为打王</param>
        /// <param name="master">当前谁为庄家,1为南家,2为北家,3为西家,4为东家</param>
        /// <param name="sendCards">当前一局各家已经出掉的牌,sendCards[0]为南家,sendCards[1]为北家,sendCards[2]为西家,sendCards[3]为东家</param>
        /// <param name="myCards">此用户手中的牌</param>
        /// <returns></returns>
        ArrayList ShouldSendCards(int who, int suit, int rank, int master, string[] sendCards, string myCards);
 
        /// <summary>
        /// 改自己出的牌时的算法(自己不是首家)
        /// </summary>
        /// <param name="who">当前用户是谁,1为南家,2为北家,3为西家,4为东家</param>
        /// <param name="suit">当前主牌的花色,1为红心,2为黑桃,3为方片,4为梅花,5为王(无主)</param>
        /// <param name="rank">当前打几,0为打2,1为打3,2为打4........11为打K,12为打A,53为打王</param>
        /// <param name="master">当前谁为庄家,1为南家,2为北家,3为西家,4为东家</param>
        /// <param name="whoIsFirst">谁首先出的牌,1为南家,2为北家,3为西家,4为东家</param>
        /// <param name="sendCards">当前一局各家已经出掉的牌,sendCards[0]为南家,sendCards[1]为北家,sendCards[2]为西家,sendCards[3]为东家</param>
        /// <param name="currentSendCards">首家以及自己的上家出的牌</param>
        /// <param name="myCards">此用户手中的牌</param>
        /// <returns></returns>
        ArrayList MustSendCards(int who, int suit, int rank, int master, int whoIsFirst, string[] sendCards, ArrayList[] currentSendCards, string myCards);
    }
}

  它首先定义了几个属性,这几个属性分别代表算法作者的名称以及email,算法的名称以及简单介绍。

  ShouldSendCards方法定义了首家出牌的算法。比如该东家首先出牌时,调用ShouldSendCards得到东家应该出的牌,接着调用MustSendCards得到北家应该出的牌,接着调用MustSendCards得到西家应该出的牌,接着调用MustSendCards得到南家应该出的牌,程序然后进行计算,得到下一次的首家,然后通过ShouldSendCards得到首家出的牌……周而复始,直到手中的牌出完。

  通过上面一段的介绍,你也明白了MustSendCards方法的含义,就是非首家应该出牌的算法。

  下面这个SampleUserAlgorithm类就是简单实现了这个接口的一个类。它的源代码可以在游戏的sources目录得到,编译好的配件放在plugins目录。您编译好的插件都必须放在plugins目录,游戏可以自行读取plugins文件下的dll文件,分析并得到编写的插件类。

  这个SampleUserAlgorithm类之所以简单,是因为它的首家出牌算法是随便挑一张牌就出了,而随牌算法假定了首家出的是一张牌,自己随便出了一张此花色的牌。您可以在这个插件上进行完善。

  游戏下载地址(包含了接口和一个简单的算法实现源代码):点击这里,  下载地址2,下载地址三,下载地址四,软件版本1.2.0.356.

  将您编写的插件编译成dll放在游戏的plugins目录,在程序中设置某一方采用您编写的算法,您就可以和程序中内置的算法进行对战了。如果您的算法不合法(比如首家出拖拉机,您手中有拖拉机却不出),说明您的算法还不完善,程序会自动将此方的算法更改为程序中内置的算法。

时间: 2024-10-21 19:29:37

轻松编写自己的拖拉机算法,进行算法大战的相关文章

template-c++ 编写类似于标准库中find算法的模板,非引用形参和引用形参的区别是什么

问题描述 c++ 编写类似于标准库中find算法的模板,非引用形参和引用形参的区别是什么 #include <iostream> #include <string> #include <vector> using namespace std; template<typename Init,typename T> Init find(Init begin,Init end,const T& val){ while(begin!=end){ if(val

轻松看懂机器学习十大常用算法

通过本篇文章可以对ML的常用算法有个常识性的认识,没有代码,没有复杂的理论推导,就是图解一下,知道这些算法是什么,它们是怎么应用的,例子主要是分类问题. 每个算法都看了好几个视频,挑出讲的最清晰明了有趣的,便于科普. 以后有时间再对单个算法做深入地解析. 今天的算法如下: 决策树 随机森林算法 逻辑回归 SVM 朴素贝叶斯 K最近邻算法 K均值算法 Adaboost 算法 神经网络 马尔可夫 1. 决策树 根据一些 feature 进行分类,每个节点提一个问题,通过判断,将数据分为两类,再继续提

数据结构教程 第三课 算法及算法设计要求

本课主题: 算法及算法设计要求 教学目的: 掌握算法的定义及特性,算法设计的要求 教学重点: 算法的特性,算法设计要求 教学难点: 算法设计的要求 授课内容: 一.算法的定义及特性 1.定义: ispass(int num[4][4]) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) if(num[i][j]!=i*4+j+1)/*一条指令,多个操作*/ return 0; return 1; }/*上面是一个类似华容道游戏中判断游戏是否结束的算法*/

《算法帝国》:被算法和算法交易改变的未来

当我们用崭新的视角去观察与思考,世界就会变成另外的模样.这是我们筹备举办"改变未来的算法与算法交易"研讨会的初衷. 美国雄霸全球依赖华尔街与硅谷等强大支柱,而近年来,算法对华尔街的渗透与控制体现出颠覆未来产业生态的力量.图灵公司出版的<算法帝国>一书中介绍,2000年,华尔街通过计算机程序交易的比率不足美国股市交易量的10%:2008年上半年,自动化电子交易占了全美股市交易量的60%:现在,华尔街70%以上的交易依靠所谓的黑盒子或者算法交易(闪电交易)运行.银行家和股票经纪

算法——贪心算法

贪心算法 贪心算法通过一系列的选择来得到问题的解.它所做的每一个选择都是当前状态下局部的最好选择,即贪心选择. 贪心选择的一般特征:贪心选择性质和最优子结构性质. 贪心选择性质: 所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到.这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别.在动态规划算法中,每步所做的选择往往依赖于相关子问题的解.因而只有在解出相关子问题后,才能做出选择.而在贪心算法中,仅在当前状态下做出最好选择,即局部最优选择.

缓存淘汰算法--LRU算法

[本文转载于缓存淘汰算法--LRU算法] 1. LRU 1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高". 1.2. 实现 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下: 1. 新数据插入到链表头部: 2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部: 3. 当链表满的时候,将链表尾部的数据丢弃. 1.3. 分析 [命中率] 当

重新想象 Windows 8 Store Apps (31) - 加密解密: 哈希算法, 对称算法

原文:重新想象 Windows 8 Store Apps (31) - 加密解密: 哈希算法, 对称算法 [源码下载] 重新想象 Windows 8 Store Apps (31) - 加密解密: 哈希算法, 对称算法 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 加密解密 hash 算法(MD5, SHA1, SHA256, SHA384, SHA512) hmac 算法(MD5, SHA1, SHA256, SHA384, SHA512) 本地数据的加密解

最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)

一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine-->mine..... 那么,就存在这样一个问题:给定一个单词作为起始单词(相当于图的源点),给定另一个单词作为终点,求从起点单词经过的最少变换(每次变换只会变换一个字符),变成终点单词. 这个问题,其实就是最短路径问题. 由于最短路径问题中,求解源点到终点的最短路径与求解源点到图中所有顶点的最短路径复

文本比较算法Ⅳ——Nakatsu算法

在"文本比较算法Ⅰ--LD算法"."文本比较算法Ⅱ--Needleman/Wunsch算法"中介绍的LD算法和LCS算法都是基于动态规划的.它们的时间复杂度O(MN).空间复杂度O(MN)(在基于计算匹配字符串情况下,是不可优化的.如果只是计算LD和LCS,空间占用可以优化到O(M)). Nakatsu算法在计算匹配字符串的情况下,有着良好的时间复杂度O(N(M-P))和空间复杂度O(N2),而且在采取适当的优化手段时,可以将空间复杂度优化到O(N),这是一个很诱人