分享

C语言猜拳游戏代码及分析

 共同成长888 2015-07-19

C语言猜拳游戏代码及分析 

猜拳游戏需求分析说明书

1.引言

1.编写目的

小时候,我们喜欢以猜拳来赢得奖励。

现在,我们希望能开发一个猜拳的游戏。

2.定义

需求:用户解决问题或达到目标所需的条件或功能;系统或系统部件要满足合同、标准,规范或其它正式规定文档所需具有的条件或权能。而且其很强的交互性及简单易行性,可以让人在很短时间内熟悉它的操作方法,不论用户文化水平如何,都会很轻松的学会使用它。

2.任务概述

1.目标

2.用户的特点

由于本程序简单易操作,交互性好,对用户没什么特别要求。一般用户经过几分钟练系都可以熟悉本系统的规则。

 

3.系统功能示例

 

3.需求细则

1.    对功能的规定

1.1       界面友好

属性:必选

描述:用户的一些操作前后做出一些必要的提示或确认。所有完成的功能都需要友好,例如:

   增加失败提示

   删除失败和成功提示、删除前的确认;

   修改失败和成功提示、修改前/后的确认;

   查找失败提示、查找成功的确认;

   退出系统时,要提示是否退出;

   其它方面的界面问题;

 

1.2       用户注册

属性:必选

描述:登录界面可以用户注册,注册信息包含用户名和密码,例如:

      不能使用已经存在的用户名

      密码不能少于6个字符

1.3       用户登录

属性:必选

描述:用户通过登录界面进行登录,必须输入正确的用户名和密码方可进入系统,例如:

      提示输入用户名

      提示输入密码

      用户名和密码验证,都符合则进入系统,不然回到第一步,超过三次登录,则提示登录次数超过三次,退出系统

 

1.4       开始游戏

属性:必选

描述:金额大于1的用户可以开始游戏

      下注:提示用户下注的金额数

      猜拳:(必须先下注,如果用户下注金额小于等于0,不能进行游戏)与电脑进行猜拳游戏,如果猜输了,扣除你的金额(由下注决定),胜利将随机获得1~5倍的下注金额奖励

n提示:电脑随机出拳,胜利奖励也是随机的,例如:

n随机获得1~5数字代码:

nsrand((unsigned)time(NULL));

nint radio = rand() % 5 + 1;//radio 为随机 1~5的整数

      如果金额少于下注数,将不能进行猜拳,給出充值提示

1.5       充值

属性:必选

描述:用户可以进行充值

      充值金额

      充值的时候,必须输入充值密码(由5个字符组成,随机包括数字0~9和所有小写字母)

      如果充值密码正确,充值成功,不然充值失败

1.6       修改用户信息

属性:必选

描述:用户可以注销(删除)自己的账户、或者修改个人信息

  修改个人信息

n   修改用户密码

  注销用户(本人)

n   删除用户所有信息(删除完毕将返回登录界面,用户账号已经不存在)

1.7       查看用户信息

 

属性:必选

描述:用户登录成功后,可以选择查看用户自己信息或者所有用户信息

 

  查看用户自己信息:(本人)用户名 密码 金额 胜率

  查看所有用户信息:所有用户名 金额 胜率

 

1.8       排序

属性:必选

描述:用户可以对所有用户信息进行排序操作,便于查看

  金额排序

  胜率排序

 

对性能的规定

 

 本系统在设计方面本着方便、实用的宗旨,性能方面应遵循如下原则:

                     执行效率(时间): 软件运行应该尽量高效;避免没有必要的循环处理、重复处理;

                     资源损耗(空间):设计尽量节约资源(内存、数组、链表等);不用的资源要及时释放;

                     初始化: 变量、数组、内存块;

                     健壮性:不能出现野指针、内存泄露、数组越界访问等等:

    声明指针后,立即将指针设置为NULL,防止产生野指针

    函数的入参必须进行有效性判断;用户输入、函数返回值(如果用到的话)都要判断;

    switch-case一定要有defaultif-else if等后要有else,除非if满足后返回或退出;

    不允许出现goto语句;

    数组的下标不要溢出。

 

