数字迷宫

数字迷宫

第一部分 案例描述

案例目的

本案例为实现动态的刷新Dos界面,使用用户控制头像“消灭”窗口中出现的数字(无固定顺序)的游戏,来使学员加深对一维数组、二维数组、循环语句、选择程序设计以及相关系统函数的使用。

案例难度

★★★★

案例覆盖技能点

a) 选择程序设计

b) 循环程序设计

c) 用户、屏幕窗口的输入输出

d) 相关系统函数

e) 一维、二维数组

推荐案例完成时间

4

适用课程和对象

C语言案例(T阶段)

第二部分需求和开发环境

使用技术和开发环境

Microsoft Visual C++ 6.0

案例需求

本案例要求制作一个《数字迷宫》的游戏,该游戏的玩法描述为:

1、 系统主要地图为固定模式

2、 地图内部包含墙体、走廊、阿拉伯数字(1~7)、玩家头像(1)四种不同内容

3、 用户通过上、下、左、右按键来控制玩家头像在地图范围内的走动

4、 在玩家走动过程中,碰撞墙壁时,该步的走动无效,玩家头像原地不变

5、 玩家允许在设计走廊内部进行走动

6、 玩家头像遇到阿拉布数字时,数字消失,并且对玩家走动无影响

7、 玩家头像遭遇所有数字之后(地图上无阿拉伯数字),该局游戏结束,并自动开始下一局游戏

8、 在某一局游戏中,游戏走廊、墙体与其他游戏相同,但数字位置会随机产生

9、 阿拉伯数字产生在走廊内而非墙体上

10、 在玩家游戏过程中按下Esc键,游戏无条件退出。

11、 在玩家未使用Esc键时,程序正常运行

数字迷宫工作原理

1. 本程序分为初始——玩家运行——重启一局——结束四个阶段

a) 初始化阶段

i. 程序当中存在一18*24大小的固定地图数组

ii. 该数组以0/-1分别标识程序地图当中的“墙体”以及“走廊”

iii. 通过随机函数在走廊中产生17阿拉伯数字,并且将该系列数字写入二维数组的相应位置当中,对-1(走廊)进行覆盖

iv. 产生玩家位置:数组的(1,1)

v. 使用循环语句遍历打印出数组元素,元素包括

1. 墙体(0):■

2. 走廊(-1): 空格*2

3. 数字(1~7):数字本身+空格*1

4. 玩家头像:\1 即:J+空格*1

b) 玩家运行阶段

i. 玩家使用上下左右键进行头像控制

ii. 与墙体碰撞时,走动无效,原地不动(通过玩家头像位置标示与数组内部数据是否为墙体(0)来判断)

iii. 为一般走廊时,玩家原头像位置清空为双空格(通过玩家头像位置标示与数组内部数据是否为走廊(-1)来判断),玩家当前位置输出玩家头像,并更新玩家头像位置全局变量。

iv. 为数字时(通过玩家头像位置标示与数组内部数据是否为数字(>0)来判断),该数字消失,玩家原位置头像消失,新位置出现玩家头像,并将数组内消失数字位置置为走廊(-1), 并更新玩家头像位置全局变量。

v. 每走动一次系统遍历数组元素,判断数字(>0)多少,当数字存在数量>0时,该局继续,=0时,进入重启一局步骤。

c) 重启一局

i. 重复初始化阶段(注意要移动头像到(1,1)位置)

d) 结束程序

i. 用户点击Esc或强行关闭应用程序时,程序无条件退出。

第三部分功能点介绍

头文件引用列表

头文件名

功能简述

#include <stdio.h>

使用一般输入输出函数

#include <conio.h>

使用getch函数达到输入数据不敲回车进行下步计算功能

#include <time.h>

使用time(int)函数

#include "windows.h"

使用光标移动函数对光标进行编码定位

系统函数使用列表

函数名称

功能简述

getch();

 

printf

 

srand();

设置系统rand函数随机引资

time(NULL);

以时间作为随机因子产生不重复的随机数,提高程序效率

rand()

得到随机数

GetStdHandle

得到该程序HANDLE的函数

GetLastError();

得到系统最近错误编号函数

SetConsoleCursorPosition(Handle, {x,y});

代码设置系统光标位置函数

公共变量列表

变量名称

初始值

功能简述

int code[17][24]

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

0,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,

0,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,-1,0,0,0,0,0,-1,-1,-1,0,0,

0,-1,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0,0,

0,-1,-1,-1,-1,-1,0,-1,-1,-1,-1,-1,0,-1,0,-1,-1,-1,-1,-1,-1,-1,0,0,

