900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 在LINUX环境终端下用C语言实现推箱子小游戏

在LINUX环境终端下用C语言实现推箱子小游戏

时间:2020-04-02 11:09:35

相关推荐

在LINUX环境终端下用C语言实现推箱子小游戏

首先要玩这个游戏得先获取键盘的键值,从而判定方向

获取方向键的功能:使用头文件 getch.h 中的gech函数

代码如下:

#ifndef GETCH_H#define GETCH_H#include <termios.h>#include <unistd.h>//修改终端的控制方式,1取消回显、确认2获取数据3还原static int getch(void){// 记录终端的配置信息struct termios old;// 获取终端的配置信息tcgetattr(STDIN_FILENO,&old);// 设置新的终端配置 struct termios new = old;// 取消确认、回显new.c_lflag &= ~(ICANON|ECHO);// 设置终端配置信息tcsetattr(STDIN_FILENO,TCSANOW,&new);// 在新模式下获取数据 int key_val = 0; do{key_val += getchar();}while(stdin->_IO_read_end - stdin->_IO_read_ptr);// 还原配置信息tcsetattr(STDIN_FILENO,TCSANOW,&old); return key_val; }#endif//GETCH_H

建立好头文件后由电脑到虚拟的LINUX环境步骤如下:

1、在windows中把getch.h头文件放入共享文件夹2、终端进入贡献文件夹:cd /media/sf_Share3、复制头文件到共享库sudo cp getch.h /usr/include/4、加读取权限:sudo chmod +r /usr/include/gerch.h

分别测试一下上下左右的键值

#include <stdio.h>#include<getch.h>int main(int argc,const char*argv[]){for(int i=0;i<4;i++)printf("%d ",getch());}

得到的方向以及键值如下:

上:183 下:184 右:185 左:186

再大致分析一下代码的整体轮廓

1.确定各种对应关系,墙体、路等用什么表示

2.画好地图

3.移动规则

4.判定规则

准备好这些就可以写代码啦

1.首先分析一下情况

推箱子游戏由路、墙、人、箱子以及目标组成

所以可以考虑用不同的数字代表这些情景,结合二维数组构成基本的地图

我这里的设定如下:分别用数字0、1、 2、 3、 4代表路、墙、人、箱子以及目标

2.地图定义如下:

int arry[8][8]={{1,1,1,1,1,1,1,1},{1,1,1,4,4,1,1,1},{1,1,1,0,4,1,1,1},{1,1,0,0,3,4,1,1},{1,1,0,3,0,0,1,1},{1,0,0,1,3,3,0,1},{1,2,0,0,0,0,0,1},{1,1,1,1,1,1,1,1}};//0路1墙2人3箱子4目标

打印效果如下

for(i=0;i<8;i++){for(j=0;j<8;j++){switch(arry[i][j]){case 1:printf(" * ");break;case 0:printf(" ");break;case 2:printf(" @ ");break;case 3:printf(" # ");break;case 4:printf(" o ");break;}}printf("\n");}

可以看到已经有了基本轮廓

3.然后我们分析一下移动规则:

(1)移动方向前方是路则可以向前

移动方向前方是目标可以向前

以前前方如果是箱子,而箱子前方是目标或者路可以向前推动

4.胜利规则的判定,由于目标点是自己定的,知道坐标的情况下可以直接判断目标点上的值,

例如这里是(1,3)(1,4)(2,4)(3,5)

如果这些坐标上的值都等于3,说明箱子都归位了

在二维数组的基础上和好理解,定义indix1、indix2分别是人的行和列下标

则人的:

上方向 arry [indix1-1] [indix2]下方向 arry [indix1+1] [indix2]左方向 arry [indix1] [indix2-1]右方向 arry [indix1] [indix2+1]

向上移动的代码例子如下:

switch(getch())//获取键值{case 183: //移动方向向上if(arry[indix1-1][indix2]==0||arry[indix1-1][indix2]==4)//行坐标-1,判断上方是路或者目标则可以向上移动,{arry[indix1-1][indix2]=2;//把地图上人的位置重新赋值、更新if((indix1==1&&(indix2==3||indix2==4))||(indix1==2&&indix2==4)||(indix1==3&&indix2==5))arry[indix1][indix2]=4;//走出的位置是目标点,标记回目标 elsearry[indix1][indix2]=0; //否则变回路indix1=indix1-1; //把人的下标更新,方便下次判断cnt++; //记录步数}else if(arry[indix1-1][indix2]==3) //如果上方是箱子的话{if(arry[indix1-2][indix2]==0||arry[indix1-2][indix2]==4) //箱子前面如果是路或者目标则可以推{arry[indix1-2][indix2]=3;//箱子的位置更新arry[indix1-1][indix2]=2;//人的位置更新if((indix1==1&&(indix2==3||indix2==4))||(indix1==2&&indix2==4)||(indix1==3&&indix2==5))arry[indix1][indix2]=4;//走出的位置是目标点,标记回目标 elsearry[indix1][indix2]=0;//否则变回路indix1=indix1-1;//把人的下标更新,方便下次判断cnt++;}}break;

