标题:我写的console下的扫雷,希望大家提点建议
只看楼主
qfyzy
Rank: 2
等 级:论坛游民
威 望:1
帖 子:380
专家分:86
注 册:2008-2-17
结帖率:100%
 问题点数:0 回复次数:22 
我写的console下的扫雷,希望大家提点建议
/*我修正了一个小bug,并改用方向键操作*/
# include <stdio.h>
# include <conio.h>
# include <malloc.h>
# include <stdlib.h>
# include <time.h>

signed char *MineField,*MineShow;  //建立两个动态数组 ,对应雷区图和显示图  
int movex[8] = { -1, 0, 1, 1, 1, 0, -1, -1 }, movey[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };//设定移动方式
int p;                              //雷数记录
long Time;

void Help ( ) {                    //帮助
     system ( "cls" );
     printf (  "\n\n\n\n"
               "\t\t\t本版本修改了2.0中的无法用方向键操作的问题。\n"
               "\t\t\t 按p标记确定的雷,再按p消失。\n"
               "\t\t\t按i表示猜测,猜测无数量限制,标志有数量限制。\n"
               "\t\t\t按回车翻开该方块.\n" );
     system ( "pause" );
}

void initMineField ( int n, int x, int y){   //初始化雷区图
    int TemX, TemY, i;
    p = n;
    MineField = ( signed char * )calloc( (x+2)*(y+2), sizeof( signed char ) );  
    srand ( time( NULL ) );                  
    while ( n >= 1 ) {
       TemX = rand ( ) % x + 1;
       TemY = rand ( ) % y + 1;
       if ( *( MineField + ( x + 2 ) * TemY + TemX ) >= 0 ){
          *( MineField + ( x + 2 ) * TemY + TemX) = -10;
          for( i = 0 ; i<=7 ; i++ ) *( MineField + ( x + 2 ) * ( TemY + movey[i] )+ TemX + movex[i] ) += 1; //将雷的周围显示雷数增加一
          n--;
       }
    }
}

void ShowMap ( int x, int y, int TemX, int TemY ) { //显示图
     int i, j;
     system("cls");
     for ( i = 1 ; i <= y ; i++ ){
        for ( j = 1 ; j <= x ; j++ ){
           if ( i==TemY && j==TemX ) putchar ( 'x' );
           else putchar ( *( MineShow + ( x + 2 ) * i + j ) );
           putchar ( 32 );
        }
        putchar ( 10 );
     }
     printf ( "您的位置在%d,%d\n标记剩余:%d\n" , TemX , TemY , p );
     printf ( "按1进入帮助\n" );
     
}

void initShow ( int x, int y ) {   //初始化显示图
    int i, j;
    MineShow = ( signed char * )malloc( ( x + 2 ) * ( y + 2 ) * sizeof( signed char ) );
    for( i = 1 ; i <= y ; i++ )
       for( j = 1 ; j <= x ; j++ )
          *( MineShow + ( x + 2 ) * i + j )='.';
}

void WhenPress ( int x, int y ) {  //处理按键主程序
     int TemX = 1, TemY = 1, state = 0;
     char c;
     int ShowOne ( int, int, int, int );
     ShowMap ( x, y, TemX, TemY );
     Time = clock ( );
     while ( 1 ) {
       c = getch ( );
       if ( c == -32 || !c ) c = getch ( );
       switch ( c ) {                        //按键处理
            case 72:if ( TemY >= 2 ) TemY--;
                     else TemY = y;
                     break;
          case 75:if ( TemX >= 2 ) TemX--;
                     else TemX = x;
                     break;
          case 80:if ( TemY <= y-1 ) TemY++;
                     else TemY = 1;
                     break;
          case 77:if ( TemX <= x-1 ) TemX++;
                     else TemX = 1;
                     break;                       
          case 'p':if ( *( MineShow + ( x + 2 ) * TemY + TemX ) == '.' ) {   //标记
                         if ( p >= 1 ) {
                                   *( MineShow + ( x + 2 ) * TemY + TemX ) = 'p';
                              p--;
                       }
                       else printf ( "标记用完!\a\n" );
                   }
                   else if ( *( MineShow + ( x + 2 ) * TemY + TemX ) == 'p' ){  
                              *( MineShow + ( x + 2 ) * TemY + TemX )= '.';
                              p++;
                        }
                   else {
                           putchar('\a');
                           continue;
                   }
                   break;
         case 'i':if( *( MineShow + ( x + 2 ) * TemY + TemX ) == '.' || *( MineShow + ( x + 2 ) * TemY + TemX ) == 'p' ){  //标记猜测
                        if ( *( MineShow + ( x + 2 ) * TemY + TemX ) == 'p' ) p++;
                        *( MineShow + ( x + 2 ) * TemY + TemX ) = '?';
                   }
                   else if ( *( MineShow + ( x + 2 ) * TemY + TemX ) == '?' ) *( MineShow + ( x + 2 ) * TemY + TemX ) = '.';
                   else putchar('\a');
                   continue;
          case 13:if ( *( MineShow + ( x + 2 ) * TemY + TemX ) == '.') state = PressOne ( x, y, TemX, TemY );  //打开
                  else {
                         putchar('\a');
                         continue;
                  }
                  break;
          case 'q':printf ( "真的要退出么?(y/n)\n" );  //退出
                   if( getch ( ) == 'y' ) return;
          case '1':Help ( );
                   break;
          default:putchar('\a');
                  continue;
       }
       ShowMap( x, y, TemX, TemY);
       if( state == 1 ) {         //胜利
          puts ( "您胜利了\n" );
          printf ( "用时:%.2lfs\n" , ( clock ( ) - Time ) / 1000.0 );
          system ( "pause" );
          return;
       }
       else if( state == 2 ){    //失败
             puts ( "您输了\n" );
             printf ( "用时:%.2lfs\n" , ( clock ( ) - Time ) / 1000.0 );
             system ( "pause" );
             return;
       }
     }
}