0,-1,0,0,-1,0,-1,0,0,0,0,-1,0,-1,-1,-1,0,0,0,0,0,0,0,0,

0,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0,0,-1,0,0,0,0,0,0,0,0,

0,-1,0,0,0,0,0,0,0,0,0,-1,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,0,

0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,-1,0,0,-1,0,0,0,0,

0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,0,0,-1,0,0,0,0,

0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,-1,-1,-1,0,-1,-1,0,

0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0,

0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,

0,0,-1,-1,-1,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,

0,-1,-1,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,

0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

};

地图数组,0表示墙体,-1表示走廊

int postionX, postionY

postionX=1;  postionY=1;

玩家的初始位置

函数功能列表

函数名称

功能简述

void main()

程序接口函数,负责程序整体运行

void SetCode(int num);

该函数通过传入的num值来判断并输出为:■,空格*2,或者数字本身

void SetWindow();

生成地图主体函数:遍历公共数组,在位置部位(1,1)时,调用SetCode函数,并在(1,1)位置输出玩家头像

void SetNum();

程序初始化时,用于使用随机函数在数组“走廊”位置生成17的阿拉伯数字

void Begin();

初始化主体函数,设置玩家头像初始位置,调用SetNum函数

void LeftKey();

void UpKey();

void DownKey()

void RightKey();

玩家按下,上下左右按键时,分别调用的函数,该函数可判断玩家是否为被墙体阻挡、正常行走、“吃”掉数字三种状态,并改变玩家头像的位置。

int CheckLeftNum();

该函数判断数组内剩余的数字(>0)数量,返回该数量

void GoToXY(int x, int y);

该函数用于在x,y位置输出用户头像

void GoToXYSpace(int x, int y);

该函数用于在x,y处输出空格*2,用于用户走动时,消除之前位置处头像。 

/*
**作者:张迪
**版本:V1.3.1
**日期:2016.7.11
**功能:数字迷宫
**     实现鼠标选择选项,ESC退出系统、通过随机函数产生随机数等
*/
#include <stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include<time.h>
#include <conio.h>
int code[17][24]= {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0},
    {0,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,-1,0,0,0,0,0,-1,-1,-1,0,0},
    {0,-1,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0,0},
    {0,-1,-1,-1,-1,-1,0,-1,-1,-1,-1,-1,0,-1,0,-1,-1,-1,-1,-1,-1,-1,0,0},
    {0,-1,0,0,-1,0,-1,0,0,0,0,-1,0,-1,-1,-1,0,0,0,0,0,0,0,0},
    {0,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0,0,-1,0,0,0,0,0,0,0,0},
    {0,-1,0,0,0,0,0,0,0,0,0,-1,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,0},
    {0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,-1,0,0,-1,0,0,0,0},
    {0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,0,0,-1,0,0,0,0},
    {0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,-1,-1,-1,0,-1,-1,0},
    {0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0},
    {0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0},
    {0,0,-1,-1,-1,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0},
    {0,-1,-1,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0},
    {0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
int ii=1,p,q;//ii随机数,p行q列
int ss,ff=1,cc=1;
char ch;
int f;
void HideCursor()
{
    CONSOLE_CURSOR_INFO cursor_info = {1, 0};
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void Set();
void help();
void input()
{
	HWND hwnd=FindWindow("ConsoleWindowClass",NULL);/*  控制台窗口句柄 */
	POINT pos;
    while(1)
    {
        GetCursorPos(&pos);
		ScreenToClient(hwnd, &pos);
        int Y=pos.y;
        int X=pos.x;
		//printf("%6ld",GetAsyncKeyState (VK_LBUTTON));
        if (GetAsyncKeyState (VK_LBUTTON)) /* 鼠标左键单击 */
        {
			Sleep(100);
         if(Y>=95&&Y<=111&&X>=272&&X<=303)//开始
		 {ss=1;break;}
         if(Y>=127&&Y<=143&&X>=272&&X<=303)//帮助
		 {help();break;}
	     if(Y>=159&&Y<=175&&X>=272&&X<=303)//设置
		 {Set();break;}
	     if(Y>=191&&Y<=207&&X>=272&&X<=303)//退出
		 {ss=0;break;}
		Sleep(100);

        }
    }
}
void SetNum()//程序初始化时,用于使用随机函数在数组“走廊”位置生成1~7的阿拉伯数字
{
    int i,j;
    for(; ii<=7;)
    {
        i=rand()%17;
        j=rand()%24;
        if((code[i][j]==-1)&&(i!=1)&&(j!=1))
            code[i][j]=ii++;
        else SetNum();
    }

}
void gotoxy(int x,int y) //移动坐标
{
    COORD coord;
    coord.X=x;
    coord.Y=y;
    SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );
}
void banquan()
{
    gotoxy(20,19);
    printf("侵权必究,最终解释权归迪哥所有!!");
}
int Key(char ch)//获取方向
{
    if (ch == -32)
    {
        ch = getch();
        if (ch == 72) return 0;//printf("上\n");
        if (ch == 80) return 1;//printf("下\n");
        if (ch == 75) return 2;//printf("左\n");
        if (ch == 77) return 3;//printf("右\n");
    }
    return -1;
}
void SetCode(int num)//该函数通过传入的num值来判断并输出为:■,空格*2,或者数字本身
{
    if(num==0) printf("■");
    else if(num==-1)
    printf("  ");
    else if(num>=1&&num<=7) printf("%d ",num);
}
void Begin()//初始化主体函数,设置玩家头像初始位置,调用SetNum函数
{
    SetNum();
    int i,j;
    for(i=0; i<17; i++)
    {
        gotoxy(12,i);
        for(j=0; j<24; j++)
            SetCode(code[i][j]);
//        printf("\n");
    }
    gotoxy(14, 1);
    printf("%c ",1);
    gotoxy(5, 3);
    printf("*数*");
    gotoxy(5, 6);
    printf("*字*");
    gotoxy(5, 11);
    printf("*谜*");
    gotoxy(5, 14);
    printf("*宫*");
    gotoxy(25, 18);
    printf("按ESC键可退出游戏!");

}
int CheckLeftNum()//该函数判断数组内剩余的数字(>0)数量,返回该数量
{
    int f=0;
    for(int i=0; i<17; i++)
        for(int j=0; j<24; j++)
            if(code[i][j]>0)
                f++;
    return f;
}
void Switch(int f)
{
    switch (f)
    {
    case 0:
        q>0&&((code[q-1][p]==-1)||(code[q-1][p]>=1&&code[q-1][p]<=7))?q--:q;
        if(cc&&code[q][p]>=1&&code[q][p]<=7) puts("\n\a");code[q][p]=-1;

        break;//上
    case 1:
        q<16&&((code[q+1][p]==-1)||(code[q+1][p]>=1&&code[q+1][p]<=7))?q++:q;
        if(cc&&code[q][p]>=1&&code[q][p]<=7) puts("\n\a");code[q][p]=-1;
        break;//下
    case 2:
        p>0&&((code[q][p-1]==-1)||(code[q][p-1]>=1&&code[q][p-1]<=7))?p--:p;
        if(cc&&code[q][p]>=1&&code[q][p]<=7) puts("\n\a");code[q][p]=-1;
        break;//左
    case 3:
        p<23&&((code[q][p+1]==-1)||(code[q][p+1]>=1&&code[q][p+1]<=7))?p++:p;
        if(cc&&code[q][p]>=1&&code[q][p]<=7) puts("\n\a");code[q][p]=-1;
        break;//右
    }
}
void help();
void show();
void Set()
{
    int i;
    system("cls");
    for(i=0; i<24; i++)
    {
        Sleep(4);
        gotoxy(12+i*2,0);
        printf("■");
    }
    for(i=1; i<16; i++)
    {
        Sleep(4);
        gotoxy(58,i);
        printf("■");
    }
    for(i=23; i>0; i--)
    {
        Sleep(4);
        gotoxy(i*2+12,16);
        printf("■");
    }
    for(i=16; i>0; i--)
    {
        Sleep(4);
        gotoxy(12,i);
        printf("■");
    }
    gotoxy(30,3);
    printf("游 戏 设 置:");
    gotoxy(30,6);
      printf("扣0关闭声音");
    gotoxy(26,8);
    printf(" 扣任意键开启声音");/*
     HANDLE hOut;
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_BLUE |
                            FOREGROUND_INTENSITY|
                            BACKGROUND_RED |
                            BACKGROUND_GREEN |
                            BACKGROUND_BLUE |
                            BACKGROUND_INTENSITY);
    gotoxy(34,11);
    printf("# #");
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED |
                            FOREGROUND_GREEN |
                            FOREGROUND_BLUE |
                            FOREGROUND_INTENSITY);*/
    gotoxy(35,11);
    cc=getch()-48;
    if(cc==-21)
    {
        ss=0;
    }
    else
    {
        ss=1;
    gotoxy(28,14);
    system("pause");
    }

}
void show()
{
    int i;
     system("cls");
    HANDLE hOut;
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hOut,
                                FOREGROUND_RED |
                                FOREGROUND_GREEN |
                                FOREGROUND_BLUE |
                                FOREGROUND_INTENSITY);
    gotoxy(27,9);puts("游戏即将开始:  %");
    for(i=0; i<=100; i++)
    {
        gotoxy(40,9);
        Sleep(20);
        printf("%d",i);
//        SetConsoleTextAttribute(hOut,
//                                BACKGROUND_RED |
//                                BACKGROUND_GREEN |
//                                BACKGROUND_BLUE |
//                                BACKGROUND_INTENSITY);
    }
    system("cls");
    for(i=0; i<24; i++)
    {
        Sleep(8);
        gotoxy(12+i*2,0);
        printf("■");
    }
    for(i=1; i<16; i++)
    {
        Sleep(8);
        gotoxy(58,i);
        printf("■");
    }
    for(i=23; i>0; i--)
    {
        Sleep(8);
        gotoxy(i*2+12,16);
        printf("■");
    }
    for(i=16; i>0; i--)
    {
        Sleep(8);
        gotoxy(12,i);
        printf("■");
    }
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED |
                            FOREGROUND_INTENSITY|
                            BACKGROUND_RED |
                            BACKGROUND_GREEN |
                            BACKGROUND_BLUE |
                            BACKGROUND_INTENSITY);
    gotoxy(23,3);
    printf("\t数 \t字 \t迷 \t宫 ");
    gotoxy(34,6);
    printf("开始");
    gotoxy(34,8);
    printf("帮助");
    gotoxy(34,10);
    printf("设置");
    gotoxy(34,12);
    printf("退出");
    SetConsoleTextAttribute(hOut,
                            FOREGROUND_RED |
                            FOREGROUND_GREEN |
                            FOREGROUND_BLUE |
                            FOREGROUND_INTENSITY);
    banquan();
  input();
