视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
纸牌游戏-课程设计报告
2025-10-03 04:08:06 责编:小OO
文档
课程设计报告

2009 ~2010  学年第 2 学期

课程         数据结构与算法

课程设计名称纸牌游戏
2010年5月

一、问题分析和任务定义

1.题目:

纸牌游戏

2.要求和任务:

① 该题目的要求如下:

(1)将52张牌编号。

(2)从2开始,依次作为基数对基数的倍数的牌进行翻转,直到以52为基数的翻转。

(3)最后输出正面向上的牌。

② 基本任务为:

(1)按照要求翻转纸牌。

(2)输出最后正面向上的纸牌的编号。

3.原始数据的输入及输出格式:

原始数据要求输入纸牌的基础编号,编号的输入为整型。输出的是经过规律翻转后正面向上的纸牌的编号。

输入的数据信息如下:

纸牌:1、2、3……、51、52。

问题直观分析表:

123456789101112……
1
2
3
4
5
6
7
8
9
10
11
12
…………
(注:图中“√”表示翻转一次。)

二.数据结构的选择和概要设计  

1.数据结构

按照题目要求,整个主体包括一个嵌套的循环,外循环控制从2开始每张纸牌都作为基数进行翻牌,内循环控制对所有纸牌进行判断,如果是当前循环中基数的倍数,则对其进行翻转操作。具体代码如下:

for(i=2;i<=52;i++)

    {

        for(j=1;j<=52;j++)

        {

            if(j%i==0)

            data[j-1]=data[j-1]*Flag;

                                    }

    }

2.概要设计

按照题目的要求,首先,应对52张牌进行编号并且保存它们的编号信息,编号的类型为整型,而对于这样固定的数据,使用整型数组是最好的,因此,我们需要在程序的开始定义一共整型的数组,同时,为了方便对翻转过程的记录,在定义记录编号信息的同时,定义一个与之相对应的标记数组,数组类型为整型。该程序的核心为一个嵌套的循环,所以定义两个变量i,j作为循环条件。

接着开始对变量进行初始化,首先是编号信息数组,使用for循环对数组进行1到52的赋值,代表52张纸牌,然后对标记数组赋值,将数组内的所有的值初始化为零,方便在接下来的循环中统计每张牌的翻牌数。数据初始化结束后,开始按照要求对纸牌进行翻转,在嵌套循环中,定义了一个全局变量Flag,值为-1,负数定义为向下,正数定义为向上,这样,翻转一次,即乘以Flag,同时,符合翻转条件时,标记数组相应的编号的纸牌翻牌次数+1。

循环结束后,编号数组中的数据已经更新,因此对数组进行扫描,大于零的即为正面向上的纸牌,输出其编号即可,同时,输出标记数组中的值,显示每张牌的翻牌记录,方便观察或者寻找规律。到此,整个题目结束。

三.详细设计和编码

1.定义全局变量:

作为判断纸牌是否向上的依据,我们需要定义一个全局变量Flag=-1,在循环中对所有纸牌进行操作。

2.主要程序代码与分析如下:

#define Flag -1

(考虑到最后要判断哪些纸牌是正面向上的,所以必须要有一共判断条件,因此定义一个全局变量作为正反面的判断条件。)

void main()

{

int i,j,data[52],flag[52];

char m;

(在程序开始,建立了两个数组,一个存放52张牌的编号,另外一个存放相应编号的纸牌的翻牌记录,便于后面对翻牌次数的输出。)

for(i=1;i<=52;i++)

{

data[i-1]=i;

(通过for循环,向数组中录入1-52个数,作为52张牌的编号,以便进行接下来的操作)

flag[i-1]=0;

(将flag数组中的相应编号纸牌的翻牌数初始化为0,在接下来的循环中,需要对翻牌次数进行统计。)

}

for(i=2;i<=52;i++)

(嵌套循环的外循环,保证基数的循环。)

{

for(j=1;j<=52;j++)

(嵌套循环的内循环,对每张纸牌进行基数的倍数条件判断)

{

if(j%i==0)

{

data[j-1]=data[j-1]*Flag;

flag[j-1]++;

(翻牌一次,则相应的标记数组中该编号的位置数值+1,即将翻牌次数记入flag数组中。)

}

}

}

printf("最后所有正面向上的牌有:");

for(i=0;i<52;i++)

{

if(data[i]>0)

(该题目中将大于零的编号定义为正面向上的纸牌的编号)

printf("第%d张牌  ",i+1);

}

printf("\\n");

}

