本文中的推箱子玩法:上:W,下:S,左:A,右:D。
我从小就喜欢玩电脑游戏,但我所玩过的每一个游戏都难以满足我的需求。从此,我开始自己构思游戏,并希望将来能够掌握游戏设计技术,自己制作游戏。所以,高考完后,我毅然决然地选择了北邮计算机科学与技术专业。
当我第一次看到我们所使用的Dev C++的时候,我的内心是崩溃的,在我的眼中,这个C语言编译器能做的也就是读取数据,处理数据,再把结果输出来(当时我并没有发现计算机游戏做的也就是这事),设计出的程序的界面也就是一张黑板,就这玩意能搞出个游戏出来?好吧,如果你非要把猜数字当一个游戏我也没话说。
就当我对C语言的兴趣越来越弱的时候,QQ空间中一个贪吃蛇的C语言源码吸引了我的眼球;紧接着,我看到了同班大佬用C制作的推箱子。从那时起,我开始意识到使用C语言制作游戏并不是一件不可能的事。
不久,计导课上出现了数组这个玩意。数组说白了就是一种数据储存的方式,但这种奇特的数据储存方式却极大的方便了我们对数据的访问。
以前我们如果要保存10个整数,就需要定义10个变量(假设是A-J)去储存这些数;如果我想把这10个数中每个数都加上1,就要动用10条语句。
A=A+1;
B=B+1;
......
J=J+1;
而如果使用数组(假设是X[10])储存这些数,只需要一个循环,就能达到我的要求,即:
for(i=0;i<10;i++){
X[i]=X[i]+1;
}
想想看,如果要处理100个数的话,用数组是不是极大的减少了代码的数量?这就是数组的好处。
但这样的数组还是搞不出什么可以愉快玩耍的游戏来的。不过很快,我们班的大佬们给我介绍了我们当前所学数组的升级版——二维数组。
目前的一维数组可以被看做一行N列的数,也就是这样。
0 1 2 3……
[] [] [] []……
而二维数组可以储存M行N列的数,他可以储存M*N个数,也就是这样。
0 1 2……
0 [] [] []……
1 [] [] []……
2 [] [] []……
……………
这下有的玩了,如果数组中存的是字符的话,那么我们把数组中的东西输出出来,不就能构出一个图形吗?然后我们就可以通过对数组中某个储存单位的字符的改变,使输出后呈现出的图形发生改变,比如:
. . . 某操作 . . .
. $ .------> $ . .
. . . . . .
X[i][j]=’$’ X[i][j-1]=’$’
这不就有游戏的效果了吗?
当然,为了更好的游戏体验,我们需要用到system(“cls”);用于清除当前屏幕上的东西,随时更新图像。这样,我们至少可以做出个走地图的东西出来。
当然,光只有走地图还是不能算做游戏的,我们还需要在地图上加很多元素。比如说墙。
###############
# # # #
# # $ #
###############
这个时候该怎么办呢?
数组的能力体现出来了,在知道主角坐标(X,Y)的情况下,我们只需要判断坐标为(X+1,Y),(X-1,Y),(X,Y+1),(X+1,Y-1)的位置在数组中对应的值是不是#就可以了。用代码表示如下:
(其中map[][]中储存着地图每个坐标对应的元素,用#表示墙。X,Y为主角的位置坐标,key中储存着你输入的控制指令。)
If(key==’W’){
If(map[X][Y-1]!=’#’){
Y=Y-1;
}
}
这样一来,当你输入的控制指令为W(向上)时,计算机就会判断主角位置上方是什么,如果不是#,主角就可以向上走一格了。
运用这种方法,我们可以轻松整出一个走迷宫的游戏出来。如果我们在地图上增加更多元素,那游戏内容不就更丰富了吗?利用闲暇时间动手试一试吧。
顺带发一下我写的推箱子,其算法并不算是好算法,仅供大家参考:
#include
#include
char x[15][12];
int box[5][2]={5,6,2,3,6,1,9,8,4,2};//箱子的位置,每两个为一组,表示箱子的X,Y坐标
int flag[5][2]={2,1,1,10,13,10,4,4,9,1};//目标点的位置,每两个为一组,表示箱子的X,Y坐标
int actorx=8,actory=6;//主角的初始位置。
void move();//主角移动函数
void clearmap();//初始化与更新地图函数
void printmap();//打印地图函数
void movebox();//移动箱子函数
int adjwin();//胜利判断函数,若胜利则返回1
main()
{
char s;//储存控制指令的变量
clearmap();
printmap();
while(1){//死循环,让程序不至于中途退出
if(kbhit()){//判断是否按下按键
s=getch();//将按下的按键储存在s中
move(s);
s=0;
}
if(adjwin()==1){
printf("You win!\n");
system("pause");
return 0;//可以退出程序
}
}
}
void move(int key){
if(key=='A'||key=='a'){
if(x[actorx-1][actory]=='B'){
movebox(key);//如果主角上方是箱子,进入推箱子判断函数,下边同理
}
if(x[actorx-1][actory]==' '||x[actorx-1][actory]=='*'){
actorx-=1;//如果主角上方是空白处‘ ’或目标点‘*’,则上移,下面同理
}
}if(key=='D'||key=='d'){
if(x[actorx+1][actory]=='B'){
movebox(key);
}
if(x[actorx+1][actory]==' '||x[actorx+1][actory]=='*'){
actorx+=1;
}
}if(key=='W'||key=='w'){
if(x[actorx][actory-1]=='B'){
movebox(key);
}
if(x[actorx][actory-1]==' '||x[actorx][actory-1]=='*'){
actory-=1;
}
}if(key=='S'||key=='s'){
if(x[actorx][actory+1]=='B'){
movebox(key);
}
if(x[actorx][actory+1]==' '||x[actorx][actory+1]=='*'){
actory+=1;
}
}
system("cls");//清空屏幕
printmap();//打印地图,实现地图更新
}
void movebox(int key){
int i,j;
if(key=='A'||key=='a'){
for(i=0;i<5;i++){
if(box[i][0]==actorx-1&&box[i][1]==actory){
//判断那个箱子在主角的左方,下同理
if(x[box[i][0]-1][box[i][1]]!='#'){//判断箱子左方是不是墙,下同理
box[i][0]-=1;//箱子左移,下同理
clearmap();//更新箱子在地图中的位置,由于在箱子上上移后,主角上方变为空地,主角会上移,所以这里不需要变换主角位置
}
}
}
}
if(key=='D'||key=='d'){
for(i=0;i<5;i++){
if(box[i][0]==actorx+1&&box[i][1]==actory){
if(x[box[i][0]+1][box[i][1]]!='#'){
box[i][0]+=1;
clearmap();
}
}
}
}
if(key=='W'||key=='w'){
for(i=0;i<5;i++){
if(box[i][0]==actorx&&box[i][1]==actory-1){
if(x[box[i][0]][box[i][1]-1]!='#'){
box[i][1]-=1;
clearmap();
}
}
}
}
if(key=='S'||key=='s'){
for(i=0;i<5;i++){
if(box[i][0]==actorx&&box[i][1]==actory+1){
if(x[box[i][0]][box[i][1]+1]!='#'){
box[i][1]+=1;
clearmap();
}
}
}
}
}
void clearmap(){
int i,j;
for(j=0;j<12;j++){
for(i=0;i<15;i++){
x[i][j]=' ';//先把地图中所有东西清空
}
}
for(i=0;i<15;i++){
x[i][0]='#';
x[i][11]='#';
}
for(i=0;i<12;i++){
x[0][i]='#';
x[14][i]='#';
}
x[2][5]='#';
x[3][1]='#';
x[3][2]='#';
x[3][3]='#';
x[3][4]='#';
x[3][5]='#';
x[4][5]='#';
x[5][5]='#';
x[6][5]='#';
x[7][5]='#';
x[7][6]='#';
x[7][7]='#';
x[7][8]='#';
x[8][8]='#';
//安放墙
for(i=0;i<5;i++){
x[flag[i][0]][flag[i][1]]='*';
}
//安放目标点
for(i=0;i<5;i++){
x[box[i][0]][box[i][1]]='B';
}
//安放箱子,其位置上有目标点,则覆盖之
}
int adjwin(){
int i,j,k=0;
for(j=0;j<12;j++){
for(i=0;i<15;i++){
if(x[i][j]=='*'){
k=1;
}
}
}
if(k==1){
return 0;
}else{
return 1;
}
}//判断地图上所有目标点是否被覆盖,若是,则返回1
void printmap(){
int i,j,k;
for(j=0;j<12;j++){
for(i=0;i<15;i++){
if(i==actorx&&j==actory){
printf("$ ");//将主角当前位置用$表示
}else{
printf("%c ",x[i][j]);
}
}
printf("\n");
}
}//打印地图中所有符号
(效果图和上方推箱子图一样)
如果多想想的话,在使用二维数组的情况下,我们可以搞出平面游戏出来,那如果使用三维数组呢?如果使用n维数组呢?那可就更好玩了。