3.    对排版的规定

 

                     缩进要对齐

                     长行拆分;

                     二元操作符的前后应当加空格,包括如下操作符:

 

赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如"=""+="">=""<=""+""*""%""&&""||""<<","^" 等;

 

                     空行:

 

    声明之后、每个函数定义结束之后都要加1行空行;

    逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔;

    一行代码只做一件事情;

    "if""for""while""do"等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加 "{ }"

 

4.    对可维护性的规定

 

    对可维护性的最终要求:别人能够轻松上手你的代码。

                     结构清晰:

 

    模块化:对界面(显示)、菜单管理、逻辑管理、文件操作等等代码要独立,必须多个.c文件,用makefile

    封装:一个函数只做一件事,函数功能要单一;一个函数不能超过50行;

避免重复、冗余代码;

    代码块清晰。

                     命名规范,变量名应该具有自明性:

    函数的命名:

使用"动词"或者"动词+名词"(动宾词组)的形式,由一个或多个单词组成且以小写字母开头,以后每个单词之间用下划线隔开

    变量的命名与定义

应当使用"名词"或者"形容词+名词",由一个或多个单词组成且以小写字母开头,以后每个单词之间用下划线隔开。

 

                     注释充分:变量、函数(包括参数、返回值)、代码功能块、一些复杂算法……等都需要

 

清晰明了地说明;

 

5.    对个性的规定

 

把项目做出个性出来。下列各项中有和比人不同之处、或很有创意,即可认为有个性。独立设计的软件,一般都会出现一些个性。参考、抄袭不会出现个性。   

 

                     设计思路:包括软件的整体架构、功能块的设计思路、函数封装等等;

                     功能实现:从用户的角度,使用上发现与众不同的地方;

                     其它方面;

 

c语言程序代码:

