XMOVE3.0手持终端——软件介绍(四):在2KB内存的单片机上实现的超精简五子棋对战算法(原创)
2012-06-20 19:53
561 查看
一. 综述
这是我两年前完成的一个小项目,它基于我开发的XMOVE动作感应系统平台。五子棋算法网上随便一搜到处都是,不过值得自豪的是,我在2KB内存的单片机上不仅跑上了我自制的嵌入式OS,还能同时跑五子棋。这是界面截图:其他模块的实现(仅供参考)
void DrawDesk() { u8 m; Clear_Screen(); SetPaintMode(0,COLOR_Black); Rectangle(23,28,205,210,1); SetPaintMode(0,COLOR_Yellow); Rectangle(20,25,202,207,1); SetPaintMode(0,COLOR_Black); for(m=0;m<15;m++) Line(20,25+13*m,200,25+13*m); for(m=0;m<15;m++) Line(20+13*m,25,20+13*m,207); //Lcd_disp(240,12,"五子棋"); //Lcd_disp(65,36,"赵一鸣之作"); } void Drawchess(u8 x,u8 y, u8 mood) { if(mood==2)//黑方 { SetPaintMode(0,COLOR_Black); Circle(20+13*x,25+y*13,5,1); } //Rectangle(2+x*4,1+y*4,4+x*4,3+y*4,1); else if(mood==1) { SetPaintMode(0,COLOR_White); Circle(20+13*x,25+y*13,5,1); SetPaintMode(0,COLOR_Black); Circle(20+13*x,25+y*13,5,0); } } void PushChess(u8 x,u8 y,u16 Data[29],u8 mood) { Drawchess(x,y,mood); WriteData(x,y,Data,mood); } u8 DrawKuang(u8 *x,u8 *y,u16 Data[29]) { u8 func_state=0; u8 GyroKey,myKey; while(func_state==0) { SetPaintMode(0,COLOR_Black); Rectangle(14+*x*13,19+*y*13,26+*x*13,31+*y*13,0); if(GyroControlEN==1&&back_light>1&&GyroMenuEN) { delay_ms(200); L3G4200DReadData(); L3G4200DShowData(); delay_ms(200); } else InputControl(); GyroKey=GyroKeyBoardInputMethod(0,0,300,300); if(GyroKey!=KEYNULL) myKey=GyroKey; else myKey=key_data; GyroKey=KEYNULL; SetPaintMode(0,COLOR_Yellow); Rectangle(14+*x*13,19+*y*13,26+*x*13,31+*y*13,0); SetPaintMode(0,COLOR_Black); PutPixel(20+(*x)*13,19+(*y)*13); PutPixel(20+(*x)*13,(*y)*13+31); PutPixel(14+(*x)*13,(*y)*13+25); PutPixel(26+(*x)*13,(*y)*13+25); switch(myKey) { case KEYENTER_UP : if(ReadData(*x,*y,Data)==0) func_state=1; break; case KEYCANCEL_UP : return 0; default: FourDirectionInputMethod(myKey,1,1,1,1,0,14,0,14,0,0, x,y); } myKey=KEYNULL; } return 1; }
四. 算法主流程(简化版)
流程因为很简单,所以就不画了。while(OS_func_state==0) //OS_func_state==0是正常的下棋状态 { if(func_state==0) //我方下棋 { if(DrawKuang(&XAxi,&YAxi,TotalCheseData)) PushChess(XAxi,YAxi,TotalCheseData,2); else { OS_func_state=10; //跳出态 } if(ResultCheck(TotalCheseData,2)==2) //胜利,跳出到成功界面 { OS_func_state=5; } else func_state=1; //让给对方下棋 } else //对方下棋 { GameSatusInit(myGameSatus); GameSatusInit(itGameSatus); CalPushPosition(&XAxi,&YAxi,myGameSatus,itGameSatus,TotalCheseData); PushChess(XAxi,YAxi,TotalCheseData,1); if(ResultCheck(TotalCheseData,1)==1) { OS_func_state=5; } else func_state=0; } }
五. 总结和改进
实现五子棋的算法有很多选项,比如基于博弈树的剪枝算法,和我这种比较简化的靠遍历评分的算法。这个算法来自于网上,水平仅仅算是初级,缺点也很明显,只顾眼前利益,不能顾全大局,这就和许多五子棋初学者一样犯了“目光短浅”的毛病。要解决这个问题,我们引入‘今后几步预测法’,具体方法是这样的: 首先, 让电脑分析一个可能的点,
如果在这儿下子将会形成对手不得不防守的棋型(例如:‘冲四’、‘活三’);那么下一步对手就会照您的思路下子来防守您,如此一来便完成了第一步的预测。这时再调用模块4对预测后的棋进行盘面分析,如果出现了‘四三’、‘双三’或‘双四’等制胜点,那么己方就可以获胜了(当然对黑棋而言‘双三’、‘双四’是禁手,另当别论);否则照同样的方法向下分析,就可预测出第二步、第三步……
不过,我做过实际的测试,加上两步迭代以后,计算时间变为原来的10倍左右(确实是指数级的),但此时内存是不够用的。考虑到是2KB内存的超低功耗单片机,实现更复杂的算法勉为其难,我也就没有在上面实现迭代,有兴趣的同学们可以尝试实现之,其实不难,用个好点的CPU,比如STM32,(用电脑就别用我这个算法了),稍微改改代码就可以。这种情况,电脑的水平在中级左右。
系统没有随机性,换句话说,如果你每次下子的方式是一样的,那么系统演化的形式完全一致。
顺便提一下,自从学习了C#编程以后,看了两年前写的C代码,真是不堪入目。不过,在单片机上实现的东西,效率比可读性和结构性更重要吧。
有任何问题,欢迎随时交流。
相关文章推荐
- XMOVE3.0手持终端——软件介绍(三):在2KB内存的单片机上实现的的俄罗斯方块 (原创)
- XMOVE3.0手持终端——软件介绍(二):在2KB内存的单片机上实现的彩屏GUI控件库
- XMOVE3.0手持终端——软件介绍(二):在2KB内存的单片机上实现的彩屏GUI控件库
- XMOVE3.0手持终端——软件介绍(五):在2KB内存的单片机上实现的T9中文输入法
- XMOVE3.0手持终端——软件介绍(一):精简型嵌入式管理系统的菜单实现和任务切换
- 介绍开发Android手持终端PDA盘点APP软件
- 2KB内存单片机上实现彩屏GUI控件库
- 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍
- 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍
- 2KB内存单片机上实现彩屏GUI控件库
- 2KB内存单片机上实现彩屏GUI控件库
- 小王的尴尬日常(二)---Openssl 实现国密算法(基础介绍和产生秘钥对)
- 进程同步与异步-软件实现(算法)
- [原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,
- MD5的介绍,算法以及实现
- Ehome:智能家居之手持终端计步器功能实现
- 五子棋算法实现
- Java虚拟机垃圾回收(一) 基础:回收哪些内存/对象 引用计数算法 可达性分析算法 finalize()方法 HotSpot实现分析
- h.264并行解码算法2D-Wave实现(基于多核非共享内存系统)
- 基于C++实现五子棋AI算法思想