[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

欢迎大家一起来开发【批处理版斗地主】

本帖最后由 cjiabing 于 2011-9-2 20:13 编辑

      斗地主游戏玩多了,心痒痒的也想用批处理写一个。见有人写批处理版的斗地主游戏,但都没见完工的。自己整理了下思路,有兴趣的朋友一起来共同开放吧!~以下是思路:

说明、进度等在三楼,主程序代码在二楼。

成功一半:代码在二楼2011年6月26日

这两天有空瞎整了一下,终于完成了自家牌分析——看自己有什么牌(还需完善),以及吃牌分析——看对家出的是什么牌。现在可以发牌开始玩游戏,不过还是自己在玩。电脑要稍微改进一下才能人机对战,不过也只能是初级的,因为分析牌型很费劲。

下一步:初级人机对战好高兴!~

-----------------------------------------------------------------------------------------------------------------


    一、我一楼二楼说得不够爽朗,我这里说一下电脑怎么出牌。

    首先要用到一个“接口”。什么是接口,就是几个玩家之间相互通信、相互理解、相互交流的一个变量。
    比如,我们把这个接口变量命名为“%JieKou%”。现在有三个玩家,上家出的牌是34567,这是一个顺子,那么,上家提供给另外两个玩家的接口是:JieKou=07顺子5
    下一家获得该接口变量,则分析这个牌是什么类型——顺子,最大的牌是什么——07,牌子有多少张——5张。
    下一家继续分析,自己有没有顺子牌——分析自己的牌型,看看自己有什么牌——这个我可以做出来——然后看看自己这副牌的接口是什么——我们假定为56789,接口是:MyJieKou=09顺子5
    然后比较下上家的接口和自家的接口,看自家的牌是否比上家大,如果大过继续判断时分是搭档(农民),如果不是,就可以出牌了,如果没有大过,则Pass。
    第三方同样获得第一家出牌的接口,并获得上一家牌的接口,如果上一家Pass了,就可以直接对比第一家,如果上一家出牌了,就分析自己的牌,并与上家的接口%MyJieKou% 比较大小。
    这样,三方通过接口变量,获得了比较的途径,也就获得了电脑出牌的途径。
    从以上看,需要做的主要有:1、分析上一家或下一家的牌,也就是分析其他人出的牌是什么牌;2、分析自己的牌,看自己的牌有什么类型的牌。
    其他需要考虑的功能:1、比较牌的大小;2、分析是否搭档(农民还是地主);3、如何中止吃牌,并决定谁可以出牌;如何获得分数……
    其实,以上我都基本上做完了,但由于一个小地方出错,心烦,找不到原因就此停下来了。回头检查,发现漏洞百出,想整合全部功能,都不好整合。我认为,还是要从以上提到的主要问题着手,解决了这两个问题,后面整合就容易了。

    二、顺便谈谈牌型分析——一个数学问题。

    主要的两个问题,第一个是知道对家出的是什么牌,第二个是知道自己有什么牌。这两个问题的关键就是进行牌型分析。斗地主的牌型很简单,他们之中包含着一定的数学关系,下面做简单分析。(注意,等差是指两个牌之间的差,即两个数相减的结果)

    牌  型          排除           张  数         等  差                 举例      
——————————————————————————————————————————————
    单张牌                          1                 0                     5
    一对牌        王炸弹          2                 0                     22
    三个牌                          3                 00                    333
    四个牌        三带一          4            001、100          9999、5551、4777
    五张牌      顺子、三代二   5            1111、0020       45678、99944
    六张牌      顺子、连对      6           11111、01010     346789、334455
    …………
    有可能计算各种牌型之间的等差关系、张数等等就可以区别去是那种牌了,甚至可以从一堆牌里面找出对牌、顺子、炸弹等,前提是这些牌必须排好顺序。
    我数学是最差的,但我偏偏遇到这种问题,希望各位数学学得好的,批处理也好的,能够解决以上这些问题。
    前面说到的牌型与接口的问题,就是这个接口变量的格式:决定牌大小的最大一张牌+牌型+张数
    好比飞机 46667778 ,它决定这副牌大小的最大的一张牌应该是7,它的牌型是飞机带单翅膀,牌的张数是8张,所以,它的接口变量应该是这样写的:JieKou=07飞单08
    07表示最大的一张牌,用两位数表示,因为J、Q、K可能超过10;飞单表示飞机带单翅膀,也可以用其他字母表示;张数最好也用两位数,因为有时候张数超过十张。

    分析牌型是个比较细致的工作,容易出错,可能一两天找不到原因都有。最近也忙点,这个工作暂时就停下来了,一旦有空会继续完成的。谢谢大家关注!~
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

本帖最后由 cjiabing 于 2011-6-27 01:28 编辑

初次整合,初见雏形

使用方法,进入游戏,输入代号出牌。比如,想出 三个6带一个K ,则输入“1116  1216  1416 1323”并回车。
代号可在游戏规则里查,暂时这样。
先把代码放这里,过段时间有空再处理。
现在的问题是,!pkvar!不懂出什么问题了,竟然不对了!~找不到原因!~可恶!~
下一步:确定两个电脑玩家如何自动出牌,利用!pkvar!作为接口~

  1. @echo off&setlocal enabledelayedexpansion
  2. ::mode con cols=86 lines=45
  3. title 批处理版斗地主扑克牌游戏
  4. ::本程序尝试整合发牌、叫地主、出牌、吃牌等功能。
  5. ::需要进一步优化各个子函数代码。
  6. ::优化接口:set var=path,!pkvar!
  7. ::优化标签。
  8. ::!pkvar!有误!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  9. ::---------------------------★代码分割线:主菜单和总台★---------------------------
  10. :ZongTai
  11. ::总台
  12. cls
  13. echo;
  14. echo;      批处理版斗地主-单机试验版
  15. echo;
  16. echo;
  17. echo;         1、开始游戏
  18. echo;         2、游戏规则展示
  19. echo;         3、退出
  20. echo;
  21. echo;
  22. echo;
  23. set input=
  24. set /p input=    请选择:
  25. if "%input%"=="" goto ZongTai
  26. if %input%==1 goto Play
  27. if %input%==2 call :YSStart
  28. if %input%==3 exit
  29. goto ZongTai
  30. :Play
  31. cls
  32. ::开始游戏
  33. call :Fapai
  34. ::呼叫发牌
  35. call :排序
  36. ::呼叫排序
  37. :Playing
  38. ::开始出牌。打牌的过程。
  39. :Play1
  40. echo;
  41. echo,--------------------------地主:%DiZhu%-----------------------------
  42. echo;
  43. set "MyPoker=%~dp0DDZTemp\%DiZhu%"
  44. set "PerPoker=%~dp0DDZTemp\%DiZhu%"
  45. call :Pkhuase "%MyPoker%"
  46. call :自家牌分析 %PerPoker%
  47. call :Chupai %MyPoker%
  48. :Play2
  49. echo;
  50. echo,--------------------------农民:%NongM1%-----------------------------
  51. echo;
  52. set "MyPoker=%~dp0DDZTemp\%NongM1%"
  53. set "PerPoker=%~dp0DDZTemp\%NongM1%"
  54. call :Pkhuase "%MyPoker%"
  55. call :自家牌分析 %PerPoker%
  56. call :Chupai %MyPoker%
  57. :Play3
  58. echo;
  59. echo,--------------------------农民:%NongM2%-----------------------------
  60. echo;
  61. set "MyPoker=%~dp0DDZTemp\%NongM2%"
  62. set "PerPoker=%~dp0DDZTemp\%NongM2%"
  63. call :Pkhuase "%MyPoker%"
  64. call :自家牌分析 %PerPoker%
  65. call :Chupai %MyPoker%
  66. goto Playing
  67. pause
  68. exit
  69. ::建立一个循环,假设玩家A\B\C,循环于三者,直至有一个玩家先出完牌。
  70. ::这个循环包括:地主出牌——下家分析桌面牌(上家牌)——分析自家牌(是否有可打的牌)——出牌——下家分析桌面牌……
  71. ::三家出牌,最大的区别是,玩家是通过输入控制过程,而电脑自动出牌。
  72. ::---------------------------★代码分割线:出牌机制★---------------------------
  73. ::改造该段代码,使之能通用,优化代码,减少临时文件。
  74. :Chupai
  75. ::出牌机制,首先对自家牌进行分析,找出有规律的牌。
  76. echo;
  77. echo;    轮到 【%1】 出牌。
  78. echo;    返回【Q】排序【P】不出【N】
  79. echo;    输入要出的牌的序号,回车出牌。多个牌用空格隔开。
  80. echo;
  81. set input=
  82. set /p input=    输入出牌:
  83. if "%input%"=="" goto Chupai
  84. if /i "%input%"=="Q" goto ZongTai
  85. if /i "%input%"=="N" goto :eof
  86. if /i "%input%"=="P" (
  87.     call :Pkhuase "%1"
  88.     goto Chupai
  89. )
  90. cd.>"%~dp0DDZTemp\DDZPlay0"
  91. cd.>"%1ed"
  92. cd.>"%1tmp"
  93. set a=0
  94. set b=0
  95. set c=
  96. ::判断输入的是否为自己手中的牌
  97. for %%i in (!input!) do (
  98.     set /a a+=1
  99.     for /f "usebackq tokens=*" %%a in ("%1") do (
  100.         if "%%a"=="" (echo;&echo Game over&echo;&pause&goto :eof)
  101.         if %%i==%%a (
  102.             echo;%%i>>"%1ed"
  103.             set /a b+=1
  104.         )
  105.     )&&set c=1
  106. )
  107. if "%c%"=="" (echo;&echo 游戏结束&echo;&pause&goto ZongTai)
  108. if not !a!==!b! (echo     !a!=/=!b!,数据有误,重新输入!&goto Chupai) else (echo;    !a!==!b!,数据重合,输入正确!)
  109. call :比较结果
  110. echo;上家的牌:!PkShangJia!
  111. ::上家的牌
  112. ::剩下的牌
  113. findstr /v  /g:"%1ed" "%1">>"%1tmp"
  114. cd.>"%1"
  115. type "%1tmp">>"%1"
  116. echo;
  117. echo;    【%1】打出的牌:
  118. ::type "%1ed">>"%~dp0DDZTemp\DDZPlay0"
  119. set PerPoker="%1ed"
  120. call :牌型分析 %PerPoker%&call :牌型分析结果
  121. echo;
  122. echo;    【%1】剩下的牌:
  123. call :Pkhuase "%1"
  124. echo;
  125. goto :eof
  126. ::---------------------------★代码分割线:机器出牌★---------------------------
  127. ::试图将处理地主的模式转换为电脑自动处理。只是在调用文件上和出牌上有所区别。
  128. :机器出牌
  129. goto :eof
  130. ::---------------------------★代码分割线:发牌机制★---------------------------
  131. ::发牌后,得到发到三个玩家手中的牌,并确定谁是地主、谁是农民。
  132. :Fapai
  133. ::准备工作
  134. echo;
  135. echo     正在发牌,请稍候……
  136. echo;
  137. if exist "%~dp0\DDZTemp" (del /q "%~dp0DDZTemp\*.*") else (md "%~dp0\DDZTemp")
  138. ::将54张扑克牌分成54行,每行一个数据输入到一个文本中,然后对该文本进行随机排序,并将牌按照顺序发到三个玩家手中。
  139. :Fapai1
  140. ::产生一副扑克牌
  141. echo 2899>"%~dp0DDZTemp\DDZFapai"
  142. for %%m in (2999 2130 2230 2330 2430) do echo;%%m>>"%~dp0DDZTemp\DDZFapai"
  143. for /l %%a in (3,1,14) do (
  144.     set pkp=%%a
  145.     set /a Pkfp=%%a+1110
  146.     set /a Pkmh=%%a+1210
  147.     set /a Pkhx=%%a+1310
  148.     set /a Pkht=%%a+1410
  149.     echo;!Pkfp!&echo;!Pkmh!&echo;!Pkhx!&echo;!Pkht!
  150. )>>"%~dp0DDZTemp\DDZFapai"
  151. call :Suijpx
  152. ::随机排序,"%~dp0DDZTemp\DDZFpsj"为随机牌。
  153. :Fapai2
  154. ::将牌发到三个玩家手中
  155. cd.>"%~dp0DDZTemp\DDZPlay1"&cd.>"%~dp0DDZTemp\DDZPlay2"&cd.>"%~dp0DDZTemp\DDZPlay3"
  156. set Pkfp=0
  157. for /f "usebackq tokens=*" %%a in ("%~dp0DDZTemp\DDZFpsj") do (
  158.     set /a Pkfp+=1
  159.     for /l %%i in (0,3,50) do (
  160.         set /a Pkff=!Pkfp!-%%i
  161.         if !Pkff!==1 echo;%%a>>"%~dp0DDZTemp\DDZPlay1"
  162.         if !Pkff!==2 echo;%%a>>"%~dp0DDZTemp\DDZPlay2"
  163.         if !Pkff!==3 echo;%%a>>"%~dp0DDZTemp\DDZPlay3"
  164.         if !Pkfp!==52 set pkdp1=%%a
  165.         if !Pkfp!==53 set pkdp2=%%a
  166.         if !Pkfp!==54 set pkdp3=%%a
  167.     )
  168. )
  169. :Fapai3
  170. ::发到每个玩家手中的牌
  171. ::此处进行重新排序。[`sort /+3 "%~dp0DDZTemp\DDZchupai"`]
  172. for /l %%i in (1,1,3) do (
  173.     echo,
  174.     echo,     玩家 %%i 的牌:
  175.     set pkp=
  176.     echo,
  177.     call :Pkhuase "%~dp0DDZTemp\DDZPlay%%i"
  178. )
  179. echo,
  180. :JiaoDiZhu
  181. ::此处增加叫地主与积分翻倍计算。
  182. ::采用随机地主形式。玩家DDZPlay1为操作者,其余两个为电脑。
  183. ::但在后面的操作中,玩家为随机的一个,剩下的两个为电脑。
  184. set tm=
  185. set DiZhu=
  186. set "tm=%time:~10,1%"
  187. if %tm% geq 0 if %tm% leq 3 set DiZhu=DDZPlay1&set NongM1=DDZPlay2&set NongM2=DDZPlay3
  188. if %tm% geq 4 if %tm% leq 6 set DiZhu=DDZPlay2&set NongM1=DDZPlay1&set NongM2=DDZPlay3
  189. if %tm% geq 7 if %tm% leq 9 set DiZhu=DDZPlay3&set NongM1=DDZPlay1&set NongM2=DDZPlay2
  190. :Fapai4
  191. ::底牌
  192. echo;!pkdp1!>>"%~dp0DDZTemp\%DiZhu%"
  193. echo;!pkdp2!>>"%~dp0DDZTemp\%DiZhu%"
  194. echo;!pkdp3!>>"%~dp0DDZTemp\%DiZhu%"
  195. echo,
  196. echo,    %DiZhu% 是地主
  197. echo,
  198. if /i not %DiZhu% ==  DDZPlay1 echo,    DDZPlay1 是农民
  199. if /i not %DiZhu% ==  DDZPlay2 echo,    DDZPlay2 是农民
  200. if /i not %DiZhu% ==  DDZPlay3 echo,    DDZPlay3 是农民
  201. echo,
  202. echo     底牌是:
  203. echo,
  204. for /l %%i in (1,1,3) do (
  205.     set pkp=!pkdp%%i!
  206.     call :HuaSe
  207.     if "!pkp:~2,1!"=="0" (echo     !Pkp1!  !Pkp2!  !pkp:~3,1!  !pkdp%%i!) else (echo     !Pkp1!  !Pkp2!  !pkp:~2,2!  !pkdp%%i!)
  208. )
  209. echo,
  210. ::处理临时文件
  211. cd.>"%~dp0DDZTemp\DDZFpsjx"&cd.>"%~dp0DDZTemp\DDZFpsj"&cd.>"%~dp0DDZTemp\DDZFapai"
  212. goto :eof
  213. ::---------------------------★代码分割线:排序★---------------------------
  214. :排序
  215. ::已设定为三个玩家排序,直接调用即可。
  216. ::对三个玩家的牌进行排序,排序是必须的。
  217. for /l %%i in (1,1,3) do (
  218.     cd.>"%~dp0DDZTemp\DDZPx"
  219.     sort /+3 "%~dp0DDZTemp\DDZPlay%%i">>"%~dp0DDZTemp\DDZPx"
  220.     cd.>"%~dp0DDZTemp\DDZPlay%%i"
  221.     type "%~dp0DDZTemp\DDZPx">>"%~dp0DDZTemp\DDZPlay%%i"
  222. )
  223.     cd.>"%~dp0DDZTemp\DDZPx"
  224. echo,
  225. goto :eof
  226. :Suijpx
  227. ::随机排序——或许要减少临时文件、提高速度,可优化以下项目:
  228. ::set ddd=for——去掉一个临时文件
  229. ::call :Suijipx——去掉外部处理
  230. ::优化为调用模式。
  231. set sjpx=
  232. cd.>"%~dp0DDZTemp\DDZFpsjx"&cd.>"%~dp0DDZTemp\DDZFpsj"
  233. for /f "tokens=1,* delims=:" %%a in ('findstr /n .* "%~dp0DDZTemp\DDZFapai"') do (
  234.     if not "%%a"=="" set sjxh=%%a
  235.     call :Suijipx
  236.     echo;!sjpx!:%%b>>"%~dp0DDZTemp\DDZFpsjx"
  237. )>nul 2>nul
  238. for /f "tokens=1,* delims=:" %%a in ('sort "%~dp0DDZTemp\DDZFpsjx"') do echo;%%b>>"%~dp0DDZTemp\DDZFpsj"
  239. goto :eof
  240. :Suijipx
  241. set /a sjpx=!sjxh!+%random:~-2,2%
  242. goto :eof
  243. ::---------------------------★代码分割线:自家牌分析★---------------------------
  244. ::分析自己的牌,看自己有什么牌
  245. ::牌的关系只有两种,要么相等——等差等于0,要么相差——等差等于1。
  246. ::调用:call :自家牌分析 "%~dp0DDZTemp\%DiZhu%"
  247. ::获得分析结果:!pkvar!
  248. :自家牌分析
  249. echo;
  250. echo     【%MyPoker%】自家牌分析
  251. echo;
  252. set pkvar=
  253. set pkvar1=
  254. set pkvar0=
  255. set pkvar2=
  256. set pkvar3=
  257. set pk1=
  258. set pk2=
  259. set pk3=
  260. set pk4=
  261. set pk5=
  262. set dc=0
  263. set nb=0
  264. set nb1=0
  265. set nb0=0
  266. for /f "usebackq" %%a in (%1) do if not "%%a"=="" (
  267.     set pk1=%%a
  268.     set /a dc=!pk1:~2,2!-!pk2:~2,2!
  269.     if !dc!==0 (
  270.         set /a nb0+=1
  271.         set pkvar0=!pk2! !pk1!
  272.         set pkvar2=!pk3! !pk2! !pk1!
  273.         set pkvar3=!pk4! !pk3! !pk2! !pk1!
  274.         if !nb0! == 1 if not "!pk2!"=="" set pkvar=!pk1:~2,2!一对子2&echo !pkvar!  一对  pkvar0=!pkvar0!
  275.         if !nb0! == 2 if not "!pk3!"=="" set pkvar=!pk1:~2,2!三张牌3&echo !pkvar!  三个  pkvar2=!pkvar2!
  276.         if !nb0! == 3 if not "!pk4!"=="" set pkvar=!pk1:~2,2!小炸弹4&echo !pkvar!  炸弹  pkvar3=!pkvar3!
  277.     )
  278.     if !dc!==1 (
  279.         set /a nb1+=1
  280.         set nb0=0
  281.         set pkvar1=!pk1! !pkvar1!
  282.         if !nb1! geq 5 set pkvar=!pk1:~2,2!长顺子!nb1!&echo !pkvar!  顺子  pkvar1=!pkvar1!
  283.     )
  284.     if not !dc!==0 if not !dc!==1 (set nb1=0&set nb0=0&set pkvar1=&set pkvar0=)
  285. rem echo %%a : !pk1! !pk2! !pk3! !pk4! !pk5!$$ pkvar=!pkvar! ##!nb0!=!nb1!##&pause
  286.     set pk5=!pk4!
  287.     set pk4=!pk3!
  288.     set pk3=!pk2!
  289.     set pk2=!pk1!
  290. )
  291. goto :eof
  292. ::---------------------------★代码分割线:牌面转换★---------------------------
  293. ::调用方法 set HuaSe="%~dp0DDZTemp\%DiZhu%"&call :Pkhuase
  294. ::`sort /+3 %HuaSe%`
  295. :Pkhuase
  296. for /f "usebackq tokens=*" %%a in (%1) do (
  297.     set pkp=%%a
  298.     call :HuaSe
  299.     if "!pkp:~2,1!"=="0" (echo     !Pkp1!  !Pkp2!  !pkp:~3,1!  %%a) else (echo     !Pkp1!  !Pkp2!  !pkp:~2,2!  %%a)
  300. )
  301. ::牌面转换。将代码转换为牌面花色,可以在处理完所有数据后再转换。
  302. goto :eof
  303. :HuaSe
  304. set Pkp2=
  305. set Pkp1=
  306. if "!pkp:~0,1!"=="1" set Pkp1=副牌
  307. if "!pkp:~0,1!"=="2" set Pkp1=主牌
  308. if "!pkp:~1,1!"=="1" set Pkp2=方片 
  309. if "!pkp:~1,1!"=="2" set Pkp2=草花 
  310. if "!pkp:~1,1!"=="3" set Pkp2=红桃 
  311. if "!pkp:~1,1!"=="4" set Pkp2=黑桃 
  312. if not "!pkp:~0,2!"=="28"  (
  313.     if not "!pkp:~0,2!"=="29" (set /a pkp=!pkp!-10) else (set pkp=大王大王)
  314. ) else (set pkp=小王小王)
  315. if "!pkp:~2,2!"=="11" set pkp=JJJ
  316. if "!pkp:~2,2!"=="12" set pkp=QQQ
  317. if "!pkp:~2,2!"=="13" set pkp=KKK
  318. if "!pkp:~2,2!"=="14" set pkp=AAA
  319. if "!pkp:~2,2!"=="20" set pkp=222
  320. goto :eof
  321. ::---------------------------★代码分割线:桌面牌分析★---------------------------
  322. ::分析上家打出的牌,分析自己打出的牌,看看两者哪个大,下家出牌是否合乎规则。稍微复杂了点,需要改进。
  323. ::可喜的是,最后找到了各种牌对比的接口“!pkvar!”。
  324. ::与自家牌分析有所差距,自家牌分析不受牌的张数影响,而桌面牌分析则考虑牌的张数。
  325. ::普通调用示例:
  326. :: set PerPoker="%~dp0DDZTemp\%DiZhu%ed"
  327. :: call :牌型分析&call :牌型分析结果
  328. :牌型分析
  329. ::用于分析桌面上的牌(包括自家和对家的)的牌型,需要确定牌的张数和顺序,区别于自家牌分析。
  330. set pk1=
  331. set pk2=
  332. set pk3=
  333. set pk4=
  334. set pk5=
  335. set zs=0
  336. set dc=
  337. set dc1=
  338. set dc2=
  339. set dc3=
  340. set dc4=
  341. set nb=0
  342. set nb0=0
  343. set nb1=0
  344. set tj=0
  345. set tj1=0
  346. set tj2=0
  347. set pkstr=
  348. set pkvar=
  349. for /f "usebackq" %%a in (%1) do if not "%%a"=="" set /a zs+=1
  350. if !zs!==1 for /f "usebackq" %%a in (%1) do set pkvar=%%a单张牌1&set pkvar=!pkvar:~2,8!&goto :eof
  351. if "!zs!" gtr "1" for /f "usebackq" %%a in (%1) do if not "%%a"=="" (
  352.     set pk1=%%a
  353.     if not "!pk2!"=="" if not "!pk1!"=="" set /a dc=!pk1:~2,2!-!pk2:~2,2!
  354.     if not "!pk3!"=="" if not "!pk2!"=="" set /a dc1=!pk2:~2,2!-!pk3:~2,2!
  355.     if not "!pk4!"=="" if not "!pk3!"=="" set /a dc2=!pk3:~2,2!-!pk4:~2,2!
  356.     if not "!pk5!"=="" if not "!pk4!"=="" set /a dc3=!pk4:~2,2!-!pk5:~2,2!
  357.     if not "!pk1!"=="" if not "!pk5!"=="" set /a dc4=!pk1:~2,2!-!pk5:~2,2!
  358.     set pk5=!pk4!
  359.     set pk4=!pk3!
  360.     set pk3=!pk2!
  361.     set pk2=!pk1!
  362.     if "!dc!"=="0" if "!zs!"=="2" (if "!pk1:~2,2!"=="99" (set pkvar=99王炸弹2) else (set pkvar=!pk1:~2,2!一对子2)&goto :eof) else (set tj1=!pk1:~2,2!)
  363.     if "!dc!"=="0" if "!dc1!"=="0" (if "!zs!"=="3" (set pkvar=!pk1:~2,2!三张牌!zs!&goto :eof) else (set /a tj+=1&set tj2=!pk1:~2,2!))
  364.     if "!zs!"=="4" if "!dc!"=="0" if "!dc1!"=="0" if "!dc2!"=="0" set pkvar=!pk1:~2,2!小炸弹4
  365.     if "!zs!"=="4" if "!dc!"=="0" if "!dc1!"=="0" if not "!dc2!"=="0" set pkvar=!pk2:~2,2!三带一4
  366.     if "!zs!"=="4" if not "!dc!"=="0" if "!dc1!"=="0" if "!dc2!"=="0" set pkvar=!pk2:~2,2!三带一4
  367.     if "!zs!"=="5" if "!dc!"=="0" if not "!dc1!"=="0" if "!dc2!"=="0" if "!dc3!"=="0" set pkvar=!pk4:~2,2!三带对5
  368.     if "!zs!"=="5" if "!dc!"=="0" if "!dc1!"=="0" if not "!dc2!"=="0" if "!dc3!"=="0" set pkvar=!pk4:~2,2!三带对5
  369.     if "!zs!"=="5" if "!dc!"=="0" if not "!dc1!"=="0" if "!dc2!"=="0" if !dc3!==0 if not !dc4!==0 set pkvar=!pk4:~2,2!四带一5
  370.     if "!zs!"=="5" if "!dc!"=="0" if "!dc1!"=="0" if "!dc2!"=="0" if not !dc3!==0 if not !dc4!==0 set pkvar=!pk4:~2,2!四带一5
  371.     if "!zs!"=="6" if "!dc!"=="0" if not "!dc1!"=="0" if "!dc2!"=="0" if !dc3!==0 if not !dc4!==0 set pkvar=!pk4:~2,2!四带对6
  372.     if "!zs!"=="6" if "!dc!"=="0" if  "!dc1!"=="0" if "!dc2!"=="0" if not !dc3!==0 if not !dc4!==0 set pkvar=!pk4:~2,2!四带对6
  373.     if !zs! gtr 7  if !dc!==0 if !dc1!==0 if !dc2!==1 if !dc3!==0  if !dc4!==1 set pkvar=!pk1:~2,2!飞机带!zs!
  374.     if !zs! gtr 7  if !dc!==0 if !dc1!==1 if !dc2!==0 if !dc3!==0  if !dc4!==1 set pkvar=!pk1:~2,2!飞机带!zs!
  375.     if !zs! geq 5 if !dc!==1  if !dc1!==1  if !dc2!==1  if !dc3!==1  if !dc4!==4 set pkvar=!pk1:~2,2!长顺子!zs!
  376.     if !zs! gtr 5 if "!dc!"=="0" if "!dc1!"=="1" if "!dc2!"=="0" if "!dc3!"=="1" if !dc4!==2 set pkvar=!pk1:~2,2!连对顺!zs!
  377.     if not "!dc!"=="" if not !dc!==0 if not !dc!==1 set /a nb+=1
  378.     if not "!dc!"=="" if !dc!==1 set /a nb1+=1
  379.     if not "!dc!"=="" if !dc!==0 set /a nb0+=1
  380. )
  381. )>nul 2>nul
  382. echo,
  383. if "!pkvar!"=="长顺子" if !nb1! == 11 if !nb! == 0 (if !nb0! == 0 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=)
  384. if "!pkvar!"=="连对顺" (
  385.     set /a jd=!nb0!*2
  386.     if !jd!==!zs! (if !nb! == 0 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=)
  387. )
  388. set dd=
  389. ::此处有冲突,会覆盖上面的结果。
  390. if !tj! gtr 0 for /l %%a in (2,1,20) do if !tj!==%%a (
  391.     set /a dd=%%a*3
  392.     if !dd!==!zs! set pkvar=!pk2:~2,2!三顺子!zs!
  393. )
  394. if "!pkvar!"=="四带一" (
  395.     if !nb0! == 4 (set pkvar=!pkvar!!zs!) else (set pkvar=)
  396. )
  397. if "!pkvar!"=="四带对" (
  398.     if !nb0! == 5 (set pkvar=!pkvar!!zs!) else (set pkvar=)
  399. )
  400. rem if !zs! gtr 7  (
  401.     if "!zs!"=="8"  if !tj!==2 (if !nb0! equ 2 (if !nb1! equ 1 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=))
  402.     if "!zs!"=="10" if !tj!==2 (if !nb0! geq 4 (if !nb1! geq 1 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=))
  403.     if "!zs!"=="12" if !tj!==3 (if !nb0! geq 3 (if !nb1! geq 2 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=))
  404.     if "!zs!"=="15" if !tj!==3 (if !nb0! geq 9 (if !nb1! geq 2 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=))
  405.     if "!zs!"=="16" if !tj!==4 (if !nb0! geq 4 (if !nb1! geq 3 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=))
  406.     if "!zs!"=="20" if !tj!==4 (if !nb0! geq 12 (if !nb1! geq 3 (set pkvar=!pkvar!!zs!) else (set pkvar=)) else (set pkvar=))
  407. )
  408. goto :eof
  409. :牌型分析结果
  410. ::将对家出的牌转换为一个简单的数字——!pkvar!。最大的牌+牌的类型+牌的张数
  411. ::set PkShangJia=
  412. for /f "usebackq" %%a in (%PerPoker%) do set /p pkstr=%%a <nul
  413. if not "!pkvar!"=="" (echo ——分析结果:【!pkvar:~2,3!】&set PkShangJia=!pkvar!) else (echo ——分析结果:【不符合规则的牌!】&goto Chupai)
  414. echo pkvar:!pkvar!:!pkstr!  zs:!zs!  =  nb:!nb!  +  nb0:!nb0!  +  nb1:!nb1!
  415. echo,
  416. goto :eof
  417. :比较结果
  418. ::出牌与吃牌分析结果
  419. ::分析上家的牌型和自家的牌型,然后比较两者是否相同牌型,自家是否比上家牌大。
  420. echo,     
  421. echo,    (最后比较结果:【!PkShangJia!】 == 【!pkvar!】 【"!PkShangJia:~0,2!" lss "!pkvar:~0,2!"】)
  422. echo,
  423. if "!PkShangJia:~0,2!" lss "!pkvar:~0,2!" (if "!PkShangJia:~2,3!"=="!pkvar:~2,3!" if "!PkShangJia:~5,2!" == "!pkvar:~5,2!" echo  你的牌大过对家) else (echo  你出的牌不符合规则&goto Chupai)
  424. echo,
  425. goto :eof
  426. ::---------------------------★代码分割线:规则演示★---------------------------
  427. :YSStart
  428. ::总台
  429. cls
  430. call :Fupai
  431. call :Zhupai
  432. call :Wangpai
  433. pause
  434. cls
  435. call :Paixing
  436. pause
  437. goto :eof
  438. :Fupai
  439. ::展示副牌大小顺序
  440. ::副牌从3到10,用11代替J,12代替Q,13代替K,14代替A,列出大小顺序。
  441. ::加四位数1110、1210、1310、1410等转换为四位代号。四位代号更具编辑性。
  442. echo,
  443. echo,    一、展示副牌大小顺序
  444. echo,
  445. echo    方片(代号)    梅花(代号)     红心(代号)     黑桃(代号)
  446. echo;================================================================
  447. for /l %%a in (3,1,14) do (
  448.     set Pks=%%a
  449.     if %%a==11 set Pks=J
  450.     if %%a==12 set Pks=Q
  451.     if %%a==13 set Pks=K
  452.     if %%a==14 set Pks=A
  453.     set /a Pkfp=%%a+1110
  454.     set /a Pkmh=%%a+1210
  455.     set /a Pkhx=%%a+1310
  456.     set /a Pkht=%%a+1410
  457.     echo     !Pks!(!Pkfp!)     !Pks!(!Pkmh!)      !Pks!(!Pkhx!)      !Pks!(!Pkht!)  
  458. )
  459. echo;================================================================
  460. goto :eof
  461. :Zhupai
  462. ::展示主牌大小顺序
  463. echo,
  464. echo,    二、展示主牌大小顺序
  465. echo,
  466. echo     方片(代号)     梅花(代号)     红心(代号)      黑桃(代号)
  467. echo;================================================================
  468. echo      2  2130       2  2230       2  2330        2  2430  
  469. goto :eof
  470. :Wangpai
  471. ::展示王牌大小顺序
  472. echo,
  473. echo,    三、展示王牌大小顺序
  474. echo,
  475. echo;================================================================
  476. echo     小王  2899      大王  2999
  477. echo;================================================================
  478. echo,
  479. goto :eof
  480. :Paixing
  481. ::牌型
  482. echo,
  483. echo,    四、展示牌型和大小规则
  484. echo,
  485. echo;================================================================
  486. echo     (1) 单张:大小顺序从3(最小)到大王(最大);
  487. echo     (2) 一对:两张大小相同的牌,从3(最小)到2(最大);
  488. echo   (3) 三张:三张大小相同的牌,例如9-9-9;
  489. echo   (4) 三带一:根据三张的大小来比较,例如9-9-9-3盖过8-8-8-A;
  490. echo     (5) 三带对:根据三张的大小来比较,例如Q-Q-Q-6-6盖过10-10-10-K-K;
  491. echo   (6) 顺子:至少5张连续大小的牌,例如8-9-10-J-Q;
  492. echo   (7) 连对:至少3个连续大小的对子,例如10-10-J-J-Q-Q-K-K;
  493. echo   (8) 飞机:至少2个连续大小的三张,例如4-4-4-5-5-5;
  494. echo   (9) 飞机带翅膀:例如7-7-7-8-8-8-3-6,例如8-8-8-9-9-9-4-4-J-J;
  495. echo   (10) 四带二:例如6-6-6-6-8-9,例如J-J-J-J-9-9-Q-Q。
  496. echo     (11) 炸弹:四张大小相同的牌,比王炸小,比其他牌大;A-A-A-A;
  497. echo   (12) 王炸:一对王,这是最大的组合,能够盖过包括炸弹在内的任何牌型;
  498. echo     (13) 除三带一、四带一外,王牌不能和副牌混用。2不能和副牌组成顺子和连对。
  499. echo     (14) 什么类型的牌用什么类型的牌打,但炸弹能够打任何牌。
  500. echo;================================================================
  501. goto :eof