/*
func:猜拳游戏
auth:肖乔
date:2014.02.22
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define TRUE 1
typedef struct {
       charname[30];       //用户名长度最长28
       charpassword[30];   //密码长度最长28
       doublemoney;
       inttimes;
       intwin;
}game_t;
//清空缓存
void fflush_in();
//登录菜单函数
void log_menu();
//功能菜单函数
void ctrl_menu();
//登录函数
int log_in(game_t *p,int *count,int *my);
//注册函数
int add_user(game_t *p,int *count);
//登录控制函数
void log_ctrl(game_t *p,int *count,int*my);
//功能控制函数
void ctrl(game_t *p,int *count,int *my);
//查看函数
void look(game_t *p,int *count,int *my);
//查看菜单
void look_menu();
//查看所有
void look_all(game_t *p,int *count);
//查看个人
void look_my(game_t *p,int *my);
//初始化函数
int log_start(game_t *p,int *count);
//保存函数
int exit_save(game_t *p,int *count);
//充值函数
int pay(game_t *p,int *my);
//修改函数
void alter(game_t *p,int *count,int *my);
//修改菜单
void alter_menu();
//修改密码
int alter_pass(game_t *p,int *my);
//注销用户
int del(game_t *p,int *count,int *my);
//游戏控制函数
void game_ctrl(game_t *p,int *my);
//游戏菜单
void game_menu();
//下注
int game_pay(game_t *p,int *my,double*mon);
//游戏函数
void game_play(game_t *p,int *my,double*mon);
//游戏
int game();
//排序控制函数
void cmp(game_t *p,int *count);
//排序菜单
void cmp_menu();
//按金额排序函数
int cmp_money(const void *px,const void*py);
//胜率函数
void win_times(game_t *p,int *count);
//按胜率排序函数
int cmp_win(const void *px,const void *py);
 
 
int main(){
       game_tstu[100]={"\0"}; //最多100个用户
       intcount=0;            //count表示用户数
       intmy=0;               //my表示本人用户下标
 
       printf("欢迎使用猜拳游戏\n");
       if(log_start(stu,&count)==0)                             //系统初始化
              printf("系统初始化成功\n");
       else
              printf("系统初始化失败\n");
       log_ctrl(stu,&count,&my);    //功能控制函数
 
       return0;
}
//初始化函数 0-成功1-失败
int log_start(game_t *p,int *count){
       FILE*fp=NULL;
 
       fp=fopen("data","a+");
       if(NULL==fp)
              return1;
       while(fread(&p[*count],sizeof(game_t),1,fp))
              *count+=1;
       fclose(fp);
      
       return0;
}
//保存函数 0-成功 1-失败
int exit_save(game_t *p,int *count){
       FILE*fp=NULL;
 
       fp=fopen("data","w");
       if(NULL==fp)
              return1;;
       fwrite(p,sizeof(game_t),*count,fp);
       fclose(fp);
       return0;
}
 
//功能控制函数
void ctrl(game_t *p,int *count,int *my){
       intchose=0;
 
       while(TRUE){
              chose=0;
              ctrl_menu();
              printf("请选择:");
              scanf("%d",&chose);
              fflush_in();
              switch(chose){
                     case1:          //查看
                            look(p,count,my);
                            break;
                     case2:          //游戏
                            game_ctrl(p,my);
                            break;
                     case3:          //充值
                            if(pay(p,my)==0)
                                   printf("充值成功\n");
                            else
                                   printf("充值失败\n");
                            break;
                     case4:          //修改
                            alter(p,count,my);
                            break;
                     case5:          //排序
                            cmp(p,count);
                            break;
                     case6:          //返回
                            return;
                            break;
                     default:
                            printf("输入错误,请重新输入\n");
              }
       }
}
//排序控制函数
void cmp(game_t *p,int *count){
       intchose=0;
 
       while(TRUE){
              chose=0;
              cmp_menu();
              printf("请选择:");
              scanf("%d",&chose);
              fflush_in();
              switch(chose){
                     case1:            //金额
                            qsort(p,*count,sizeof(game_t),cmp_money);      
                            printf("排序成功\n");
                            break;
                     case2:            //胜率
                            win_times(p,count);
                                   printf("排序成功\n");
                            break;
                     case3:            //返回
                            return;
                            break;
                     default:
                            printf("输入错误,请重新输入\n");
              }
       }
}
//胜率函数
void win_times(game_t *p,int *count){
       doublewins[100]={0.0};
       doublei=0,j=0;
       intk=0;
      
       for(k=0;k<*count;k++){
              i=p[k].times;
              j=p[k].win;
              wins[k]=(i=0?0:(double)j/i*100);
       }
              qsort(wins,*count,sizeof(game_t),cmp_win);
}
//按胜率排序函数
int cmp_win(const void *px,const void *py){
       constgame_t *p1=px;
       constgame_t *p2=py;
 
       if(p1->money>p2->money)
              return-1;
       if(p1->money<p2->money)
              return1;
       else
              return0;
}
//按金额排序函数
int cmp_money(const void *px,const void*py){
       constgame_t *p1=px;
       constgame_t *p2=py;
 
       if(p1->money>p2->money)
              return-1;
       if(p1->money<p2->money)
              return1;
       else
              return0;
}
//排序菜单
void cmp_menu(){
       printf("1.按金额排序 2.按胜率排序 3.返回\n");
}
//游戏控制函数
void game_ctrl(game_t *p,int *my){
       intchose=0;
       doublemon=0.0;
 
       while(TRUE){
              chose=0;
              game_menu();
              printf("请选择:");
              scanf("%d",&chose);
              fflush_in();
              switch(chose){
                     case1:          //下注
                            if(game_pay(p,my,&mon)==0)
                                   printf("下注成功,请开始游戏\n");
                            else
                                   printf("下注失败\n");
                            break;
                     case2:          //猜拳
                            game_play(p,my,&mon);     
                            break;
                     case3:          //返回
                            return;
                            break;
                     default:
                            printf("输入错误,请重新输入\n");
              }
       }
}
//游戏函数
void game_play(game_t *p,int *my,double*mon){
       intresult=0;
       intradio=0;
 
       if(*mon==0){
              printf("请先下注\n");
              return;
       }
       p[*my].money-=*mon;
       result=game();
       srand((unsigned)time(NULL));
       radio=rand()%5+1;
       if(result==0){
              p[*my].money+=0;
              printf("平局,余额%.2f\n",p[*my].money);
              p[*my].times+=1;
       }
       elseif(result==1){
              p[*my].money+=(*mon)*radio;
              printf("您胜利了,奖金:%.2f余额:%.2f\n",(*mon)*radio,p[*my].money);
              p[*my].times+=1;
              p[*my].win+=1;
       }
       else{
              printf("您输了%.2lf,余额%.2lf\n",*mon,p[*my].money);
              p[*my].times+=1;
       }
       *mon=0.0;
}
//游戏 0-平局,1-胜,-1-输
int game(){
       intmy=0;
       intradio=0;
       while(my!=1&&my!=2&&my!=3){
              printf("1.剪刀 2.石头 3.布\n");
              printf("请选择:");
              scanf("%d",&my);
              fflush_in();
              switch(my){
                     case1:
                            printf("您出的是剪刀\n");
                            break;
                     case2:
                            printf("您出的是石头\n");
                            break;
                     case3:
                            printf("您出的是布\n");
                            break;
                     default:
                            printf("输入错误,请重新输入\n");
              }
       }
       srand((unsigned)time(NULL));
       radio=rand()%3+1;
       if(radio==1)
              printf("电脑出的是剪刀\n");
       elseif(radio==2)
              printf("电脑出的是石头\n");
       elseif(radio==3)
              printf("电脑出的是布\n");
       switch(radio-my)
       {
              case1:
              case-2:
                     return-1;
              case2:
              case-1:
                     return1;
              default:
                     return0;
       }
}
//下注 0-成功 1-失败
int game_pay(game_t *p,int *my,double*mon){
       doublemoney=0.0;
      
       if(p[*my].money==0){
              printf("您的余额为0.00,请充值\n");
              return1;
       }
       printf("您的余额为:%.2lf元\n",p[*my].money);
       printf("请下注:");
       scanf("%lf",&money);
       fflush_in();
       if(money<=0){
              printf("金额输入有误\n");
              return1;
       }
       if(money>p[*my].money){
              printf("余额不足,请充值\n");
              return1;
       }
       *mon=money;
       return0;
}
//游戏菜单
void game_menu(){
       printf("1.下注 2.猜拳 3.返回\n");
}
//修改函数 0-成功 1-失败
void alter(game_t *p,int *count,int *my){
       intchose=0;
 
       while(TRUE){
              chose=0;
              alter_menu();
              printf("请选择:");
              scanf("%d",&chose);
              fflush_in();
              switch(chose){
                     case1:          //改密
                            if(alter_pass(p,my)==0)
                                   printf("修改密码成功\n");
                            else
                                   printf("修改密码失败\n");
                            break;
                     case2:          //注销
                            if(del(p,count,my)==0){
                                   printf("注销成功\n");
                                   log_ctrl(p,count,my);     //功能控制函数
                            }
                            else
                                   printf("注销失败\n");
                            break;
                     case3:          //返回
                            return;
                            break;
                     default:
                            printf("输入错误,请重新输入\n");
              }
       }
}
//注销用户 0-成功 1-失败
int del(game_t *p,int *count,int *my){
       charpass[30]="\0";
       inti=0,chose=0;
 
       printf("密码:");
       fgets(pass,30,stdin);
       pass[strlen(pass)-1]='\0';
       if(!(strcmp(p[*my].password,pass))==0){
              printf("密码输入错误\n");
              return1;
       }
       printf("是否注销?\n1.是 2.否\n");
       printf("请选择:");
       scanf("%d",&chose);
       fflush_in();
       if(chose==1){
              for(i=*my;i<*count-1;i++){
                     strcpy(p[i].name,p[i+1].name);
                     strcpy(p[i].password,p[i+1].password);
                     p[i].money=p[i+1].money;
                     p[i].times=p[i+1].times;
                     p[i].win=p[i+1].win;
              }
       }
       else
              return1;
       *count-=1;
       return0;
}
//修改密码 0-成功 1-失败
int alter_pass(game_t *p,int *my){
       charpass[30]="\0",pass2[30]="\0";
       intchose=0;
 
       printf("密码:");
       fgets(pass,30,stdin);
       pass[strlen(pass)-1]='\0';
       if(!(strcmp(p[*my].password,pass))==0){
              printf("密码输入错误\n");
              return1;
       }
       printf("提示:密码长度为6-28位\n");
       printf("输入新密码:");
       fgets(pass,30,stdin);
       pass[strlen(pass)-1]='\0';
       printf("确认新密码:");
       fgets(pass2,30,stdin);
       pass2[strlen(pass2)-1]='\0';
       if(strcmp(pass,pass2)!=0){
              printf("两次输入密码不一样\n");
              return1;
       }
       if(strcmp(p[*my].password,pass)==0){
              printf("新密码与原密码相同\n");
              return1;
              }
       printf("是否改密?\n1.是 2.否\n");
       printf("请选择:");
       scanf("%d",&chose);
       fflush_in();
       if(chose==1)
              strcpy(p[*my].password,pass);
       else
              return1;
       return0;
}
//修改函数菜单
void alter_menu(){
       printf("1.修改密码 2.注销 3.返回\n");
}
//充值函数
int pay(game_t *p,int *my){
       inti=0;
       doublemoney=0;
       charpass[30]="\0";
       charstr[10]="\0",str2[10]="\0";
      
       printf("请输入金额:");
       scanf("%lf",&money);
       fflush_in();
       if(money<=0.0)
              return1;
      
       //验证码
       for(i=0;i<5;i++){
              srand((unsigned)time(NULL)+i); 
              str[i]="0123456789abcdefghihklmnopqrstuvwxyz"[rand()%36];
       }
       printf("充值密码:%s",str);
       printf("\n");
       printf("请输入充值密码:");
       fgets(str2,10,stdin);
       str2[strlen(str2)-1]='\0';
       if(strcmp(str,str2)!=0){
              printf("充值密码输入错误\n");
              return1;
       }
      
       printf("密码:");
       fgets(pass,30,stdin);
       pass[strlen(pass)-1]='\0';
       if(!(strcmp(p[*my].password,pass))==0)
              return1;
       p[*my].money+=money;
      
       return0;
}
//查看函数
void look(game_t *p,int *count,int *my){
       intchose=0;
 
       while(TRUE){
              chose=0;
              look_menu();
              printf("请选择:");
              scanf("%d",&chose);
              fflush_in();
              switch(chose){
                     case1:       //个人
                            look_my(p,my);
                            break;
                     case2:       //所有
                            look_all(p,count);
                            break;
                     case3:       //返回
                            return;
                            break;
                     default:
                            printf("输入错误,请重新输入\n");
              }
       }
}
//查看所有
void look_all(game_t *p,int *count){
       inti=0;     //i表示游戏次数
       intj=0;     //j表示胜利次数
       intk=0;
      
       printf("用户\t金额\t胜率\t\n");  
       for(k=0;k<*count;k++){
              i=p[k].times;
              j=p[k].win;
              printf("%s\t%.2f\t%.2lf%%\t\n",p[k].name,
                     p[k].money,i==0?0:(double)j/i*100);
       }
}
//查看个人
void look_my(game_t *p,int *my){
       inti=0;     //i表示游戏次数
       intj=0;     //j表示胜利次数
 
       i=p[*my].times;
       j=p[*my].win;
       printf("用户名:%s\n",p[*my].name);
       printf("密 码:%s\n",p[*my].password);
       printf("金 额:%.2lf\n",p[*my].money);
       printf("胜 率:%.2lf%%\n",i==0?0:(double)j/i*100);
}
//查看菜单
void look_menu(){
       printf("1.个人 2.所有 3.返回\n");
}
//功能菜单函数
void ctrl_menu(){
       printf("1.查看 2.游戏 3.充值 4.修改 5.排序 6.返回\n");
}
//登录控制函数
void log_ctrl(game_t *p,int *count,int*my){
       intchose=0,chose2=0;
 
       while(TRUE){
              chose=0;
              chose2=0;
              log_menu();
              printf("请选择:");
              scanf("%d",&chose);
              fflush_in();
              switch(chose){
                     case1:           //登录
                            if(log_in(p,count,my)==1)
                                   printf("登录失败\n");                 
                            else{
                                   printf("登录成功\n");
                                   ctrl(p,count,my);
                            }
                            break;
                     case2:           //注册
                            if(add_user(p,count)==1)
                                   printf("注册失败\n");
                            else
                                   printf("恭喜您,注册成功\n");
                            break;
                     case3:           //退出
                            printf("是否退出?\n1.是 2.否\n");
                            printf("请选择:");
                            scanf("%d",&chose2);
                            fflush_in();
                            if(chose2==1){
                                   if(exit_save(p,count)==0)
                                          printf("信息保存成功\n");
                                   else
                                          printf("信息保存失败\n");
                                   exit(0);
                            }
                            else
                                   log_ctrl(p,count,my);
                            break;
                     default:
                            printf("输入错误,请重新输入\n");
              }
       }
}
//登录函数 0-成功 1-失败
int log_in(game_t *p,int *count,int *my){
       inti=0,flag=0;
       charname[30]="\0",pass[30]="\0";
      
       printf("用户名:");
       fgets(name,30,stdin);
       name[strlen(name)-1]='\0';
       flag=0;
       for(i=0;i<*count;i++)
              if(strcmp(p[i].name,name)==0){
                     *my=i;
                     flag=1;
                     break;
              }
       if(flag==0){
              printf("用户不存在\n");
              return1;
       }
      
       i=0;
       while(i<3){
              printf("密码:");
              fgets(pass,30,stdin);
              pass[strlen(pass)-1]='\0';
              if(strcmp(p[*my].password,pass)==0){
                     return0;
              }
              printf("密码输入错误,请重新输入\n");
              i++;
       }
       if(i==3){
              printf("登录失败\n");
              printf("登录次数超过三次,您将退出系统\n");
              if(exit_save(p,count)==0)  //保存信息
                     printf("信息保存成功\n");
              else
                     printf("信息保存失败\n");
              exit(1);
       }
 
       return0;
}
//注册函数 0-成功 1-失败
int add_user(game_t *p,int *count){
       inti=0;
       charname[30]="\0";
       charpass[30]="\0",pass2[30]="\0";
 
       if(*count>100){
              printf("注册用户已满\n");
              return1;
       }
       printf("提示:用户名长度为3-28\n");
       printf("用户名:");
       fgets(name,30,stdin);
       name[strlen(name)-1]='\0';
       if(strlen(name)<3||strlen(name)>28){          //用户名长度3-28
              printf("用户名长度不合法\n");
              return1;
              }
       for(i=0;i<*count;i++){
              if(strcmp(p[i].name,name)==0){
              printf("已有同名用户名\n");
              return1;
              }
       }
       strcpy(p[*count].name,name);
      
       printf("提示:密码长度6-28\n");
       printf("密码:");
       fgets(pass,30,stdin);
       pass[strlen(pass)-1]='\0';
       if(strlen(pass)<6||
              strlen(pass)>28){   //密码长度6-28
              printf("密码长度不合法\n");
              return1;
              }
       printf("确认密码:");
       fgets(pass2,30,stdin);
       pass2[strlen(pass2)-1]='\0';
       if(!(strcmp(pass,pass2))==0){
              printf("两次输入密码不一样\n");
              return1;
       }
 
       strcpy(p[*count].password,pass);
       *count+=1;
 
       return0;
}
//登录菜单函数
void log_menu(){
       printf("1.登录 2.注册 3.退出\n");
}
//清空缓存
void fflush_in(){
       charc='\0';
 
       c=getchar();
       while(c!='\n'){
              c=getchar();
       }
}
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多