以上为程序主要代码的分析。

在程序中,主要还包括功能界面,如下:

printf("\-----------------------------------------------------------\\n");    printf("\-----------------------------------------------------------\\n");

    printf("\---------          欢迎进入纸牌游戏             -----------\\n");

    printf("\---------          1.查看题目                   -----------\\n");

    printf("\---------          2.查看所有纸牌的翻牌次数     -----------\\n");

    printf("\---------          3.查看指定编号纸牌翻牌记录   -----------\\n");

    printf("\---------          4.查看最终正面向上的纸牌编号 -----------\\n");

    printf("\---------          5.制作人信息                 -----------\\n");

    printf("\---------          0.按0键结束                 -----------\\n");

    printf("\-----------------------------------------------------------\\n");

    printf("\-----------------------------------------------------------\\n");

同时,整个功能实现由do-while语句和switch语句组合而成,do-while语句可以保证界面最少运行一次,switch语句保证每个功能实现,通过choice的输入来进入不同的功能,同时在每个小的功能内,我都添加了判断是否回到主菜单的语句,如下:

printf("是否回到主菜单?(Y/N):");

        n=getchar();

        n=getchar();

        if(n=='Y')break;

        else if(n=='N')

            choice=0;

        else printf("***************(提示:输入错误,默认为继续。)****** *****\\n");

整个do-while语句的结束条件为:choice=0,所以如果用户输入为N,则直接将0赋值给choice,则符合循环结束的条件,则直接结束程序,如果输入为Y,则break,继续循环,输入错误,没有对choice任何的赋值操作,即不能满足结束条件,则无论输入什么都默认为继续,break后继续循环。由于程序默认的将回车操作通过getchar()赋值给n,导致不能正常的实现下面的判断,而直接显示为输入错误,所以加入两个n=getchar()语句,保证第二句能够正确的实现功能,让用户自行输入条件,进行下一步的操作。在整个程序中,存在着大量的输入判断条件,如下:

if(num<1&&num>52)

                printf("\输入错误!\\n");

这两句代码就是对输入的num值进行判断,由于纸牌序号为1-52,所以不在这个范围的值都为错误值,需要有一个错误信息的反馈,所以需要对输入的信息进行判断,然后通过不同的值对数据进行相应的操作,这对于程序的正确运行,有着至关重要的作用。

四.上机调试过程:

该程序任务相对比较简单,思路较明确。

在一开始编写代码的时候,在嵌套循环中,外循环for的条件(i=2;i<=52;i++),写成(i=1;i<=52;i++),导致对每个纸牌的翻转都多判断了一次,按照一开始定义的大于零的编号数为正面向上的条件,最后输出的结果正好相反,经过修改调试后,问题解决。

在每个case中加入的判断是否回到主菜单的语句,一开始getchar()总是不能正确录入,没有输入就直接运行下一个语句,在加入控制语句后经过调试发现,程序把上一个输入的回车直接默认赋值给getchar(),导致没有输入,直接进行下一个语句,后来使用了两个连续的getchar()语句,第一个getchar()语句默认为回车,但是后面一个getchar()语句可以正确的重新输入判断值,经过重新的调试,运行正常,问题解决,但是希望能找到更完善的答案。在判断是否继续输入纸牌编码的功能中,同样遇到了这个问题,按照相同的解决办法解决。

