游戏开发中的经典算法.docx
- 文档编号:11814354
- 上传时间:2023-04-02
- 格式:DOCX
- 页数:18
- 大小:22.13KB
游戏开发中的经典算法.docx
《游戏开发中的经典算法.docx》由会员分享,可在线阅读,更多相关《游戏开发中的经典算法.docx(18页珍藏版)》请在冰豆网上搜索。
游戏开发中的经典算法
游戏开发中的经典算法
算法是程序设计的精髓,程序设计的实质就是构造解决问题的算法,将其解释为计算机语言。
算法是在有限步骤内求解某一问题所使用的一组定义明确的规则。
通俗点说,就是计算机解题的过程。
在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法。
前者是推理实现的算法,后者是操作实现的算法。
一个算法应该具有以下五个重要的特征:
有穷性:
一个算法必须保证执行有限步之后结束;
确切性:
算法的每一步骤必须有确切的定义;
输入:
一个算法有0个或多个输入,以刻画运算对象的初始情况;
输出:
一个算法有一个或多个输出,以反映对输入数据加工后的结果。
没有输出的算法是毫无意义的;
可行性:
算法原则上能够精确地运行,而且人们用笔和纸做有限次运算后即可完成。
动态规划-航线设置
问题描述:
美丽的莱茵河畔,每边都分布着N个城市,两边的城市都是唯一对应的友好城市,现需要在友好城市开通航线以加强往来.但因为莱茵河常年大雾,如果开设的航线发生交叉现象就有可能出现碰船的现象.现在要求近可能多地开通航线并且使航线不能相交!
假如你是一个才华横溢的设计师,该如何设置友好城市间的航线使的航线数又最大又不相交呢?
分析:
此问题可以演化成求最大不下降序列来完成.源程序如下:
programdongtai;{动态规划之友好城市航线设置问题}
var
d:
array[1..1000,1..4]ofinteger;
i,j,k,n,L,p:
integer;
procedureprint(L:
integer);{打印结果}
begin
writeLn('最多可设置的航线数是:
',k);
repeat
writeLn(d[L,1]:
4,d[L,2]:
4);{输出可以设置航线的友好城市代码}
L:
=d[L,4]
untiLL=0
end;
begin
writeLn('输入友好城市对数:
');
readLn(n);
writeLn('输入友好城市对(友好城市放在同一行:
');{输入}
fori:
=1tondo
readLn(d[i,1],d[i,2]);{D[I,1]表示起点,D[I,2]表示终点}
fori:
=1tondo
begin
d[i,3]:
=1;{D[I,3]表示可以设置的航线条数}
d[i,4]:
=0{D[I,4]表示后继,即下一条航线从哪里开始设置,为0表示不能设置下一条航线}
end;
fori:
=n-1downto1do{从倒数第二个城市开始规划}
begin
L:
=0;p:
=0;{L表示本城市后面可以设置的航线数,P表示下条航线从哪个城市开始}
forj:
=i+1tondo{找出本城市后面可以设置的最大航线数和小条航线到底从哪个城市开始设置}
if(d[i,2]L)then
{如果本城市I的终点小于后面城市的终点(即不相交)}{并且此城市后面可以设置的航线数大于L}
begin
L:
=d[j,3];{那么L等于城市J的可以设置航线数}
p:
=j{P等于可以设置下条航线的城市代码}
end;
ifL>0then{如果本城市后面总共可以设置的航线数>0则}
begin
d[i,3]:
=L+1;{本城市可以设置的航线数在下个城市可以设置航线数的基础上加1}
d[i,4]:
=p{D[I,4]等于本城市后续城市的代码}
end
end;
k:
=d[1,3];{K为可以设置最大航线数,假设初值为第一个城市可以设置的航线数}
L:
=1;{L为城市代码,初值为第一个城市}
fori:
=2tondo{找出可以设置航线的最大值,赋值给K,同时L记下哪个可以设置最大航线数的城市代码}
ifd[i,3]>kthen
begin
k:
=d[i,3];
L:
=i
end;
fori:
=1tondo{打印结果,因为有可能有多种方案,所以只要哪个城市可以设置的航线数等于最大值K就打印结果}
ifd[i,3]=kthenprint(i)
end.
归并排序算法
合并排序(MERGESORT)是又一类不同的排序方法,合并的含义就是将两个或两个以上的有序数据序列合并成一个新的有序数据序列,因此它又叫归并算法。
它的基本思想就是假设数组A有N个元素,那么可以看成数组A是又N个有序的子序列组成,每个子序列的长度为1,然后再两两合并,得到了一个N/2个长度为2或1的有序子序列,再两两合并,如此重复,值得得到一个长度为N的有序数据序列为止,这种排序方法称为2—路合并排序。
例如数组A有7个数据,分别是:
49386597761327,那么采用归并排序算法的操作过程如图7所示:
初始值[49][38][65][97][76][13][27]
看成由长度为1的7个子序列组成
第一次合并之后[3849][6597][1376][27]
看成由长度为1或2的4个子序列组成
第二次合并之后[38496597][132776]
看成由长度为4或3的2个子序列组成
第三次合并之后[13273849657697]
图6归并排序算法过程图
合并算法的核心操作就是将一维数组中前后相邻的两个两个有序序列合并成一个有序序列。
合并算法也可以采用递归算法来实现,形式上较为简单,但实用性很差。
合并算法的合并次数是一个非常重要的量,根据计算当数组中有3到4个元素时,合并次数
是2次,当有5到8个元素时,合并次数是3次,当有9到16个元素时,合并次数是4次,按照这一
X
规律,当有N个子序列时可以推断出合并的次数是X(2>=N,符合此条件的最小那个X)。
源程序:
programhebing;
const
n=10;
var
a:
array[1..n]ofinteger;
i:
integer;
procedureinit;
var
i:
integer;
begin
fori:
=1tondoread(a[i]);
readln;
end;
proceduremerge(low,mid,high:
integer);
var
h,i,j,k:
integer;
b:
array[1..n]ofinteger;
begin
h:
=low;i:
=low;j:
=mid+1;
while(h<=mid)and(j<=high)do
begin
if(a[h]<=a[j])then
begin
b[i]:
=a[h];h:
=h+1;
end
else
begin
b[i]:
=a[j];j:
=j+1;
end;
i:
=i+1;
end;
ifh>midthen
fork:
=jtohighdo
begin
b[i]:
=a[k];i:
=i+1;
end
else
fork:
=htomiddo
begin
b[i]:
=a[k];i:
=i+1;
end;
fork:
=lowtohighdo
a[k]:
=b[k];
end;
proceduremergesort(low,high:
integer);
var
mid:
integer;
begin
iflow<>
begin
mid:
=(low+high)div2;
mergesort(low,mid);
mergesort(mid+1,high);
merge(low,mid,high);
end;
end;
枚举法
有4个学生,上地理课时提出我国四大谈水湖的排列次序如下:
甲:
洞庭湖最大,洪泽湖最小,鄱阳湖第三;
乙:
洪泽湖最大,洞庭湖最小,鄱阳湖第二,太湖第三;
丙:
洪泽湖最小,洞庭湖第三;
丁:
鄱阳湖最大,太湖最小,洪泽湖第二,洞庭湖第三;
对于各湖泊应处的位置,每个人只说对了一个。
根据以上描述和条件,编写程序,让计算机判断一下各湖泊应该处于第几位。
解题思路:
设置洞庭湖、洪泽湖、鄱阳湖、太湖分别用字母A、B、C、D代表,最大到最小依次用数字4——1表示。
应用枚举法可以解决此问题,不过稍微复杂罗嗦点。
源程序如下:
programhupo;
var
a,b,c,d:
integer;
begin
forb:
=1to4do
fora:
=1to4do
if((b=1)and(a<>2))or((a=2)and(b<>1))then
ifa<>bthen
forc:
=1to4do
if(a<>c)and(b<>c)then
if(a+b+c<>7)and(a+b<>5)and(a+c<>6)and(b+c<>3)then
ford:
=1to4do
ifc<>dthen
if(b+a<>5)and(b+c<>7)and(b+d<>6)then
if(a+c<>4)and(a+d<>3)and(c+d<>5)then
if(c+d<>5)and(c+b<>7)and(c+a<>6)then
if(d+b<>4)and(d+a<>3)and(b+a<>5)then
writeln('a=',a,'b=',b,'c=',c,'d=',d)
end.
改进程序:
programygzj;
var
a,b,c,d:
integer;
begin
fora:
=1to4do
forb:
=1to4do
forc:
=1to4do
begin
d:
=10-a-b-c;
iford(a=1)+ord(b=4)+ord(c=3)=1then
iford(b=1)+ord(a=4)+ord(c=2)+ord(d=3)=1then
iford(b=4)+ord(a=3)=1then
iford(c=1)+ord(d=4)+ord(b=2)+ord(a=3)=1then
ifa*b*c*d=24then
writeln('洞庭湖第':
3,a:
3,'洪泽湖第':
3,b:
3,'波阳湖第':
3,c:
3,'太湖第':
3,d:
3);
end;
writeln
end.
数字全排列问题:
任意给出从1到N的N个连续的自然数,求出这N个自然数的各种全排列。
如N=3时,共有以下6种排列方式:
123,132,213,231,312,321。
注意:
数字不能重复,N由键盘输入(N<=9)。
解题思路:
应用回溯法,每个数的取法都有N个方向(1——N),当取够N个数时,输出一个排列,然后退后一步,取前一个数的下一个方向(即前一个数+1),并且要保证所有数字不能重复。
当前数字的所有方向都取完时,继续退一步,一直重复到第一个数为止。
程序代码:
programquanpailie;{数字全排列问题}
var
a:
array[1..9]ofinteger;
k,x,n:
integer;
functionpanduan(j,h:
integer):
boolean;{判断当前数字是否能赋值给当前数组元素}
var
m:
integer;
begin
panduan:
=true;
form:
=1toh-1do
ifa[m]=jthenpanduan:
=false{如果当前数字与前面的数组元素相同则不能赋值}
end;
proceduretry(h:
integer);
var
i,j,m:
integer;
begin
forj:
=1tondo
ifpanduan(j,h)then
begin
a[h]:
=j;{能够赋值,且长度k加一}
k:
=k+1;
ifk=nthen{如果长度达到N则表示一种组合已经完成,输出结果}
begin
form:
=1tondo
write(a[m]);
write('':
4);
x:
=x+1;{每输出一种排列方式加一}
ifxmod5=0thenwriteln;{每行输出5种排列方案}
end
else
try(h+1);{对下一个数组元素进行赋值}
k:
=k-1{回溯的时候一定要把长度减一}
end
end;
begin
writeln('输入N:
');
readln(n);
k:
=0;{k表示长度,长度初始值为0}
x:
=0;{x表示总的排列方式}
try
(1);{对第一个数组元素赋值}
writeln('共有',x,'种排列方案')
end.
Dijkstra最短路径(一点到各顶点最短路径)
{本程序解决6个顶点之间的最短路径问题,各顶点间关系的数据文件在sj.txt中}
{如果顶点I到顶点J不能直达就设置距离为30000}
programdijkstra;
type
jihe=setof0..5;
var
a:
array[0..5,0..5]ofinteger;
dist:
array[0..5]ofinteger;
i,j,k,m,n:
integer;
fv:
text;
s:
jihe;
begin
s:
=[0];
assign(fv,'sj.txt');
reset(fv);
fori:
=0to5do{从文件中读数据,其中a[i,j]代表从顶点i到顶点j的直达距离,如果不通用30000代替}
begin
forj:
=0to5doread(fv,a[i,j]);
readln(fv)
end;
fori:
=1to5do{设置DIST数组的初始值,即为顶点0到各顶点的直达距离(算法的第一步)}
dist[i]:
=a[0,i];
fori:
=1to5do
begin
m:
=0;
dist[m]:
=30000;{设置DIST[M]的目的是为下面的一步做准备,即在DIST数组中一个最小的值}
forj:
=1to5do{算法的第二步,找最小的DIST值}
if(not(jins))and(dist[m]>dist[j])
thenm:
=j;{用M来记录到底是哪个顶点}
s:
=s+[m];{把顶点加入S中}
fork:
=1to5do{算法的第三步,修改后面的DIST值}
if(not(kins))and(dist[k]>dist[m]+a[m,k])
then
dist[k]:
=dist[m]+a[m,k]
end;
writeln('原各顶点间的路径关系是:
(30000代表不通)');
fori:
=0to5do
begin
forj:
=0to5dowrite(a[i,j]:
6);
writeln
end;
writeln;writeln;
八皇后问题
{问题描述:
在国际象棋8X8的棋盘里摆放8个皇后,使每个皇后都能生存而不互相冲突,即同一行、同一列同对角线(包括主对角线和辅对角线)都只能有一个皇后}
programeightqueen;{本程序可以搜索出所有的解}
var
a,b:
array[1..8]ofinteger;
c:
array[-7..7]ofinteger;
d:
array[2..16]ofinteger;
i,k:
integer;{K变量用来存放答案的个数}
fv:
text;
procedureprint;
var
i:
integer;
begin
fori:
=1to8do
writeln(fv,'第',i:
2,'行放在第',a[i]:
2,'列');{结果输出到文件里}
k:
=k+1;{每输出一个答案计数加1}
writeln(fv)
end;
proceduretry(i:
integer);
var
j:
integer;
begin
forj:
=1to8do
if(b[j]=0)and(c[i-j]=0)and(d[i+j]=0)then
begin
a[i]:
=j;
b[j]:
=1;{宣布占领列、主副对角线}
c[i-j]:
=1;
d[i+j]:
=1;
ifi<8thentry(i+1)elseprint;
b[j]:
=0;{释放占领列、主副对角线}
c[i-j]:
=0;
d[i+j]:
=0
end
end;
begin
fori:
=1to8doa[i]:
=0;
fori:
=-7to7doc[i]:
=0;
fori:
=2to16dod[i]:
=0;
k:
=0;
assign(fv,'jieguo.txt');{指定文件与文件变量相联系}
rewrite(fv);{以写的方式打开文件}
try
(1);
close(fv);{一定要记得关闭文件,不然数据有可能丢失}
writeln('共有',k:
3,'种摆法')
end.
快速排序算法
programkuaisu(input,output);
constn=10;
var
s:
array[1..10]ofinteger;
k,l,m:
integer;
procedureqsort(lx,rx:
integer);
var
I,j,t:
integer;
Begin
I:
lx;j:
rx;t:
s[I];
Repeat
While(s[j]>t)and(j>I)do
Begin
k:
=k+1;
j:
=j-1
end;
ifI<>
begin
s[I]:
=s[j];I:
=I+1;l:
=l+1;
while(s[I]<(i
begin
k:
=k+1;
I:
=I+1
End;
IfI<>
begin
S[j]:
=s[I];j:
=j-1;l:
=l+1;
End;
End;
UntilI=j;
S[I]:
=t;I:
=I+1;j:
=j-1;l:
=l+1;
Iflx
IfI<>
End;{过程qsort结束}
Begin
Writeln('input10integernum:
');
Form:
=1tondoread(s[m]);
K:
=0;l:
=0;
Qsort(l,n);
Writeln('排序后结果是:
');
Form:
=1tondowrite(s[m]:
4)
End.
地图四色问题
{问题描述:
任何一X地图只要用四种颜色进行填涂,就可以保证相邻省份不同色}
programtt;
constnum=20;
vara:
array[1..num,1..num]of0..1;
s:
array[1..num]of0..4;{用1-4分别代表RBWY四种颜色;0代表末填进任何颜色}
k1,k2,n:
integer;
functionpd(i,j:
integer):
boolean;{判断可行性:
第I个省填上第J种颜色}
vark:
integer;
begin
fork:
=1toi-1do{一直从第一个省开始进行比较一直到I省减一的那个省,目的是对已经着色的省份来进行比较,因为>I的省还没有着色,比较没有意义,着色的顺序是先第一、二、三……I个省}
if(a[i,k]=1)and(j=s[k])then{省I和省J相邻且将填进的颜色和已有的颜色相同}
begin
pd:
=false;{即不能进行着色}
exit;{退出当前函数}
end;
pd:
=true;{可以进行着色}
end;
procedureprint;{打印结果}
vark:
integer;
begin
fork:
=1tondo{将数字转为RBWY串}
cases[k]of
1:
write('R':
4);
2:
write('B':
4);
3:
write('W':
4);
4:
write('Y':
4);
end;
writeln;
end;
proceduretry(i:
integer);
varj:
integer;
begin
forj:
=1to4do
ifpd(i,j)thenbegin
s[i]:
=j;
ifi=nthenprint
elsetry(i+1);{对下一个省进行着色}
s[i]:
=0;{不能进行着色,将当前状态设置0,即不进行着色}
end;
end;
BEGIN
write('pleaseinputcitynumber:
');readln(n);
writeln('pleaseinputtherelationofthecities:
');
fork1:
=1tondo
begin
fork2:
=1tondoread(a[k1,k2]);{A[K1,K2]=1表示省K1、K2相邻,为0就不相邻}
readln;
end;
fork1:
=1tondos[k1]:
=0;{把所有的颜色设置为0,即还没有进行着色}
try
(1);
END.
穿越迷宫
{本程序假设迷宫是一个4X4的矩阵,入口在A[1,1],出口在A[4,4]}
{矩阵数据放在文件shuju3.txt中}
programmikong;
var
a,b,c:
array[1..4,1..4]ofinteger;{数组A用来存放迷宫路径,约定元素值为0表示通,1表示不通}
{数组B用来存放方向增量}
{数组C用来记录结果,当第I步移到某一元素时,该元素就等于I}
i,j,k,m,n:
integer;
fv:
text;
q:
boolean;{用来标记迷宫是否有出路}
procedureprint;
var
m,n:
integer;
begin
q:
=true;{如果打印步骤,表示肯定有出路}
writeln;
writeln;
writeln('穿越迷宫的步骤是:
');
form:
=1to4do
begin
forn:
=1to4do
write(c[m,n]:
4);
writeln;
end
end;
proceduretry(x,y,i:
integer);
var
u,v,k:
integer;
begin
fork:
=1to4do{可以有4个方向选择}
begin
u:
=x+b[k,1];{当前坐标加上方向增量}
v:
=y+b[k,2];
if(u>=1)and(u<=4)and(v>=1)and(v<=4)then{判断是否越界}
if(a[u,v]=0)and(c[u,v]=0)then{判断是否为0,为0就表示通,为1就表示不通}
begin
if(x=2)and(y=3)thenwriteln('aaaaaaaaaaaa');
c[u,v]:
=i;{数组C打上记号,表示此元素是第I步到达}
if(u<>4)or(v<>4)then{判断是否到出口}
try(u,v,i+1){没有就
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 游戏 开发 中的 经典 算法