复制代码
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

本帖最后由 cjiabing 于 2011-9-2 19:46 编辑

                                                第一章  游戏规则和过程模拟
一、牌子大小(游戏规则)

1、制定游戏规则,这个可以借鉴QQ的斗地主游戏。批处理要做的就是,用批处理再现这些规则。
2、用批处理再现整付斗地主扑克牌大小顺序,分成主牌和副牌。——已完成
3、用批处理呈现扑克牌的花色、图案等,即方片、草花、红桃和黑桃,——这个似乎有人做出来了,期待合作。——进行中

二、发牌机制
1、将一副扑克牌54张随机分发到三个玩家手中,农民手中各17张,地主手中20张。——已完成

2、地主选择、发牌顺序等。——期待


三、牌面分析
主要考虑出牌的速度和牌子的强度,包括进攻和防守,列出最优方案和替代方案。这个思路决定程序的智能程度和厉害程度。
1、分析牌子中是否存在炸弹,主要包括王炸和四张牌炸——已完成
2、分析牌子中是否存在顺子,多少个顺子,顺子后散牌多少——进行中
3、分析牌子中三带一、三带二的情形,统计数量并考虑散牌——已完成

4、分析牌子中的对牌,统计数量并比较大小——进行中
5、分析牌子中的散牌,统计数量并比较大小——进行中

