小游戏的算法就是就是对游戏规则的抽象。一切事物皆可以成抽象成数学语言,程序语言。对游戏而言首先要明确定义游戏规则,一般我们在向他人讲述一个游戏规则时都很随意。比如五子棋我们就会说一句“连成五个子就行了”。其他的就靠人们通常的理解,和我们之间基本的默契了,但是当我写游戏就要把游戏规则高度精确的定义出来。
首先要能够用比较严谨的语言将规则表述清楚这个很重要。
下面我就有相对精确的语言把五子棋的规则给定义出,来并且说出每句的必要性;
1.棋盘:五子棋的棋盘是15*15的方格组成。棋子必须落在格点上
注释:15*15这个的必要性就是让五子棋有个适当的终结以免五子棋无穷的下下去,他对我们的影响就是:
即使你有4个子了但是到达了边界你还是没赢;由于这个规则就影响了你的落子,和你的策略;
对于程序:来说就是如果你鼠标点击了棋盘之外的点视为无效操作可以继续走。
如你点击的不是刚好在格点上就视为你点了离你鼠标位置最近的格点
2.棋子:就是黑子和白子棋子到时要求不大如果非要说一个的话就是棋子的直径要<=格子的边长
在程序中的体现就是注意下素材和算法关系不大
3.落子:一局棋中一个玩家只能使用一种颜色的棋子,双方交替落子一次只能落一子,两个棋子不能落在同一位置
对于程序:点击棋盘,如果你点击的那个部位超出界限,或对应的格点上已有棋子,或者对方尚未落子,则视为无效点击,可继续落子
3.赢:就是如果有经过玩家最后一次落子位置水平,竖直,与水平线成45度角,与水平线成135度角,这四条直线上又连续5个同色的棋子连续就是之中间没有中间没有空格点也没有异色的子
如果你能对一个游戏描述的像上面的那样那你基本上就可以根据游戏规则自己设计算法了而不是贴别人现成的
首先我解释下下面这个方法的参数:
int[,]winarr:就是记录棋盘上所有格点上落子情况的数组无子为0,黑子为1,白子为2
Pointluozi:这个只得是棋盘上最后落下的那个子的坐标。intx:代表的是棋盘上最后落地是黑子1,还是白子2
对于人人对战的来说核心的算法就是
inta,intb,intA,intB:代表目前棋盘的有效范围分别就是最左最上最右最下
有效范围:就是包含所有已经落子区域的最小矩形因为我这个五子棋做的是有AI的为了减小在棋盘上检索的范围就只检索这个有效范围
如果你不想考虑这些就a=0,b=0,a=14,b=14;
boolwin(int[,]winarr,Pointluozi,inta,intb,intA,intB,intx){
//这两个for指的就是所有的行和列for(introw=a;row<=A;row++){for(intcolum=b;colum<=B;colum++){
//4个if指的就是经过最后落子位置的4条线为什么要弄最后落子经过的4条线呢因为这样大大缩小了检索的范围
//我是怎吗让这4个if里面的直线经过最后的落子呢这个其实就是一个简单高中学的数学的一次函数的知识
//row==luozi.X就保障了该直线上所有的点都和最后落子在同一行4个if()中写包含luozi的都是为了保障该线经过落子
if(row==luozi.X&&colum+4<=B&&winarr[row,colum]==x&&winarr[row,colum+4]==x&&winarr[row,colum+1]==x&&winarr[row,colum+2]==x&&winarr[row,colum+3]==x)returntrue;if(colum==luozi.Y&&row+4<=A&&winarr[row,colum]==x&&winarr[row+4,colum]==x&&winarr[row+1,colum]==x&&winarr[row+2,colum]==x&&winarr[row+3,colum]==x)returntrue;if(colum+row==luozi.X+luozi.Y&&row-4>=a&&colum+4<=B&&winarr[row,colum]==x&&winarr[row-4,colum+4]==x&&winarr[row-1,colum+1]==x&&winarr[row-2,colum+2]==x&&winarr[row-3,colum+3]==x)returntrue;if(row-colum==luozi.X-luozi.Y&&row+4<=A&&colum+4<=B&&winarr[row,colum]==x&&winarr[row+4,colum+4]==x&&winarr[row+1,colum+1]==x&&winarr[row+2,colum+2]==x&&winarr[row+3,colum+3]==x)returntrue;}
}returnfalse;}
或许有人认为这个方法有些麻烦因为为了缩小检索的范围我多弄了好多参数。如果不考虑这些的话仅用一个数组参数就OK了
这些代码核心就是4个if只要你认真弄懂1一个if的含义其他的都差不多我个人认为此方法的代码已经够短了对于5子棋判断输赢而且方法也比较好减少了至少一半的运算量如果你有其他好的方法可以贴出来交流下
对于人人对战的五子棋来说核心的算法就是我上面贴出来的判断输赢关于联机下五子棋如果你学了协议方面的东西就不用我多说了相信你会做的如果你对界面的绘制有问题请看我的上一篇如果你想了解五子棋的AI制作也就是做人机对战的五子棋我将在下一篇中讲解
上面的问题我讲的比较细致下面我就直接贴出几个其他游戏的核心算法来供大家参考
先来个简单的启发下新手的思维其实很多事物都是可以用程序表达的如果你经常能把自己周围的事物也程序的眼光去看待相信你的编程会有极大的提高下面我就有一个程序描述出石头剪刀布这个游戏
enumCaiQuan//这就是个枚举定义了石头,剪刀,布{ShiTou,//石头值为0枚举类型的值默认等于他出现的次序从0开始JianDao,//剪刀值为1Bu//布值为2}
intwin(CaiQuanA,CaiQuanB)//此方法就是石头剪刀布的规则参数为A的出招,和B的出招{if(A==B)//A,B出招相同返回0return0;elseif((int)A-(int)B==1||(int)A-(int)B==2)//A胜返回1这个规律是我总结的石头剪刀布就那么几种情况很好总结return1;elsereturn-1;//没胜没平自然就是输了输了返回-1}//这个算法游戏规则大家都很清楚根据游戏规则直接转化成代码的就需要列举所有的对阵情况而我写的代码是从所有对阵情况的总结
下面在贴练练看的算法好像没写注释等有空我把他们一个一个给大家细细讲解给对这方面有兴趣的朋友一个学习的帮助
练练看连连看中基本上就一个算法就是他的消除算法如下
//线面这个方法是练练看的消除需要用到的
///
}else{if(A1.X>B1.X){for(inti=B1.X;i<=A1.X;i++){if(map[i,A1.Y]!=-1&&newPoint(i,A1.Y)!=point1&&newPoint(i,A1.Y)!=point2){returnfalse;}}}else{for(inti=A1.X;i<=B1.X;i++){if(map[i,A1.Y]!=-1&&newPoint(i,A1.Y)!=point1&&newPoint(i,A1.Y)!=point2){returnfalse;}}}}returntrue;}
}
这个方法我写的比较长如果你见到更好的算法请发我研究下
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本来想多帖几个小游戏的算法呢可我的其他的小游戏的算法没整理好直接用的群居变量没用参数贴出来不好看