本文作者:kaifamei

黑白棋代码

更新时间:2024-06-18 02:19:07 人在看 0条评论

黑白棋代码


2024年6月18日发(作者:温州女公务员日记)

AI = {};

function(){

n= pattern;

04.// 定义了 8 个偏移量

05.// 可以简单通过加法得到任一点周围 8 个点的坐标

06.// -11 -10 -9

07.// -1 x 1

08.// 9 10 11

09.// 如左上角的坐标为 x + (-11)

directions=[-11,-10,-9,-1,1,9,10,11];

on pattern()

12.{

13. // 把整个棋盘填满 0

14. for(var i=0;i<100;i++)this[i]=0;

15. // 中间的 4 个格子,先放上两黑两白的棋子

16. this[54]=this[45]=1;this[55]=this[44]=2;

17. // 黑净胜外围子数目(黑减去白),估值时用。

18. ence=0;

19. // 当前可走棋方为黑棋

20. =1;

21. // 已经走了几步棋

22. =0;

23. // 稳定原型

24. // 0 是空白,1 是黑棋,2 是白棋,3 是边界

25. // 把 8 * 8 的棋盘扩展成 10 * 10,是一种技巧

26. // 可以简化坐标有效性的判断

27. var stableProto = [

28. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

29. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

30. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

31. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

32. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

33. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

34. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

35. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

36. 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,

37. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3

38. ]

39. // 从一个 8 * 8 的棋盘载入状态

40. =function(arr)

41. {

42. for(var y=1;y<=8;y++)

43. {

44. for(var x=1;x<=8;x++)

45. {

46. this[y*10+x]=arr[y-1][x-1];

47. }

48. }

49. }

50. // 判断能不能 pass

51. // 如果能,则当前可走棋方变更

52. =function()

53. {

54. for(var y=1;y<=8;y++)

55. {

56. for(var x=1;x<=8;x++)

57. {

58. if(this[y*10+x]==0)

59. {

60. // 有任何一步棋可走,都不可以 Pass

61. if((x,y,))

62. {

63. return false;

64. }

65. }

66. }

67. }

68. //alert("pass");

69. // 这是一个技巧,因为 的值域是 {1, 2}

70. // 所以当 color 是 1 时,执行完下一语句后就是 2

71. // 当 color 是 2 时,执行完下一语句后就是 1

72. = 3 - ;

73. return true;

74. }

75. =function()

76. {

77. function pattern(){}

78. ype=this;

79. return new pattern();

80. }

81. ng=function()

82. {

83. var icon=[" ","*","o"]

84. var r="";

85. for(var y=1;y<=8;y++)

86. {

87. for(var x=1;x<=8;x++)

88. {

89. r+=icon[this[y*10+x]]+" ";

90. //r+=stableDiscs[y*10+x]+" ";

91. }

92. r+="n";

93. }

94. return r+();

95. }

96.

97. // 净胜子数

98. =function()

99. {

100. // 这里是一个技巧, r[0] 是不使用的,r[1] r[2] 对应黑白棋子的个数

101. var r=[0,0,0];

102. for(var y=1;y<=8;y++)

103. {

104. for(var x=1;x<=8;x++)

105. {

106. r[this[y*10+x]]++; // 数目加一

107. }

108. }

109. // 当前颜的数量为 0,输了,返回负极值

110. if(r[]==0) return -64;

111. // 敌对颜的数量为 0,赢了,返回极值

112. if(r[]==0) return 64;

113. // 返回当前走棋方比对方多的数量

114. return r[]-r[];

115. }

116. // 对棋盘的估值

117. ate=function()

118. {

119. // 基本估值方法:

120. // 1、能占棋盘四角是很有价值的

121. // 2、邻近棋盘四角的位子是很差的

122. // 3、稳定子

123. // 4、外围子净胜数

124. var r=[0,0,0];

125. var r=ence;

126. // 如果左上角有棋子,自己的,就+30分,敌方的,-30 分

127. if(this[11]) r+=((this[11]==)?1:-1)*30;

128. // 次左上角,分值是 -15

129. else if(this[22]==)r-=15;

130. // 右上角,分值 30

131. if(this[18])r+=((this[18]==)?1:-1)*30;

132. // 次右上角,分值 -15

133. else if(this[27]==)r-=15;

134. // 左下角,分值 30

135. if(this[81])r+=((this[81]==)?1:-1)*30;

136. // 次左下角,分值 -15

137. else if(this[72]==)r-=15;

138. // 右下角,分值 30

139. if(this[88]){r+=((this[88]==)?1:-1)*30;}

140. // 次右下角,分值 -15

141. else if(this[77]==)r-=15;

142. // 查稳定子,

143. // 稳定子就是挨着 4 个角点并且周边的棋子要么是同,要么是边界

144. //var color = ;

145. var stableDiscs=();

146.

147. var queue = [];

148. if(this[11]!=0) ([11,this[11]]);

149. if(this[18]!=0) ([18,this[18]]);

150. if(this[81]!=0) ([81,this[81]]);

151. if(this[88]!=0) ([88,this[88]]);

152. while()

153. {

154. var position = queue[0][0];

155. var c = queue[0][1];

156. // 不懂 JS 的数组的内存管理算法,不过感觉从头上删除肯定是比较慢

的,

157. // 我感觉从后面删除会更好,或者使用标记不删除的方法性能会更好

158. ();

159. //if(stableDiscs[position]==0 || stableDiscs[position]==3)

continue;

160. stableDiscs[position] = c;

161. if( (stableDiscs[position-10]==3 || stableDiscs[position+10]==3

|| stableDiscs[position-10] == c || stableDiscs[position+10] == c) &&

162. (stableDiscs[position-1]==3 || stableDiscs[position+1]==3 ||

stableDiscs[position-1] == c || stableDiscs[position+1] == c) &&

163. (stableDiscs[position-11]==3 || stableDiscs[position+11]==3

|| stableDiscs[position-11] == c || stableDiscs[position+11] == c) &&

164. (stableDiscs[position-9]==3 || stableDiscs[position+9]==3 ||

stableDiscs[position-9] == c || stableDiscs[position+9] == c) )

165. {

166. stableDiscs[position]=c;

167. // 稳定子的分值为 7

168. r += ((c==)?1:-1)*7;

169. // 进一步扩展,查稳定子

170. for(var i = 0;i < ; i++)

171. if(stableDiscs[directions[i]+position]==0 &&

this[directions[i]+position]==c)

172. ([directions[i]+position,c]);

173. }

174. }

175.

176. // 返回估值

177. return r;

178. }

179. lString=function(depth)

180. {

181. var r="";

182. if(!depth)depth=0;

183.

184. for(var y=1;y<=8;y++)

185. {

186. for(var x=1;x<=8;x++)

187. {

188. if(this[y*10+x]!=0)r+=(this[y*10+x]==1?"*":"o")+" ";

189. else

190. {

191. var tmp=(x,y,);

192. if(tmp)

193. {

194. var tmp2=-(-Infinity,Infinity,depth);

195. if(tmp2<0||tmp2>9)r+=tmp2;

196. else r+=" "+tmp2;

197. }

198. else r+="X ";

199. }

200. }

201. r+="n";

202. }

203. return r+();

204. }

205. // 计算机去一步可走的棋步

206. // 这里 AI 部分的入口

207. er=function(depth,exactDepth){

208. if(!depth)depth=0;

209. if(!exactDepth)exactDepth=depth;

210. var r=[];

211. var max=-Infinity;

212. for(var y=1;y<=8;y++)

213. {

214. for(var x=1;x<=8;x++)

215. {

216. if(this[y*10+x])continue;

217. // 到一个空白格子

218. else

219. {

220. // 尝试走这个格子

221. var tmp=(x,y,);

222. // 不成功,非法

223. if(!tmp)continue;

224. // 已走步数+已搜索深度 >= 有 60 步

225. // 这时使用精确搜索得到更精确的结果

226. if(+exactDepth>=60)

227. {

228. var v=-earch(-Infinity,Infinity);

229. //alert([x,y]+":"+v);

230. }

231. // 离四个角最近的那 3 * 4 个格子,则多搜索一层

232. // 因为对手可能在下一手下在角上,会出现大翻盘。

233. else if( (x==2||x==7) && (y==2||y==7) )

234. var v=-(-Infinity,Infinity,depth+1);

235. else

236. var v=-(-Infinity,Infinity,depth);

237. // 还不如之前的棋步

238. if(v

239. // 比之前的棋步好

240. if(v>max){

241. // 保存起来

242. r=[[x,y]];max=v;

243. }

244. // 另一个可选的棋步

245. else ([x,y]);

246. }

247. }

248. }

249. // 在所有可选的棋步中,随机选择一个,让玩家觉得比较多变化,不那么单调。

250. var tmp=(()*);

251. return r[tmp];

252. }

253. // 搜索算法

254. // 使用负极大值形式的 Alpha-Beta 剪枝搜索算法

255. =function(alpha,beta,depth,pass){

256. // 叶子节点,返回估值

257. if(depth==0)return ate();

258. var canmove=false;

259. for(var y=1;y<=8;y++)

260. {

261. for(var x=1;x<=8;x++)

262. {

263. if(this[y*10+x]!=0)r+=(this[y*10+x]==1?"*":"o")+" ";

264. else

265. {

266. var tmp=(x,y,);

267. if(!tmp)continue;

268. canmove=true;

269. // 往更深搜索

270. var r=-(-beta,-alpha,depth-1);

271. //if(depth==4)(r);

272. // 收窗窗口

273. if(r>=alpha)alpha=r;

274. // 胜着

275. if(alpha>beta)return Infinity;

276. }

277. }

278. }

279. // 返回当前局面的最佳着法估值

280. if(canmove)return alpha;

281. // 双方都没有可下子之处,返回净胜子数

282. if(pass) return ();

283. // pass 一次,往深搜索

284. =;

285. return -(-beta,-alpha,depth-1,true);

286. }

287. // 精确搜索,这段的算法原理跟 search 是一样的

288. earch=function(alpha,beta,pass){

289. // 已经走了 60 步了,返回净胜子数

290. if(==60)return ();

291. var canmove=false;

292. for(var y=1;y<=8;y++)

293. {

294. for(var x=1;x<=8;x++)

295. {

296. if(this[y*10+x]!=0);//r+=(this[y*10+x]==1?"*":"o")+" ";

297. else

298. {

299. var tmp=(x,y,);

300. if(!tmp)continue;

301. canmove=true;

302. var r=-earch(-beta,-alpha);

303. if(r>=alpha)alpha=r;

304. if(alpha>beta)return Infinity;

305. }

306. }

307. }

308. if(canmove)return alpha;

309. if(pass)return ();

310. =;

311. return -earch(-beta,-alpha,true);

312. }

313. // 尝试在 x, y 放下 颜的棋子,成功返回下一棋盘状态,否则返回

null

314. =function(x,y)

315. {

316. // 复制当前状态

317. var pattern=();

318. =;

319. // 注意这个负号

320. ence=-ence;

321. // move 数++

322. ++;

323. var canmove;

324. canmove=false;

325. // 放在函数入口处,可以优化性能

326. // 把 10*y+x 放入临时变量可优化性能

327. if(pattern[10*y+x]!=0)return null;

328. // 8 方向判断

329. for(var i=0;i<8;i++)

330. {

331. // 转换为一维索引

332. var p=10*y+x+directions[i];

333. // 邻近的格子上棋子不同

334. if(pattern[p]==)

335. while(pattern[p]!=0)

336. {

337. // 往同方向搜索

338. p+=directions[i];

339. // 另一端还有一个自己的棋子,则是一个可走的点。

340. if(pattern[p]==)

341. {

342. canmove=true;

343. // 把中间的棋子翻过来

344. while((p+=-directions[i])!=10*y+x)

345. {

346. pattern[p]=;

347. //alert(p);

348. for(var d=0;d<8;d++)

349. {

350. // 非空

351. if(!pattern[p+directions[d]]

352. // 非边界

353.

&&p+directions[d]>10

354.

&&p+directions[d]<89

355.

&&(p+directions[d])%10!=0

356.

&&(p+directions[d])!=9)

357. // 外围净胜子数增加

358. ence++;

359. }

360. }

361. break;

362. }

363. }

364. }

365. // 返回新的棋盘状态

366. if(canmove){pattern[10*y+x]=;return pattern;}

367. else return null;

368. }

369.}

370.//ype = emptyboard;

371.//(new

pattern().move(5,6).move(6,4).move(4,3).move(3,4).toLocalString(3));

372.//(new pattern().move(5,6).search(-Infinity,Infinity,2));

373.}()

本文来自CSDN博客,转载请标明出处

/lanphaday/archive/2010/11/22/



文章投稿或转载声明

本文链接:https://www.en369.cn/fanwen/xinxi-1-1421420-0.html

来源:范文频道-369作文网版权所有,转载请保留出处。本站文章发布于 2024-06-18 02:19:07

发表评论

验证码:
用户名: 密码: 匿名发表
评论列表 (有 条评论
2人围观
参与讨论