6、比较顺子、三带一、对牌、单牌等之间的最优方案——进行中
7、做出最优出牌方案和替补出牌方案——进行中

(时间:2011年5月30日;接单人:cjiabing;状态:进行中)

--------------------------------------进度线-------------------------------------
三、出牌机制
1、制定出牌顺序——同上

2、如何分析对方的牌?——完成

3、如何根据对方的牌出牌?——进行中

4、如何对剩下的牌进行分析?——进行中

5、如何对已经出过的牌和未出过的牌进行分析?——进行中

(时间:2011年6月1日;接单人:cjiabing;状态:进行中)

--------------------------------------进度线-------------------------------------


四、过程分析

1、如何进攻和防守?

2、如果是农民,如何配合搭档?

3、游戏即将结束时,如何进行合理攻防?


五、分值计算
六、单机和联机,通信

七、其他问题

1、玩家的牌临时存储(不一定必要,但如必要请使用类似以下的文件名):
玩家(角色)     存储位置                                       出过的牌记录    大家没有出过的牌   最佳出牌方案      替补方案            
玩家1(地主):"%~dp0\DDZTemp\DDZPlay1"       DDZPlay1log     DDZPlay1un      DDZPlay1best    DDZPlay1re
玩家2(农民):"%~dp0\DDZTemp\DDZPlay2"       DDZPlay2log     DDZPlay2un      DDZPlay2best    DDZPlay2re
玩家3(农民):"%~dp0\DDZTemp\DDZPlay3"       DDZPlay3log     DDZPlay3un      DDZPlay3best    DDZPlay3re
桌面(用于交换信息的平台,比如出牌和吃牌):"%~dp0\DDZTemp\DDZPlay0"  
2、说明、进度等在一楼,主程序代码在二楼,其它代码在三楼。



                                                        第二章  创作要求和代码规范