int PressOne ( int x, int y, int TemX, int TemY ) {
    int i, j;
    int Win ( int, int );
    void ShowBlankAll ( int, int, int, int );
    if( *( MineField + ( x + 2 ) * TemY + TemX ) < 0 ) {
        for (  i = 1 ; i <= y ; i++ )
           for ( j = 1 ; j <= x ; j++ )
              if( *( MineField + ( x + 2 ) * i + j ) < 0 )
              *( MineShow + ( x + 2 ) * i + j ) = '*';
        return 2;
    }
    if( *( MineField + ( x + 2 ) * TemY + TemX ) > 0 ) *( MineShow + ( x + 2 ) * TemY + TemX ) = '0' + *( MineField + ( x + 2 ) * TemY + TemX );
    else ShowBlankAll ( x, y, TemX, TemY );
    if( Win ( x, y ) ) return 1;
    else return 0;
}

void ShowBlankAll ( int x, int y, int TemX, int TemY ) {
     int i ;
     if ( TemX  >= x + 1  ||  TemX <= 0 || TemY  <= 0 || TemY  >= y + 1 ) return;
     if ( *( MineShow + ( x + 2 ) * TemY + TemX ) != '.' ) return;
     if ( ( *( MineShow + ( x + 2 ) * TemY + TemX ) = *( MineField + ( x + 2 ) * TemY + TemX ) + '0' ) != '0' ) return;
     for ( i = 0 ; i <= 7 ; i++ ) ShowBlankAll( x , y , TemX + movex[i], TemY + movey[i] );
    
}

int Win ( int x, int y ) {
    int i, j;
    for ( i = 1 ; i <= y ; i++ )
       for ( j = 1 ; j <= x ; j++ )
          if ( *( MineField + ( x + 2 ) * i + j ) >= 0 && *( MineField + ( x + 2 ) * i + j ) != ( *( MineShow + ( x + 2 ) * i + j ) - '0') ) return 0;
    return 1;
}

void ShowFile ( int c ) {
     system ( "cls" );
     printf ( "\n\n\n\t\t\t\t=============\n"
              "\t\t\t\t|%c  简  单  |\n"
              "\t\t\t\t|%c  普  通  |\n"
              "\t\t\t\t|%c  困  难  |\n"
              "\t\t\t\t|%c  自定义  |\n"
              "\t\t\t\t|%c  帮  助  |\n"
              "\t\t\t\t|%c  退  出  |\n"
              "\t\t\t\t=============\n",
              c == 0 ? 'O' : ' ' ,
              c == 1 ? 'O' : ' ' ,
              c == 2 ? 'O' : ' ' ,
              c == 3 ? 'O' : ' ' ,
              c == 4 ? 'O' : ' ' ,
              c == 5 ? 'O' : ' ' );
}