整个程序由一个大的do-while语句和switch语句组合实现界面的不同功能,do-while语句通过choice=0作为结束的条件,在case 3中,有一个小的do-while语句实现纸牌编号的重复输入,在整个程序中有很多信息的输入,需要根据输入的信息正确与否来反馈信息,否则会导致程序出错,所以在调试的过程中加入了很多判断条件,可以解决信息输入错误的情况,但是仍然存在输入非整型值程序出错的问题,所以在输入条件中加入提示信息,以保证信息类型输入正确。

五.测试结果及其分析

1.测试结果如下图1-12;

2结果分析以注释的形式写在图的下方;

(图1)

(注:MessageBox制作的一个欢迎提示)

(图2)

(注:纸牌游戏程序的主功能界面。)

(图3)

(注:纸牌游戏程序功能1:查看题目。)

(图4)

(注:纸牌游戏程序功能2:查看所有纸牌的翻牌次数。)

(图4续1)

(图4续2)

(图5)

(注:纸牌游戏程序功能3:查看指定编号纸牌翻牌记录。)

(图8)

(注:纸牌游戏程序功能4:查看最终正面向上的纸牌编号。)

(图10)

(注:纸牌游戏程序结束画面。)

(图11)

(注:主界面输入错误提示。)

(图12)

(注:功能3输入错误提示以及判断是否需要继续查询纸牌编码。)

(图13)

(注:回主菜单判断以及输入错误提示。)

(图14)

(注:功能3继续查询纸牌编码判断输入错误提示以及回主菜单输入错误提示。)

六.用户使用说明: 

用户运行程序,按操作提示进行操作。程序运行环境VC++6.0。

七.参考文献:

    [1].王昆仑、李红 《数据结构与算法》 北京:中国铁道出版社

    [2].宁国正 《数据结构(C语言版)》 南京:东南大学出版社

    [3].严尉敏 《数据结构(C语言版)》 北京:清华大学出版社

    [4].吴乃陵 《C++程序设计》 北京:高等教育出版社

附录:

程序源代码:

#include

#include

#define Flag -1//定义一个全局变量作为正反面的判断条件。

void main()