//    ss = getch()-48;
//    while(ss = getch())
//    {
//        if(ss==0)
//            continue;
//        else if(ss==27)
//        {
//            ss=0;
//            break;
//        }
//        else if(ss==50)
//        {
//            ss=2;
//            help();
//            break;
//        }
//        else if(ss==49)
//        {
//            ss=1;
//            break;
//        }
//        else if(ss==51)
//         {
//               Set();
//               break;
//         }
//    }

}
void help()
{
    int i;
    system("cls");
    for(i=0; i<24; i++)
    {
        Sleep(4);
        gotoxy(12+i*2,0);
        printf("■");
    }
    for(i=1; i<16; i++)
    {
        Sleep(4);
        gotoxy(58,i);
        printf("■");
    }
    for(i=23; i>0; i--)
    {
        Sleep(4);
        gotoxy(i*2+12,16);
        printf("■");
    }
    for(i=16; i>0; i--)
    {
        Sleep(4);
        gotoxy(12,i);
        printf("■");
    }
    gotoxy(15,3);
    printf("游 戏 说 明:");
    gotoxy(15,5);
    printf("1. 通过上下左右键控制头像走动");
    gotoxy(15,7);
    printf("2. 将地图中七个数字吃光");
    gotoxy(15,9);
    printf("3. 按esc可退出游戏");
    gotoxy(15,11);
    printf("4. 感谢您的使用,迪哥真心为您提供优质的游戏");
 gotoxy(15,13);

    printf("按任意键开始游戏,退出游戏请扣ESC:");
    gotoxy(40,15);
    printf("designed by dige!");
    ss = getch()-48;
    if(ss!=-21) ss=1;
}

int main()//程序接口函数,负责程序整体运行
{
    system("mode con cols=70 lines=23");
    HideCursor();//隐藏光标
    show();
    while(ss==1)
    {
        p = 1, q = 1;//定义用户初始位置在(1,1)
        srand((unsigned)time(NULL));//使用 time函数来获得系统时间,使用系统时间来做种子
        Begin();//打印地图
        while (ch = getch())//接收方向键输入方向
        {
            if(27==ch)//判断用户是否按下esc键
            {
                ff=0;//若是程序将结束循环
                break;
            }
            gotoxy(2*p+12, q);
            printf("  ");//覆盖掉上一步的笑脸轨迹
            f = Key(ch);//转译方向
            Switch(f);
            gotoxy(2*p+12, q);//更新用户坐标
            printf("%c ", 1);//输出用户位置

            if(CheckLeftNum()==0)//判断数组内剩余的数字(>0)数量,数量为零的话结束循环
            {
                gotoxy(20,19);
                printf("你真是太棒啦!");
                system("pause");//按任意键继续
                system("cls");
                break;
            }
        }
        if(ff==0)
        {
//            gotoxy(10,19);
            break;
        }
        ii=1;
        show();
    }
    gotoxy(23,20);//控制输出结束语句的位置
    return 0;
}
//EXIT


//puts("\n\a");

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值