void Files ( ) {
    int n, x, y , t = 0;
    char c;
    while ( 1 ){
       ShowFile ( t );      
       c = getch ( );
       if ( c == -32 || !c ) {
                 c = getch ( );
            switch ( c ) {
                 case 72:if ( t >= 1 ) t--;
                         else t = 5;
                         continue;
                case 80:if ( t <= 4 ) t++;
                         else t = 0;
                         continue;
                default:printf ( "\n无效选项\a\n" );
                       continue;
            }
       }
       if ( c == 13 ) {
                 switch (t){
            case 0:x = y = 9;
                   n = 10;
                   break;
            case 1:x = y = 16;
                   n = 40;
                   break;
            case 2:x = 30;
                   y = 16;
                   n = 99;
                   break;
            case 3:printf ( "\n请输入雷数,长(<=35),宽(<=20):" );
                   while ( scanf( "%d%d%d" , &n, &x, &y ) != 3 ){
                            while ( getchar () != '\n' );
                      printf ( "输入有错,请重新输入: ");
                   }
                   if ( n >= x * y ) {
                         printf ( "雷数过多\n" );
                         system ( "pause" );
                         continue;
                   }
                   else if ( n <= 1 ) {
                           printf ( "雷数过少!\n");
                        system ( "pause" );
                        continue;
                   }
                   if ( x >= 36 || x <= 0 || y >= 21 || y <= 0 ) {
                            printf ( "长宽数据有错。\n" );
                            system ( "pause" );
                       continue;
                       }
                    break;
            case 4:Help ( );
                   continue;
            case 5:exit(0);
            }             
            initMineField ( n, x, y );
            initShow ( x, y );
            WhenPress( x, y );
            return;
       }
       else printf ( "\n无效选项\a\n" );
    }
}

void FirstShow ( ) {
     printf ( "\n\n\n\n\t\t\t=====================================\n"
             "\t\t\t|欢迎进入扫雷console版3.0(fmk制作)|\n"
             "\t\t\t|本版本修正了2。0中的无法用方向     |\n"
             "\t\t\t|键操作的问题,回车确定。           |\n"  
             "\t\t\t=====================================\n\t\t\t" );
    system ( "pause" );
}

int main ( ) {
    FirstShow ( );
    while ( 1 ) {
           Files ( );
           free( MineField );
           free( MineShow );
           printf ( "想继续么?(y/n)" );
           if ( getch ( ) != 'y' ) break;
       }
    return 0;
}

[[it] 本帖最后由 qfyzy 于 2008-2-23 17:56 编辑 [/it]]
收到的鲜花
  • cosdos2008-02-18 22:47 送鲜花  4朵   附言:很不错。
  • 永夜的极光2008-02-20 13:09 送鲜花  8朵  
  • cosdos2008-02-20 18:13 送鲜花  1朵   附言:再加一个
搜索更多相关主题的帖子: console 提点 扫雷 
2008-02-17 21:41
sunkaidong
Rank: 4
来 自:南京师范大学
等 级:贵宾
威 望:12
帖 子:4496
专家分:141
注 册:2006-12-28
得分:0 
帮你顶一下
2008-02-17 21:46
qfyzy
Rank: 2
等 级:论坛游民
威 望:1
帖 子:380
专家分:86
注 册:2008-2-17
得分:0 
谢谢二楼了
2008-02-17 21:46
阿牧
Rank: 1
等 级:新手上路
威 望:1
帖 子:138
专家分:0
注 册:2007-11-5
得分:0 
很厉害,我是初学者,能写出这个就很满意了。
加点图形进去,用windows方式玩更好。
2008-02-17 21:49
sunkaidong
Rank: 4
来 自:南京师范大学
等 级:贵宾
威 望:12
帖 子:4496
专家分:141
注 册:2006-12-28
得分:0 
看了一下,风格相当不错.....呵呵
2008-02-17 22:07
xianshizhe111
Rank: 1
等 级:新手上路
帖 子:1451
专家分:0
注 册:2007-12-8
得分:0 
支持一下.
2008-02-17 22:30
link1130
Rank: 1
等 级:新手上路
帖 子:44
专家分:0
注 册:2006-10-29
得分:0 
为什么 执行到
case 'k':if ( *( MineShow + ( x + 2 ) * TemY + TemX ) == '.') state = PressOne ( x, y, TemX, TemY );  //打开

这句 就下不去了[bc10]

2008-02-18 09:44
sunkaidong
Rank: 4
来 自:南京师范大学
等 级:贵宾
威 望:12
帖 子:4496
专家分:141
注 册:2006-12-28
得分:0 
可以执行啊..
2008-02-18 10:36
xianshizhe111
Rank: 1
等 级:新手上路
帖 子:1451
专家分:0
注 册:2007-12-8
得分:0 
确实可以运行 DEV-CPP VC++ 6.0
运行都正常确实不错.
2008-02-18 12:46
cosdos
Rank: 9Rank: 9Rank: 9
来 自:ShangHai
等 级:蜘蛛侠
威 望:6
帖 子:2109
专家分:1385
注 册:2007-6-19
得分:0 
帮你顶一下

—>〉Sun〈<—
2008-02-18 22:47



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-200193-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.144674 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved