我写的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]]