前言
简单用C语言实现了扫雷小游戏,所谓之版本1.0(水平只够1.0…)。如有错误,欢迎uu们指出!
游戏规则介绍
思路
建立两个棋盘: ①用来展示给玩家玩的,一个是生成地雷的。 ②用来生成地雷的,即地雷位置的信息。 当玩家在①棋盘中进行选择时,程序根据②棋盘中雷的信息,给予相应的反馈
在test.c中生成游戏菜单
# pragma once
# include "game.h"
void menu ( )
{
printf ( "*****************************\n" ) ;
printf ( "****** 1.play ******\n" ) ;
printf ( "*****************************\n" ) ;
printf ( "*****************************\n" ) ;
printf ( "*****************************\n" ) ;
printf ( "****** 0.exit ******\n" ) ;
printf ( "*****************************\n" ) ;
}
int main ( )
{
int input = 0 ;
do
{
srand ( ( unsigned int ) time ( NULL ) ) ;
menu ( ) ;
printf ( "请输入您的选择->\n" ) ;
scanf ( "%d" , & input) ;
switch ( input)
{
case 1 :
game ( ) ;
break ;
case 0 :
printf ( "退出游戏\n" ) ;
break ;
default :
printf ( "没有该选项,请重新输入\n" ) ;
break ;
}
} while ( input) ;
}
void game ( )
{
char mine[ ROWS] [ COLS] = { 0 } ;
char show[ ROWS] [ COLS] = { 0 } ;
InitBoard ( mine, ROW, COL, '0' ) ;
InitBoard ( show, ROW, COL, '*' ) ;
DisplayBoard ( show, ROW, COL) ;
SetMine ( mine, ROW, COL) ;
DisplayBoard ( mine, ROW, COL) ;
FindMine ( mine, show, ROW, COL) ;
}
雷区的建立
我们照着代码说:
首先在game.h中定义行和列以及函数的声明,COLS、ROWS 则是为了防止数组越界
# define COL 9
# define ROW 9
# define COLS COL+ 2
# define ROWS ROW+ 2
# define COUNT 10
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
void InitBoard ( char board[ ROWS] [ COLS] , int rows, int cols, char set) ;
棋盘的建立
在game.c中实现初始化雷区的函数,这里①②棋盘只需用一个函数即可实现,set为对应棋盘初始化用的符号
void InitBoard ( char board[ ROWS] [ COLS] , int rows, int cols, char set)
{
int i = 0 ;
int j = 0 ;
for ( i = 0 ; i <= rows+ 1 ; i++ )
{
for ( j = 0 ; j <= cols+ 1 ; j++ )
{
board[ i] [ j] = set;
}
}
}
随机埋地雷
void SetMine ( char board[ ROWS] [ COLS] , int rows, int cols)
{
int count = COUNT; ;
while ( count)
{
int x = rand ( ) % rows;
int y = rand ( ) % cols;
if ( board[ x] [ y] == '0' && x >= 1 && x <= rows && y >= 1 && y <= cols)
{
board[ x] [ y] = '1' ;
count-- ;
}
}
}
int main ( )
{
int input = 0 ;
do
{
srand ( ( unsigned int ) time ( NULL ) ) ;
menu ( ) ;
printf ( "请输入您的选择->\n" ) ;
scanf ( "%d" , & input) ;
switch ( input)
{
case 1 :
game ( ) ;
break ;
case 0 :
printf ( "退出游戏\n" ) ;
break ;
default :
printf ( "没有该选项,请重新输入\n" ) ;
break ;
}
} while ( input) ;
}
效果展示
这里我们用' * '带表棋盘①未知格子,' 0 '表示②棋盘无雷格子,' 1 '表示②棋盘藏雷格子。至此雷区建立完成。
排雷
周围雷计数
我们知道,当我们玩扫雷时,点击格子会出现一个数字,这个数字代表的就是我们选择的格子周围八个格子中的地雷个数。
int count_mine ( char mine[ ROWS] [ COLS] , int x, int y)
{
return mine[ x - 1 ] [ y - 1 ] +
mine[ x] [ y - 1 ] +
mine[ x + 1 ] [ y - 1 ] +
mine[ x - 1 ] [ y] +
mine[ x + 1 ] [ y] +
mine[ x - 1 ] [ y + 1 ] +
mine[ x] [ y + 1 ] +
mine[ x + 1 ] [ y + 1 ] - 8 * '0' ;
}
这里其实就是将选择的格子周围的八个格子的字符相加,我们知道,棋盘②中存放的是字符'0'和'1',而数字字符的ACILL值是按序递增的,所以这里累加之后再减去8*'0'即可算出地雷的个数。
附上ACILL表格(部分截取):
排雷的展开效果实现
原理:当玩家选择的格子周围八个格子都没有地雷时,它会不断展开,这就可以用递归来实现。
附图:
void SpreadMine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int x, int y)
{
int count = count_mine ( mine, x, y) ;
if ( count != 0 )
{
show[ x] [ y] = count + '0' ;
return ;
}
else if ( count == 0 )
{
show[ x] [ y] = ' ' ;
if ( show[ x] [ y + 1 ] == '*' )
SpreadMine ( mine, show, x, y + 1 ) ;
if ( show[ x] [ y - 1 ] == '*' )
SpreadMine ( mine, show, x, y - 1 ) ;
if ( show[ x + 1 ] [ y] == '*' )
SpreadMine ( mine, show, x + 1 , y) ;
if ( show[ x - 1 ] [ y] == '*' )
SpreadMine ( mine, show, x - 1 , y) ;
if ( show[ x - 1 ] [ y - 1 ] == '*' )
SpreadMine ( mine, show, x - 1 , y - 1 ) ;
if ( show[ x + 1 ] [ y + 1 ] == '*' )
SpreadMine ( mine, show, x + 1 , y + 1 ) ;
if ( show[ x - 1 ] [ y + 1 ] == '*' )
SpreadMine ( mine, show, x - 1 , y + 1 ) ;
if ( show[ x + 1 ] [ y - 1 ] == '*' )
SpreadMine ( mine, show, x + 1 , y - 1 ) ;
}
return ;
}
这里我用递归来实现,终止条件就是当展开到的格子周围有雷时,未达到终止条件时,依次对周围格子进行重复判断,无地雷的格子用空格表示。最终的递归效果就是围绕着地雷会显示周围地雷个数的数字。
输赢的判断
void FindMine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int rows, int cols)
{
int x = 0 ;
int y = 0 ;
while ( 1 )
{
printf ( "请输入您的排雷坐标->(x,y)\n" ) ;
scanf ( "%d %d" , & x, & y) ;
if ( x >= 1 && x <= rows && y >= 1 && y <= cols&& show[ x] [ y] == '*' )
{
if ( mine[ x] [ y] == '1' )
{
printf ( "!!!您踩到了地雷,被炸死了!!!\n" ) ;
break ;
}
else if ( mine[ x] [ y] = '0' )
{
SpreadMine ( mine, show, x, y) ;
DisplayBoard ( show, rows, cols) ;
if ( is_win ( show, rows, cols) == COUNT)
{
printf ( "!!!恭喜您,排雷成功!!!\n" ) ;
DisplayBoard ( mine, rows, cols) ;
break ;
}
}
}
else
{
printf ( "输入坐标错误,请重新输入->(x,y)\n" ) ;
DisplayBoard ( show, rows, cols) ;
}
}
return ;
}
int is_win ( char show[ ROWS] [ COLS] , int rows, int cols)
{
int i = 0 ;
int j = 0 ;
int count = 0 ;
for ( i = 1 ; i <= rows; i++ )
{
for ( j = 1 ; j <= cols; j++ )
{
if ( show[ i] [ j] == '*' )
{
count++ ;
}
}
}
return count;
}
当我们遍历棋盘①,发现未知格子' * '的个数等于我们布置的雷的个数时,即为排雷成功。至此,扫雷完成。
代码
game.h
# pragma once
# define COL 9
# define ROW 9
# define COLS COL+ 2
# define ROWS ROW+ 2
# define COUNT 10
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
void InitBoard ( char board[ ROWS] [ COLS] , int rows, int cols, char set) ;
void DisplayBoard ( char board[ ROWS] [ COLS] , int rows, int cols) ;
void SetMine ( char board[ ROWS] [ COLS] , int rows, int cols) ;
void FindMine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int rows, int cols) ;
int count_mine ( char mine[ ROWS] [ COLS] , int x, int y) ;
void SpreadMine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int x, int y) ;
int is_win ( char board[ ROWS] [ COLS] , int rows, int cols) ;
game.c
# pragma once
# include "game.h"
void InitBoard ( char board[ ROWS] [ COLS] , int rows, int cols, char set)
{
int i = 0 ;
int j = 0 ;
for ( i = 0 ; i <= rows+ 1 ; i++ )
{
for ( j = 0 ; j <= cols+ 1 ; j++ )
{
board[ i] [ j] = set;
}
}
}
void DisplayBoard ( char board[ ROWS] [ COLS] , int rows, int cols)
{
int i = 0 ;
int j = 0 ;
for ( i = 0 ; i <= cols; i++ )
{
printf ( "%3d" , i) ;
}
putchar ( '\n' ) ;
for ( i = 1 ; i <= rows; i++ )
{
printf ( "%3d" , i) ;
for ( j = 1 ; j <= cols; j++ )
{
printf ( "%3c" , board[ i] [ j] ) ;
}
putchar ( '\n' ) ;
}
putchar ( '\n' ) ;
}
void SetMine ( char board[ ROWS] [ COLS] , int rows, int cols)
{
int count = COUNT; ;
while ( count)
{
int x = rand ( ) % rows;
int y = rand ( ) % cols;
if ( board[ x] [ y] == '0' && x >= 1 && x <= rows && y >= 1 && y <= cols)
{
board[ x] [ y] = '1' ;
count-- ;
}
}
}
int count_mine ( char mine[ ROWS] [ COLS] , int x, int y)
{
return mine[ x - 1 ] [ y - 1 ] +
mine[ x] [ y - 1 ] +
mine[ x + 1 ] [ y - 1 ] +
mine[ x - 1 ] [ y] +
mine[ x + 1 ] [ y] +
mine[ x - 1 ] [ y + 1 ] +
mine[ x] [ y + 1 ] +
mine[ x + 1 ] [ y + 1 ] - 8 * '0' ;
}
void FindMine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int rows, int cols)
{
int x = 0 ;
int y = 0 ;
while ( 1 )
{
printf ( "请输入您的排雷坐标->(x,y)\n" ) ;
scanf ( "%d %d" , & x, & y) ;
if ( x >= 1 && x <= rows && y >= 1 && y <= cols&& show[ x] [ y] == '*' )
{
if ( mine[ x] [ y] == '1' )
{
printf ( "!!!您踩到了地雷,被炸死了!!!\n" ) ;
break ;
}
else if ( mine[ x] [ y] = '0' )
{
SpreadMine ( mine, show, x, y) ;
DisplayBoard ( show, rows, cols) ;
if ( is_win ( show, rows, cols) == COUNT)
{
printf ( "!!!恭喜您,排雷成功!!!\n" ) ;
DisplayBoard ( mine, rows, cols) ;
break ;
}
}
}
else
{
printf ( "输入坐标错误,请重新输入->(x,y)\n" ) ;
DisplayBoard ( show, rows, cols) ;
}
}
return ;
}
void SpreadMine ( char mine[ ROWS] [ COLS] , char show[ ROWS] [ COLS] , int x, int y)
{
int count = count_mine ( mine, x, y) ;
if ( count != 0 )
{
show[ x] [ y] = count + '0' ;
return ;
}
else if ( count == 0 )
{
show[ x] [ y] = ' ' ;
if ( show[ x] [ y + 1 ] == '*' )
SpreadMine ( mine, show, x, y + 1 ) ;
if ( show[ x] [ y - 1 ] == '*' )
SpreadMine ( mine, show, x, y - 1 ) ;
if ( show[ x + 1 ] [ y] == '*' )
SpreadMine ( mine, show, x + 1 , y) ;
if ( show[ x - 1 ] [ y] == '*' )
SpreadMine ( mine, show, x - 1 , y) ;
if ( show[ x - 1 ] [ y - 1 ] == '*' )
SpreadMine ( mine, show, x - 1 , y - 1 ) ;
if ( show[ x + 1 ] [ y + 1 ] == '*' )
SpreadMine ( mine, show, x + 1 , y + 1 ) ;
if ( show[ x - 1 ] [ y + 1 ] == '*' )
SpreadMine ( mine, show, x - 1 , y + 1 ) ;
if ( show[ x + 1 ] [ y - 1 ] == '*' )
SpreadMine ( mine, show, x + 1 , y - 1 ) ;
}
return ;
}
int is_win ( char show[ ROWS] [ COLS] , int rows, int cols)
{
int i = 0 ;
int j = 0 ;
int count = 0 ;
for ( i = 1 ; i <= rows; i++ )
{
for ( j = 1 ; j <= cols; j++ )
{
if ( show[ i] [ j] == '*' )
{
count++ ;
}
}
}
return count;
}
test.c
# pragma once
# include "game.h"
void menu ( )
{
printf ( "*****************************\n" ) ;
printf ( "****** 1.play ******\n" ) ;
printf ( "*****************************\n" ) ;
printf ( "*****************************\n" ) ;
printf ( "*****************************\n" ) ;
printf ( "****** 0.exit ******\n" ) ;
printf ( "*****************************\n" ) ;
}
void game ( )
{
char mine[ ROWS] [ COLS] = { 0 } ;
char show[ ROWS] [ COLS] = { 0 } ;
InitBoard ( mine, ROW, COL, '0' ) ;
InitBoard ( show, ROW, COL, '*' ) ;
DisplayBoard ( show, ROW, COL) ;
SetMine ( mine, ROW, COL) ;
DisplayBoard ( mine, ROW, COL) ;
FindMine ( mine, show, ROW, COL) ;
}
int main ( )
{
int input = 0 ;
do
{
srand ( ( unsigned int ) time ( NULL ) ) ;
menu ( ) ;
printf ( "请输入您的选择->\n" ) ;
scanf ( "%d" , & input) ;
switch ( input)
{
case 1 :
game ( ) ;
break ;
case 0 :
printf ( "退出游戏\n" ) ;
break ;
default :
printf ( "没有该选项,请重新输入\n" ) ;
break ;
}
} while ( input) ;
}