既然是共同开发,那就要有共同的规范和语言,制定共同的要求和原则。


一、代码规范可读

首先要求可读性,也就是便于他人阅读。因为是大家共同开发的,太深奥的代码不容易理解,不方便他人继续开发。
可读性包括标签和变量的规范,包括缩进、注解,包括必要的展开。特别是一些可能不容易理解的地方,最好将代码展开分解。

1、标签名

头字母大写,其它相应小写。按中文拼音或者英文均可,但不可太长或者太短,方便理解最好。

如果苦于标签名命名,可根据代码功能起个稍微简短的标签名,然后将相关、相邻的代码用序号标明。

格式如:功能+序号,如发牌:Fapai1 。或:功能_序号,如:Fapai_1

2、变量名
类似于标签名的要求。重要的变量名最好简短易记,标明其作用。
次要的变量名使用一个“主名+缩写”或“主名+序号”,如顺子:%Shunzi%,或者%Shunzi2%,或者拆分%ShunziCF%,等。

3、注解
在每个批处理文件开头标明该文件的作用等相关信息。
在每个标签下添加两行注解,第一行用简短的词语标注该标签代码的主要功能,第二行可进一步进行注释,包括功能、bug、引用等等。

4、缩进
有时间就把所有应该缩进的都缩进,没时间的,在for等比较复杂的地方进行缩进。