后面几个方向的原理类似,只要把代码复制下去改一下方向即可,篇幅原因,这里不贴出来

几个方向间的代码有很多的雷同之处,可以考虑总结一下优化代码

在前面提到过,这是方向的表示:上方向 arry [indix1-1] [indix2]下方向 arry [indix1+1] [indix2]左方向 arry [indix1] [indix2-1]右方向 arry [indix1] [indix2+1]对于上下方向、左右方向,可以分别用一个变量表示,获取相应键值后对不同变量进行赋值这里用up表示上下、on表示左右方向 arry [indix1+up] [indix2+on]对于(up,on)=(-1,0)/(1,0)/(0,-1)/(0,1)就能表示各个方向了对于移动、推箱子后的更新,可以考虑另一种赋值关系,这样对于出入目标值、成功的判断就不用坐标判断法定义如下:1、人移动到新的位置或者目标,则该处坐标+=2,即加上人对应的数值,离开则-=2这样子若移动的方向是路0+2=2,若是目标4+2=6,所以6打印的也是人离开原位2-2=0,还原路;6-2=4还原目标2、推箱子也是一样,如果能推,箱子要移动到的坐标的值+=3,人移动到箱子的位置-=1;离开原位-=2这样子若移动的方向是路0+4=2,移动到箱子的位置3-1=2(打印的还是人),离开原位2-2=0,还原路;、若是目标4+3=7,所以7打印的也是箱子,并且是到了目标的箱子!!原理基本就这样优化后的代码cnt=0; //记录箱子进入目标的个数,全部进入判定成功up=0; //清除上一次的方向on=0; //清除上一次的方向switch(getch()) //获取键值并决定移动方向{case 183:up--;break;case 184:up++;break;case 185:on++;break;case 186:on--;break;}if(0==arry[indix1+up][indix2+on]||4==arry[indix1+up][indix2+on])//是路或者目标{arry[indix1+up][indix2+on] +=2; //新位置arry[indix1][indix2] -=2; //旧位置indix1 +=up;//更新人的坐标indix2 +=on;step++;//记录步数}else if(3==arry[indix1+up][indix2+on]||7==arry[indix1+up][indix2+on])//是箱子{if(arry[indix1+up*2][indix2+on*2]==0||arry[indix1+up*2][indix2+on*2]==4) //箱子要移动的方向是路或者目标{arry[indix1+up*2][indix2+on*2] +=3;//箱子的新位置arry[indix1+up][indix2+on] -=1; //人去到箱子原位置arry[indix1][indix2] -=2;//人原来的位置indix1 +=up;//更新人的下标indix2 +=on;step++; //记录步数}}

总的代码如下:

#include <stdio.h>#include<getch.h>#include<stdlib.h>int main(int argc,const char*argv[]){int arry[8][8]={{0,0,0,1,1,1,0,0},{0,0,1,4,4,1,0,0},{0,0,1,0,4,1,1,0},{1,1,0,0,3,4,1,0},{1,1,0,3,0,0,1,1},{1,0,0,0,3,3,0,1},{1,2,0,0,0,0,0,1},{1,1,1,1,1,1,1,1}};//1墙2人3箱子4目标//3+4=7箱子//2+4=6人int up,on,i,j,cnt=0,step=0,indix1=6,indix2=1;while(1){system("clear"); //清屏cnt=0;up=0;on=0;for(i=0;i<8;i++){for(j=0;j<8;j++){switch(arry[i][j]){case 1:printf(" * ");break;case 0:printf(" ");break;case 2:printf(" @ ");break;case 3:printf(" # ");break;case 4:printf(" o ");break;case 6:printf(" @ ");break;case 7:cnt++; //统计一下目标与箱子叠加的个数printf(" # ");break;}}printf("\n");}if(cnt==4) //四个箱子都在目标位置上就说你成功了{printf("走了:%d步数",step);return 0;}cnt=0;up=0;on=0;switch(getch()){case 183:up--;break;case 184:up++;break;case 185:on++;break;case 186:on--;break;}if(0==arry[indix1+up][indix2+on]||4==arry[indix1+up][indix2+on]){arry[indix1+up][indix2+on] +=2;arry[indix1][indix2] -=2;indix1 +=up;indix2 +=on;step++;}else if(3==arry[indix1+up][indix2+on]||7==arry[indix1+up][indix2+on]){if(arry[indix1+up*2][indix2+on*2]==0||arry[indix1+up*2][indix2+on*2]==4){arry[indix1+up*2][indix2+on*2] +=3;arry[indix1+up][indix2+on] -=1;arry[indix1][indix2] -=2;indix1 +=up;indix2 +=on;step++;}}}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。