来自童晶老师的游戏开发课程作业

此作业的要求参见:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11577

作业要求

1.课程网址 [https://www.icourse163.org/course/HHU-1206797807]

2.项目名称及分值

游戏名称满分分值功能点提示
生命游戏 20 随机初始化、生命算法、刷新显示

 

 

 

 

3.作业提交要求

除代码及git以外,要求 WBS、PSP,要求使用博客报告完成的功能和截图,讲解
关键技术和代码片断。其中WBS要求包括不限于每个子任务的工时估算时间和实
际耗时,精确到分钟。子任务可以包括分析、设计、代码、测试、调试、文档,
鼓励精确到二级子任务如功能点等。

项目coding地址: https://e.coding.net/jianghui2/lifegame/lib.git

项目PSP:

 

类型任务开始时间结束时间中断时间(分钟)delta时间(分钟)
准备 问题了解及主要算法流程设计 12.18  19:28 12.18 20:12 0 44
编程 代码编写 12.19  9:04 12.19  12:33 5+6 198
编程 代码调试 12.19  18:06 12.19  19:50 2+5 97
文档 技术文档编写 12.20  10:34 12:20  11:30 0 56

 

项目WBS:

 

 

关键技术:

1.随机初始化
 

为了实现随机初始化,调用了stdlib.h头文件中的rand函数,在c语言中用来产生一个随机数的函数。srand函数是随机数发生器的初始化函数。

rand()函数每次调用前都会查询是否调用过srand(seed),是否给seed设定了一个值,如果有那么它会自动调用srand(seed)一次来初始化它的起始值。若之前没有调用srand(seed),那么系统会自动给seed赋初始值,即srand(1),自动调用它一次。

为了避免rand()产生随机数时,因srand(seed)相同产生而产生相同的的随机数数组。所以在这里采用时间作种子 srand((unsigned)time(NULL))。每次运行程序的时间肯定是不相同的,产生的随机数就也不一样了。rand()产生的随机数和2取余得到随机的0或1,然后将随机数循环赋值给每一个细胞,得到一个随机的细胞生命的初始化状态。

 
void randStart()// 数据随机初始化
{
    int i, j;
    srand((unsigned)time(NULL));//让rund函数在每次程序运行中产生不同的随机数
    for ( i = 0; i < High; i++)
    {
        for ( j = 0; j < Width; j++)
        {
            cells[i][j] = rand() % 2;//随机数与2取余,得到随机的0或1
        }
    }
}

 

2.生命算法
 

根据生命游戏演化的规则:

一个由N*M个放个组成的矩形中,每个方格可以包含一个细胞,不在边上的有机体有8个相邻方格。

1. 如果一个细胞周围有3个细胞为生,则该细胞为生(即该细胞若原先为死,则转为生,若原先为生,则保持不变)

2. 如果一个细胞周围有2个细胞为生,则该细胞的生死状态保持不变

3. 在其它情况下,该细胞为死(即该细胞若原先为生,则转为死,若原先为死,则保持不变)

 
 

根据上述规则,用一个临时的二维数组nextCells,来记录Cells的下一个状态。每次对Cells中的点的周围情况neibourNumber进行统计,并据此更新nextCells的值,然后用nextCells更新cells的值。

 
void cellUpdate()
{
    int nextCells[Width][High];// 下一帧的细胞生命状态
    int neibourNumber;//细胞周围生存细胞数
    int i, j;
    for ( i = 1; i <= High-1; i++)
    {
        for ( j = 1; j <= Width-1; j++)
        {
            neibourNumber = cells[i - 1][j - 1] + cells[i - 1][j] + cells[i - 1][j + 1] + cells[i][j - 1] + cells[i][j + 1] + cells[i + 1][j - 1] + cells[i + 1][j] + cells[i + 1][j + 1];
            if (neibourNumber == 3)
            {
                nextCells[i][j] = 1;
            }
            else if (neibourNumber == 2)
            {
                nextCells[i][j] = cells[i][j];
            }
            else
                nextCells[i][j] = 0;
        }
    }
    for (i = 1; i <= High - 1; i++)
    {
        for ( j = 1; j <= Width-1 ; j++)
        {
            cells[i][j] = nextCells[i][j];
        }
    }
}
 
3.刷新显示
 
3.1移动光标

在这里使用了控制台API函数SetConsoleCursorPosition,这个函数的功能是设置控制台光标坐标(Set--设置、Console--控制台、Cursor--光标、Position--坐标),使用这个函数需要两个参数:第一个参数类型为HANDLE,第二个参数类型为COORD。

HANDLE是用来定义任何类型的句柄。函数功能:获取指定的标准设备的句柄,使用GetStdHandle需要一个参数,参数的取值有三种

1.STDINPUTHANDLE----标准输入句柄,

2.STDOUTPUTHANDLE----标准输出句柄,

3.STDERRORHANDLE----标准错误句柄。

所以在此处赋值给handle的是标准输出句柄

COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标

使用上述类型以及函数必须包含windows.h头文件

 
void gotoxy(int x, int y)//将光标移动到坐标(x,y)
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD pos;
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);//设置控制台光标坐标
}
 
3.2 刷新显示 
 
void showCell()//从原点坐标刷新细胞状态
{
    gotoxy(0,0);//清理上一帧状态
    int i, j;
    for ( i = 1; i <= High-1; i++)
    {
        for ( j = 1; j <= Width-1; j++)
        {
            if (cells[i][j]==1)
            {
                cout << "*";
            }
            else
            {
                cout << " ";
            }
        }
        cout << endl;
    }
}
 
4.主函数及效果展示图
 
int main()
{
    char judge;
    int count=0;
    int L;
    randStart();
    cout << "是否开始初始化细胞状态(Y/N)?" << endl;
    cin >> judge;
    while (judge!= 'Y' && judge!= 'y' && judge!= 'N' && judge!= 'n') {
        cout << "输入错误,请重新输入(Y/N)" << endl;
        cin >> judge;
    }
    while (judge== 'Y' || judge== 'y') {
        showCell();
        cellUpdate();
        count++;
        cout << "当前为第" << count <<"次繁衍后的细胞生命状态"<< endl ;
        cout << "请输入是否继续(Y/N)?" << endl;
        for(L=0;L<20;L++)
            cout << "                                                                " <<endl;
        gotoxy(0,31);
        cin >> judge;
        while (judge!= 'Y' && judge!= 'y' && judge!= 'N' && judge!= 'n') {
        cout << "输入错误,请重新输入(Y/N)" << endl;
        cin >> judge;
        }
    }
    cout << "感谢试玩!欢迎下次继续!" << endl;
    return 0;
}

 

 

 

 

 


 

 

posted @ 2020-12-22 22:50  蒋慧  阅读(201)  评论(0编辑  收藏  举报