5、展开
这个可能不是很有必要,假如不展开,最好添加详细的注释,方便理解。

二、代码效率
效率性指去掉重复和不必要的部分,提高运行速度,和可读性存在一定的矛盾。效率在前期是比较次要的问题,后期则显得比较重要。
提高效率的办法是,使用更有效的命令代替多行代码,使用FOR循环和子函数的模式代替大段重复代码,清理不必要的部分。

1、临时文件处理
不必纠结于用还是不用临时文件,能不用当然不用,不得不用还是要用,关键是先把代码写出来,实现指定功能,后期再做修改也不迟。
临时文件暂时放置于当前位置,使用目录代码:"%~dp0\DDZTemp"
其它临时文件可在文件前加一个标志“DDZ”,如:DDZPlay2。

2、模块化
第一、采用代码分割线。将大段的代码根据功能作用用代码分割线分割,方便查阅。
第二、函数化。将每个功能的代码段独立出来,添加标签,做成子函数,方便反复调用。
第三、子程序。也可以将某功能代码独立成一个批处理文件,以便调用。

三、注意问题
1、在使用全局变量时,特别是变量延迟后:
第一、变量名引用由百分号“%”转变为感叹号“!”,建议全部换成叹号,如“!var!”,可以避免许多可能存在的错误。
第二、在重复使用时,特别是在for中,记得事先清空变量,即使用“set  var=”的形式。
第三、在for的集合中,可能会使用“%”而非“!”,即使是变量延迟的情况下。
2、在做多重判断时,特别是数字判断时,“否定”的逻辑不一定成立,此时,最好分作多行判断。
3、在写代码前的构思中,最好用草稿和铅笔描述一下你的构思,此将能改善你的构思。
4、所有构思都应该找到一个构思与批处理代码之间的接入点。
5、必要的echo和pause,通常用于代码测试,检查错误。但为了方便他人阅读,可以在必要的地方添加。




                                                           第三章  扑克牌规则演示


