一:问题描述
用C语言实现9*9扫雷小游戏
二:游戏逻辑分析流程
1.菜单界面选择开始或者退出游戏。 2.创建两个数组来存放布置雷的信息和排查出雷的信息。 3.初始化两个棋盘。 4.布置雷。 5.打印棋盘,让棋盘可视化。 6.玩家排雷,并判断排雷是否成功。
三:代码模块
3.1菜单实现
void menu ( )
{
printf ( "*************************\n" ) ;
printf ( "*********1.play**********\n" ) ;
printf ( "*********0.eixt**********\n" ) ;
printf ( "*************************\n" ) ;
}
3.2创建棋盘
棋盘:使用11行11列二维数组mine和show来表示,元素类型是char类型;玩家界面是9行9列的格子,使用11行11列的二维数组是避免排查雷时出现越界问题。
使用宏定义: (1)提高代码的可读性,方便理解含义 (2)提高项目的扩展性,方便未来修改棋盘尺寸
# define ROW 9
# define COL 9
# define ROWS ROW+ 2
# define COLS COL+ 2
char mine[ ROWS] [ COLS] = { 0 } ;
char show[ ROWS] [ COLS] = { 0 } ;
3.3棋盘初始化
注意这里传递了参数set,可以通过函数Init_board一次性实现mine数组和show数组的初始化。
Init_board ( mine, ROWS, COLS, '0' ) ;
Init_board ( show, ROWS, COLS, '#' ) ;
void Init_board ( char arr[ ROWS] [ COLS] , int rows, int cols, char set)
{
int i, j = 0 ;
for ( i = 0 ; i < rows; i++ )
{
for ( j = 0 ; j < cols; j++ )
{
arr[ i] [ j] = set;
}
}
}
3.4在mine数组中布置雷
# define EASY_COUNT 10
void Set_mine ( char mine[ ROWS] [ COLS] , int row, int col)
{
int x, y = 0 ;
int count = EASY_COUNT;
while ( count)
{
x = rand ( ) % row + 1 ;
y = rand ( ) % col + 1 ;
if ( mine[ x] [ y] == '0' )
{
mine[ x] [ y] = '1' ;
count-- ;
}
}
}
3.5打印棋盘
void Show_board ( char arr[ ROWS] [ COLS] , int row, int col)
{
int i = 0 , j = 0 ;
printf ( "-----------扫雷-----------\n" ) ;
for ( i = 0 ; i <= col; i++ )
{
printf ( "%d " , i) ;
}
printf ( "\n" ) ;
for ( i = 1 ; i <= row; i++ )
{
printf ( "%d " , i) ;
for ( j = 1 ; j <= col; j++ )
{
printf ( "%c " , arr[ i] [ j] ) ;
}
printf ( "\n" ) ;
}
}
3.6玩家排查雷
注意Find_mine函数接收了mine数组和show数组,mine数组用来判断玩家输入的坐标位置是否有雷,show数组用来显示排查出的雷的信息。
int get_mine_count ( char mine[ ROWS] [ COLS] , int x, int y)
{
int sz = 0 ;
int i = x - 1 , j = y - 1 ;
for ( i = x - 1 ; i <= x + 1 ; i++ )
{
for ( j = y - 1 ; j <= y + 1 ; j++ )
{
sz = sz + mine[ i] [ j] - '0' ;
}
}
return sz;
}
void Fine_mine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int row, int col)
{
int x, y = 0 ;
int win = 0 ;
while ( win< row* col- EASY_COUNT)
{
printf ( "请输入要排查的坐标:>" ) ;
scanf ( "%d%d" , & x, & y) ;
if ( x >= 1 && x <= row && y >= 1 && y <= col)
{
if ( mine[ x] [ y] == '1' )
{
printf ( "很遗憾,你被炸死了" ) ;
Show_board ( mine, ROW, COL) ;
break ;
}
else
{
int count = get_mine_count ( mine, x, y) ;
show[ x] [ y] = count + '0' ;
Show_board ( show, ROW, COL) ;
win++ ;
}
}
else
{
printf ( "非法坐标,请重新输入" ) ;
}
}
if ( win == row * col - EASY_COUNT)
{
printf ( "恭喜你,排雷成功!" ) ;
Show_board ( mine, ROW, COL) ;
}
}
四:结果演示
4.1排雷失败
4.2排雷成功
这里取巧,直接修改了雷的个数,并在透析雷所处的位置的情况下实现。
五:项目源代码
# define _CRT_SECURE_NO_WARNINGS 1
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# define ROW 9
# define COL 9
# define ROWS ROW+ 2
# define COLS COL+ 2
# define EASY_COUNT 10
void Init_board ( char arr[ ROWS] [ COLS] , int rows, int cols, char set) ;
void Show_board ( char arr[ ROWS] [ COLS] , int row, int col) ;
void Set_mine ( char arr[ ROWS] [ COLS] , int row, int col) ;
void Find_mine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int row, int col) ;
void Init_board ( char arr[ ROWS] [ COLS] , int rows, int cols, char set)
{
int i, j = 0 ;
for ( i = 0 ; i < rows; i++ )
{
for ( j = 0 ; j < cols; j++ )
{
arr[ i] [ j] = set;
}
}
}
void Show_board ( char arr[ ROWS] [ COLS] , int row, int col)
{
int i = 0 , j = 0 ;
printf ( "-----------扫雷-----------\n" ) ;
for ( i = 0 ; i <= col; i++ )
{
printf ( "%d " , i) ;
}
printf ( "\n" ) ;
for ( i = 1 ; i <= row; i++ )
{
printf ( "%d " , i) ;
for ( j = 1 ; j <= col; j++ )
{
printf ( "%c " , arr[ i] [ j] ) ;
}
printf ( "\n" ) ;
}
}
void Set_mine ( char mine[ ROWS] [ COLS] , int row, int col)
{
int x, y = 0 ;
int count = EASY_COUNT;
while ( count)
{
x = rand ( ) % row + 1 ;
y = rand ( ) % col + 1 ;
if ( mine[ x] [ y] == '0' )
{
mine[ x] [ y] = '1' ;
count-- ;
}
}
}
int get_mine_count ( char mine[ ROWS] [ COLS] , int x, int y)
{
int sz = 0 ;
int i = x - 1 , j = y - 1 ;
for ( i = x - 1 ; i <= x + 1 ; i++ )
{
for ( j = y - 1 ; j <= y + 1 ; j++ )
{
sz = sz + mine[ i] [ j] - '0' ;
}
}
return sz;
}
void Find_mine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int row, int col)
{
int x, y = 0 ;
int win = 0 ;
while ( win< row* col- EASY_COUNT)
{
printf ( "请输入要排查的坐标:>" ) ;
scanf ( "%d%d" , & x, & y) ;
if ( x >= 1 && x <= row && y >= 1 && y <= col)
{
if ( mine[ x] [ y] == '1' )
{
printf ( "很遗憾,你被炸死了" ) ;
Show_board ( mine, ROW, COL) ;
break ;
}
else
{
int count = get_mine_count ( mine, x, y) ;
show[ x] [ y] = count + '0' ;
Show_board ( show, ROW, COL) ;
win++ ;
}
}
else
{
printf ( "非法坐标,请重新输入" ) ;
}
}
if ( win == row * col - EASY_COUNT)
{
printf ( "恭喜你,排雷成功!" ) ;
Show_board ( mine, ROW, COL) ;
}
}
void menu ( )
{
printf ( "*************************\n" ) ;
printf ( "*********1.play**********\n" ) ;
printf ( "*********0.eixt**********\n" ) ;
printf ( "*************************\n" ) ;
}
void game ( )
{
char mine[ ROWS] [ COLS] = { 0 } ;
char show[ ROWS] [ COLS] = { 0 } ;
Init_board ( mine, ROWS, COLS, '0' ) ;
Init_board ( show, ROWS, COLS, '#' ) ;
Set_mine ( mine, ROW, COL) ;
Show_board ( show, ROW, COL) ;
Find_mine ( mine, show, ROW, COL) ;
}
int main ( )
{
int input = 0 ;
srand ( ( unsigned int ) time ( NULL ) ) ;
do
{
menu ( ) ;
printf ( "请选择:>" ) ;
scanf ( "%d" , & input) ;
switch ( input)
{
case 1 :
game ( ) ;
break ;
case 0 :
printf ( "退出游戏\n" ) ;
break ;
default :
printf ( "选择错误,请重新选择:>" ) ;
break ;
}
} while ( input) ;
return 0 ;
}