{

    int i,j,data[52],flag[52],choice,num;//建立两个数组,一个存放52张牌的编号,另外一个存放相应编号的纸牌的翻牌记录。

    char m,n;

    MessageBox(NULL,"欢迎进入纸牌游戏程序!//添加了一个MessageBox欢迎对话框

for(i=1;i<=52;i++)

    {

        data[i-1]=i;//录入52张牌的编号。

        flag[i-1]=0;//将相应编号纸牌的翻牌数初始化为0。

    }

    for(i=2;i<=52;i++)//外循环,基数循环。

    {

        for(j=1;j<=52;j++)//内循环,基数倍数条件判断。

        {

            if(j%i==0)

            {

                data[j-1]=data[j-1]*Flag;//将翻转后的结果更新data中的数据。

                flag[j-1]++;//翻牌一次,即记入flag数组中。

            }

        }

    }

    do{

    printf("\-----------------------------------------------------------\\n");    printf("\-----------------------------------------------------------\\n");

    printf("\---------          欢迎进入纸牌游戏             -----------\\n");

    printf("\---------          1.查看题目                   -----------\\n");

    printf("\---------          2.查看所有纸牌的翻牌次数     -----------\\n");

    printf("\---------          3.查看指定编号纸牌翻牌记录   -----------\\n");

    printf("\---------          4.查看最终正面向上的纸牌编号 -----------\\n");

    printf("\---------          5.制作人信息                 -----------\\n");

    printf("\---------          0.按0键结束                 -----------\\n");

    printf("\-----------------------------------------------------------\\n");

    printf("\-----------------------------------------------------------\\n");

    printf("请输入您的选择(数字0-5):");//主界面

    scanf("%d",&choice);

    switch(choice)//通过switch语句进行功能的选择

    {

    case 1:{

        printf("---题目---\\n");

        printf("**************************************************************\\n");

        printf("编号为1-52张牌,正面向上,从第2张开始,以2为基数,是2的倍数的牌翻一次,");

        printf("直到最后一张牌;然后,从第3张开始,以3为基数,是3的倍数的牌翻一次,");

        printf("直到最后一张牌;直到以52为基数的翻过,输出:这时输出正面向上的牌有哪些?\\n");

        printf("****************************************************************");

        printf("\\n");

        printf("\\n");

        printf("是否回到主菜单?(Y/N):");//在每个功能后添加了的判断语句,从而可以选择性的回到主菜单。

        n=getchar();

        n=getchar();

        if(n=='Y')break;

        else if(n=='N')

            choice=0;//0作为整个界面的循环结束条件,所以直接将choice=0,即可结束循环。

        else printf("**********(提示:输入错误,默认为继续。)***********\\n");

           }break;

    case 2:{

        printf("以下为翻牌记录:\\n");

        printf("\----第1张牌翻过0次。----\");

        printf("\\n");

        printf("\\n");

for(i=1;i<52;i++)

    {

        printf("\----第%d张牌翻过%d次。----\",i+1,flag[i]);

        if(i%2==0)

            printf("\\n");

    }

    printf("\\n");

    printf("是否回到主菜单?(Y/N):");

        n=getchar();

        n=getchar();

        if(n=='Y')break;

        else if(n=='N')

            choice=0;

        else printf("**********(提示:输入错误,默认为继续。)*********** **\\n");

           }break;

    case 3:{

        do{

            printf("\请输入您想查询的纸牌编码:");

            scanf("%d",&num);

            if(num<1&&num>52)//纸牌的序号为1-52,所以其他数值都为输入错误。

                printf("\输入错误!\\n");

            else

            {

                printf("\纸牌翻转记录如下:\\n");

                printf("\纸牌翻转次数为%d\\n",flag[num-1]);

                for(j=2;j<=52;j++)//内循环,基数倍数条件判断。

                {

                    if(num%j==0)

                    {

                        printf("\在以编号%d为基数时此纸牌有一次翻转。\\n",j);

                    }

                }

            }

            printf("需要继续查询纸牌编码吗?(Y/N):");//的判断语句,作为do-while的结束条件,从而可循环的查询纸牌编码。

            m=getchar();

            m=getchar();

            if(m!='Y'&&m!='N')

                printf("************(提示:输入错误,默认为跳过。)******** **\\n");

        }while(m=='Y');

        printf("是否回到主菜单?(Y/N):");

        n=getchar();

        n=getchar();

        if(n=='Y')break;

        else if(n=='N')

            choice=0;

        else printf("**************(提示:输入错误,默认为继续。)***** *****\\n");

           }break;

    case 4:{

    printf("\最后所有正面向上的牌有:\\n");

for(i=0;i<52;i++)

    {

        if(data[i]>0)//所有大于0的数即为正面向上的纸牌。

        printf("  第%d张牌  ",i+1);

    }

    printf("\\n");

    printf("是否回到主菜单?(Y/N):");

        n=getchar();

        n=getchar();

        if(n=='Y')break;

        else if(n=='N')

            choice=0;

        else printf("***************(提示:输入错误,默认为继续。)**** ******\\n");

           }break;

    case 5:{

        printf("\\\制作人: \\n");

        printf("\\\班级: \\n");

        printf("\\\指导老师: \\n");

        printf("是否回到主菜单?(Y/N):");

        n=getchar();

        n=getchar();

        if(n=='Y')break;

        else if(n=='N')

            choice=0;

        else printf("***************(提示:输入错误,默认为继续。)****** *****\\n");

           }

    case 0:break;

    default:printf("\输入错误,请重新输入!\\n");

    }

    }while(choice!=0);//0作为整个循环的结束条件。

    printf("*******************程序结束,谢谢使用********************\\n");

    }

    下载本文

显示全文
专题