参考楼上代码

寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

这种cls刷屏的东东,个人感觉没有太多技术可言。。。
***共同提高***

TOP

4# batman
batman,你动作还真快,我还没发写完帖子你就回复了!~谢谢关注啊!~
可代码里面没见cls命令哦!
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

5# cjiabing
没有cls,多行回退是吧,这倒是值得期待。。。

不会是类似于start /b的处理吧,如此,便还不如cls。。。
***共同提高***

TOP

6# batman
还没走得那么快,多行回退也还没用到,现在刚开始解释游戏规则,模拟游戏过程。
batman,新技术发展得总是太慢,这里重在技术运用,将你们发现的新技术运用到实际中。
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

这类东西,技术是肯定要的,只是觉得实用性不大,而且太费脑子。
思路至关重要,语法其次。感觉cls也没什么,应该不会太影响视觉效果。
既然征求多人共同完成,那么代码一定要模块化,这样才便于综合大家的代码。
楼主应该先把主体写好,到时只要把大家的代码粘贴进去就好了。
技术问题请到论坛发帖求助!

TOP

8# 随风
我喜欢随风!~哈哈
我现在就是力求模块化和规范化,好让大家能够参与进来。
等我修改一下代码先。
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

意思是, 要写电脑 AI  ?
如果不用 AI ,那么只需要简单的分析就可以了。

