C的第一个“大作业”——小游戏:没有推箱子的Helltaker

想了想还是发下这东西,太喜欢写注释了,虽然没啥营养内容,但还是希望新人轻松点。

极致偷懒不想用图形库,所以被批评简陋了
内容:没有推箱子的Helltaker(下附有推箱子的代码
大概是三天赶作业的原因,所以没加推箱子逻辑,参考的只有推箱子绘制地图的方法(还不就是造点没用的轮子)
能看出的缺点太多,但是不太想完善了(画面音乐和把妹王差太多了)
不管怎么说吧,也是小成就了哈哈哈

有挺多没用的代码,为了凑要求的……见谅

/*没有推箱子的Helltaker
作者:chiha
游戏说明:
    1、选择地图;
    2、设置人物初始位置;
    3、地图图标说明:★是钥匙,♀是操控人物,◎是出口;
    4、操作方法:
        大小写WASD或方向键控制移动;
        大小写R重置所选地图的人物初始位置;
        大小写Q退出游戏;
            ---函数库---
--初始目标--
    步数计数器                  有
    位置记录                    有
    移动键                      有
    人物输出&地图输出(图)       有
    地图创建(包括入口和出口)    有
    初始人物位置                 有
--最终目标--
    地图选择                     有
    最优路径查找(限制步数)       无
    钥匙设置                     有
    添加音乐                     无
-新想法-
    限制只能用小写awsdqr(加入ctype.h中的识别函数islower())
*/
// #include
#include
#include
#include       //getch()
#include     //Sleep()
#include
#define MAX 10
typedef int Key;
typedef struct Position{
    int x,y;
}POS;
typedef struct MAP{
    int x[MAX][MAX];
}map;
//int next[4][2]={(1,0),()} 如果采用小括号赋值,括号整体的值是最后一个元素的值
int next[4][2]={{0,1},{0,-1},{1,0},{-1,0}};    //移动坐标
int cnt = 0;      //步数计数
POS Origin;       //人物原始位置
//地图库
map Maplib_1 = {
     1,1,1,1,1,1,1,1,1,1,
     1,0,0,1,0,1,0,0,0,1,
     1,0,0,1,0,0,0,0,0,1,
     1,0,0,0,1,0,1,0,0,1,
     1,0,0,0,0,0,0,1,0,1,
     1,1,1,0,1,1,1,0,0,1,
     1,0,0,0,0,0,0,1,0,5,
     1,0,1,1,0,1,0,0,0,1,
     1,0,1,0,0,1,0,1,1,1,
     3,0,0,0,1,1,1,1,1,1};//10行10列
map Maplib_2 = {
     1,1,1,1,1,1,1,1,1,1,
     1,0,0,0,0,0,0,0,0,1,
     1,0,1,1,0,1,1,1,0,1,
     1,0,0,3,1,0,1,0,0,1,
     1,0,1,0,0,0,0,1,0,1,
     1,0,1,0,1,1,1,1,0,1,
     1,0,1,0,0,1,0,1,0,5,
     1,0,0,0,0,0,0,1,0,1,
     1,0,1,0,0,1,0,0,0,1,
     1,1,0,1,1,1,1,1,1,1};
int move_Ctrl(POS &A, map M);    //移动控制
int  move_Judge(POS A,map M);    //移动判断   判断人物是否与地图障碍重叠  返回值为 1重叠 0正常
void create_Map(map &M);         //创建地图   int M[][10]  int只存地址  (全局变量map实现,无法换地图)
void init_Pos(POS &A, map M);    //初始位置   手动输入xy
int  pace_Count(int &c);         //步数记录   全局变量cnt实现
int  output_Cha(POS A,map M);    //人物输出   修改地图来实现
int  key_exit(POS A,map M,Key &k,int c);//钥匙设置
int  key_Delete(map &M, POS A);  //在地图上删除钥匙的位置
void game_WIN(int c);            //游戏结束
void game_load();                //游戏加载模拟
void game_intr();                //游戏介绍
int  map_Select(map &M);         //地图选择
void map_Show(map M1,map M2);    //地图展示
int main(){
    map Map;        //地图地址
    POS pos;        //人物位置
    Key k = 0;      //钥匙是否获取flag
    int move_Status = 0; 
    game_intr();
    map_Show(Maplib_1,Maplib_2);
    map_Select(Map);
    init_Pos(pos,Map);
    game_load();
    //create_Map(Map);
    do{
        system("cls");                  //刷新屏幕
        key_exit(pos,Map,k,cnt);        //1111
        output_Cha(pos, Map);
        move_Status = move_Ctrl(pos,Map);
        key_exit(pos,Map,k,cnt);        //2222必须两遍,否则会无法结束游戏
        key_Delete(Map, pos);
        if(move_Status != 7)            //加了这句if步数正常了,不用再/2处理
            pace_Count(cnt);
    }while(1);
    return 0;
}
void game_intr(){
    printf("游戏说明:\n1、选择地图;\n2、设置人物初始位置;\n3、地图图标说明:★是钥匙,♀是操控人物,◎是出口;\n4、操作方法:\n大小写WASD或方向键控制移动;\n大小写R重置所选地图的人物初始位置;\n大小写Q退出游戏;\n");
}
int  key_Delete(map &M, POS A){
    if(M.x[A.x][A.y] == 3)
        M.x[A.x][A.y] = 0;
    return 0;
}
void game_load(){
    system("cls");printf("正在生成所选地图");Sleep(500);printf(".");
    Sleep(500);printf(".");Sleep(500);printf(".");Sleep(500);
    system("cls");printf("正在加载人物");Sleep(500);printf(".");
    Sleep(500);printf(".");Sleep(500);printf(".");Sleep(500);
}
void map_Show(map Maplib_1,map Maplib_2){
    for(int i = 0; i < 10; i++){
        for(int j = 0; j < 10; j++){
            switch (Maplib_1.x[i][j])
            {
            case 0:
                printf("  "); //空白的地方
                break;
            case 1:
                printf("■");  //墙
                break;
            case 3:
                printf("★"); //钥匙
                break;
            case 5:
                printf("◎"); //出口
                break;
            }
        }
        printf("\n");
    }
    printf("地图1\n\n");
    for(int i = 0; i < 10; i++){
        for(int j = 0; j < 10; j++){
            switch (Maplib_2.x[i][j])
            {
            case 0:
                printf("  "); //空白的地方
                break;
            case 1:
                printf("■");  //墙
                break;
            case 3:
                printf("★"); //钥匙
                break;
            case 5:
                printf("◎"); //出口
                break;
            }
        }
        printf("\n");
    }
    printf("地图2\n\n");
}
int  map_Select(map &M){
    int n;
    printf("地图选择");
    sss:printf("(可选1,2):");//sss
    scanf("%d",&n);
    printf("\n");
    switch (n)
    {
    case 1:
        M=Maplib_1;
        printf("你选择了我,我是いちぽ哒!\n");
        break;
    case 2:
        M=Maplib_2;
        printf("你选择了我,我是にぽ哒!\n");
        break;
    default:
        printf("我没有那么厉害啦!!!\n");
        printf("重新选咯~");
        // map_Select(M); //递归不好实现,改用goto
        goto sss;
    }
    return 0;
}
void game_WIN(int c){
    int n;
    system("cls");
    printf("成功\n");
    printf("花费步数:%d\n",c);//计数会计数两遍,暂时作/2处理
    printf("按R重置游戏,按Q退出游戏\n");
}
int  key_exit(POS A,map M,Key &k,int c){
    if(M.x[A.x][A.y] == 3)
        k = 1; //拿到钥匙
    if(k == 1 && M.x[A.x][A.y] == 5)
        game_WIN(c); //拿到钥匙且走到出口
    return 0;
}
int move_Ctrl(POS &A,map M){
    int dir;//方向键
    // Origin_CG = A;//保留上一步
    dir = getch();//getchar()需要回车
    // if(islower(dir)||dir==75||dir==72||dir==77||dir==80)//加这句只限制小写后,用方向键操作会加倍步数
        switch (dir){
        //case 'A':
        case 'a':
        case 75:            //左
            A.y--;          //数组反向思维
            if(move_Judge(A,M)==1)
                A.y++;      //重叠就重新输入
            break;
        //case 'W':
        case 'w':
        case 72:            //上
            A.x--;          
            if(move_Judge(A,M)==1)
                A.x++;  
            break;
        //case 'D':
        case 'd':
        case 77:            //右
            A.y++;
            if(move_Judge(A,M)==1)
                A.y--;  
             break;
        //case 'S':
        case 's':
        case 80:            //下
            A.x++;
            if(move_Judge(A,M)==1)
                A.x--;  
             break;
        //case 'R':
        case 'r':
            A = Origin;
            //cnt = -1;         //因为main执行后会加一所以需要改为-1
            cnt = 0;            //或者和退出Q一样用返回值7
            return 7;           
        //case 'Q':
        case 'q':
            Sleep(1000);      //慢一点退出
            exit(-2);
        default:
            //exit(-2);       //测试暂定直接退出
            return 7;         //7的意志!!!
    }
    return 0;
}
void init_Pos(POS &A,map M){
    printf("\n请输入人物的初始位置: x = ");
    scanf("%d",&A.y);
    printf("%23sy = ");//刚刚好对齐
    scanf("%d",&A.x);
    A.y--;
    A.x--;
    Origin = A;
    if(A.y > 9 || A.x > 9 || move_Judge(A, M)){ //人物是否生成越界或者与地图重叠
        printf("你不能出现在这!!!\n");
        init_Pos(A,M);
    }
}
int  move_Judge(POS A,map M){
    if(M.x[A.x][A.y]==1)
        return 1;       //重叠地图 1
    return 0;           //正常    0
}
int  pace_Count(int &c){
    c++;
    return 0;
}
int  output_Cha(POS A,map M){
    M.x[A.x][A.y] = 2; //把人放到地图上先————先前已经判断重叠,这里直接放
    for(int i = 0; i < 10; i++){
        for(int j = 0; j < 10; j++){
            switch (M.x[i][j])
            {
            case 0:
                printf("  "); //空白的地方
                break;
            case 1:
                printf("■");  //墙
                break;
            case 2:
                 printf("♀");  //人 
                break;
            case 3:
                printf("★"); //钥匙
                break;
            case 5:
                printf("◎"); //出口
                break;
            default:
                break;
            }
            if(i==6 && j==9)
                printf("  已走步数:%d",cnt);
            if(i==7 && j==9)
                printf("  按R重新开始");
        }
        printf("\n");
    }
    return 0;
}

以下是推箱子的,实在找不到原作者了,实在抱歉。。。(作为轮子来说应该也没太大关系)

#include<stdio.h>
#include<conio.h> 
#include<windows.h>

int map[9][11]={
    {0,1,1,1,1,1,1,1,1,1,0},
    {0,1,0,0,0,1,0,0,0,1,0},
    {0,1,0,0,3,0,0,0,0,1,0},
    {0,1,0,3,0,3,3,3,0,1,1},
    {0,1,0,0,0,2,0,0,0,0,1},
    {1,1,0,0,1,1,1,0,3,0,1},
    {1,0,4,4,0,4,0,0,0,0,1},
    {1,0,4,4,0,4,4,3,0,1,1},
    {1,1,1,1,1,1,1,1,1,1,0}
    };//原始的图表,五行六列,其中 0 代表着空白的地方; 1 代表着墙;2 代表着人;
                  //3 代表着箱子;4 代表着箱子的终点位置。 

                      //图的变化要靠自己来编写数组,通过数字来进行图的构造。
int drawmain();
int tuidong();
int winshu();

int main()//主函数 
{
    while(1)
    {
        system("cls");//对其进行清屏 
         drawmain();
         tuidong();

    }
    printf("shuchu \n");
    return 0;
 } 
//把图形刻画出来

int drawmain()
{    
  int i,j;
    winshu();//调用输赢的函数 
    for(i=0;i<9;i++)
    {
       for(j=0;j<11;j++)
              {
                     switch(map[i][j])
                     {
                             case 0:
                                 printf("  "); //空白的地方
                                 break;
                             case 1:
                                 printf("■"); //墙 
                                 break;
                             case 2:
                                 printf("♀"); //人 
                        break;
                    case 3:
                        printf("☆"); //箱子 
                        break;
                    case 4:
                        printf("◎"); //终点地方 
                         break; 
                    case 6:
                        printf("♂");//人加终点位置 
                        break;
                    case 7: 
                        printf("★") ;//箱子加终点位置
                        break;
                     }
              }
       printf("\n");
    }       
} 

 //进行小人的移动,整个移动的过程就是数组变化的过程 
int tuidong()
{
    int count,caw=0;//行和列 
    int i,j,tui;
    for(i=0;i<9;i++){
        for (j=0;j<11;j++)
        {
            if(map[i][j]==2||map[i][j]==6)
            {
                count=i;
                caw=j;
            }
        }       
    }

    tui=getch();//与getchar()有区别的是:getchar()输入一个字符后需要回车来进行下一个字符的输入,
                    //比较麻烦 ,getch()则不需要回车就能连续输入多个字符。 
    switch(tui)
    {//上
        case 'W':
        case 72:
            // 1.人的前面是空地;
            // 2.人的前面是终点位置;
            // 3.人的前面是箱子
            //3.1.箱子的前面是空地;
            //3.2.箱子的前面是终点位置。
         if(map[count-1][caw]==0||map[count-1][caw]==4)
            {
                map[count][caw]-=2;
                map[count-1][caw]+=2;
            } 
         else if(map[count-1][caw]==3||map[count-1][caw]==7)
            {
                if(map[count-2][caw]==0||map[count-2][caw]==4)
                {
                  map[count][caw]-=2;
                  map[count-1][caw]-=1;
                  map[count-2][caw]+=3;
                }
            }
        break;

//下 
        case 'S':
        case 80://键值 
             if(map[count+1][caw]==0||map[count+1][caw]==4)
            {
                map[count][caw]-=2;
                map[count+1][caw]+=2;
            }

             else if(map[count+2][caw]==0||map[count+2][caw]==4)
            {
                   if(map[count+1][caw]==3||map[count+1][caw]==7)
                {
                  map[count][caw]-=2;
                  map[count+1][caw]-=1;
                  map[count+2][caw]+=3;
                }
            }
            break;
//左 
        case 'A':
        case 75:
                 if(map[count][caw-1]==0||map[count][caw-1]==4)
            {
                map[count][caw]-=2;
                map[count][caw-1]+=2;
            }

              else if(map[count][caw-2]==0||map[count][caw-2]==4)
            {
                   if(map[count][caw-1]==3||map[count][caw-1]==7)
                {
                  map[count][caw]-=2;
                  map[count][caw-1]-=1;
                  map[count][caw-2]+=3;
                }
            }
            break;
//右 
        case 'D':
        case 77:
                 if(map[count][caw+1]==0||map[count][caw+1]==4)
            {
                map[count][caw]-=2;
                map[count][caw+1]+=2;
            }

              else if(map[count][caw+2]==0||map[count][caw+2]==4)
            {
                 if(map[count][caw+1]==3||map[count][caw+1]==7)
                {
                  map[count][caw]-=2;
                  map[count][caw+1]-=1;
                  map[count][caw+2]+=3;
                }
            }
            break;

}
} 

int winshu() 
{
    int k = 0;//初始化
    int j,i;
    for(i=0;i<9;i++)
    {
        for (j=0;j<11;j++)
        {
             if(map[i][j]==3)
                 k++;
        }
    }
    if(k==0)
        printf("恭喜你,你赢了!\n");
}

共勉

全部评论

相关推荐

11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
头像
11-09 17:30
门头沟学院 Java
TYUT太摆金星:我也是,好几个华为的社招找我了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务