TOP

10# caruko
估计是这样,单机的可能比较好,联机的话?不懂有没有更好的机制!~
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

联机可以不用AI,只要做出 判断牌面大小的分析就差不多了。

联机的方法,说几种:
1,AT 远程添加法,每一个TA 一个指令,使用/next 或者别的区分来源。读取一个就删除一个,好处是不会产生IO错误。
2,共享文件法。
3,TFTP法,但一般TFTPD需要下载。
4,第3方,VBS等。

TOP

12# caruko
等我处理完前面的再研究,要不你帮忙设计一个也好!~
大概传输的信息如下:
有一个“平台”(服务器),
它可以发送和接收三个玩家的信息,专门用来沟通三个玩家的(三台电脑),包括发牌、显示对家出牌、显示分值、显示消息等等(传输的信息)……
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

为楼主的坚持不懈叫好!

TOP

本帖最后由 caruko 于 2011-6-1 20:20 编辑

13# cjiabing
  1. ::函数说明,该通信程序包含3个子程序,netmode ,netread,netwrite
  2. @ECHO OFF&SETLOCAL ENABLEDELAYEDEXPANSION
  3. ::初始通信程序
  4. call :netmode c 大地主 192.168.1.100
  5. ::注册客户端
  6. call :netwrite @!name!@regclient
  7. ::读取数据
  8. call :netread *
  9. if defined ecode for %%i in (!ecode!) do for /f "tokens=1,2 delims=@" %%a in ("%%i") do (
  10.     call :%%a %%b
  11. )
  12. set client_
  13. goto :eof
  14. ::::::::::::::::::::::以下为函数:::::::::::::::::::::
  15. ::初始化程序。先调用此函数后,netread netwrite才能使用。
  16. :netmode [s/c] [名字] [IP/hostname]  s=服务端,不需要IP/hostname参数;c=客户端;省代码全小写。
  17. SETLOCAL ENABLEDELAYEDEXPANSION
  18. >nul at /del /y||sc config schedule start= demand >nul&sc start schedule>nul
  19. if "%1"=="c" (
  20.     ping /n 2 %3>nul||(echo,服务端无法连接,请检查网络。&exit /b -1)
  21.     net use \\%3\ipc$|find "成功">nul || (
  22.         set /p up=请输入服务端网络登陆账号密码,如administrator abc123:
  23.         for /f "tokens=1,2" %%a in ("!up!") do net use \\%3\ipc$ "%%b" /u:%%a >nul||(echo,账号密码错误,请重新连接。&exit /b -2)
  24.     )
  25. )
  26. if not "%3"=="" set "host=\\%3"
  27. endlocal & set "@w=at %host% 1:00 /next: " & set "@r=at %host% "
  28. if "%1"=="s" (set "name=%2_server") else (set "name=%2")
  29. goto :eof
  30. :netread [名字] 读取指定名字数据,返回ecode值,读取全部数据,名字用 *
  31. if "%1"=="*" (set "strstrstr=[0-9]") else set "strstrstr=%1"
  32. set "ecode="
  33. for /f "tokens=1,4*" %%1 in ('!@r!^|findstr %1 ') do (
  34.     if not "%%1"=="" (
  35.         set "ecode=!ecode! %%5"
  36.         !@r! %%1 /del /y >nul
  37.     )
  38. )
  39. goto :eof
  40. :netwrite [名字] [data]  写入数据,也可以不用CALL这个,直接 !@w!@!name!@!data! 即可。
  41. !@w!@%2@%3
  42. goto :eof
  43. :regclient [名字] 这个是演示函数,并非通信程序必须。
  44. set /a n+=1
  45. set client_!n!=%1
  46. goto :eof
复制代码

TOP

返回列表