C语言“黑框框”下简易扫雷实现

来源:互联网 发布:学编程的游戏ios 编辑:程序博客网 时间:2024/05/06 15:50

初步了解数组、指针后,实现了一个win32控制台下(黑框框)简易版扫雷程序.


程序中 行数列数雷数可自行定义。


程序用*代表位置未知,空格代表此位置周围无雷,数字代表周围雷个数。


分三个代码共同编译实现,SaoLei.h包含程序所需头文件,宏定义及所用函数声明。SaoLei.c为游戏逻辑代码。Function.c 为自定义函数实现代码。


程序用两个char数组分别表示两块地图,一副地图呈现给玩家,一幅地图用于实现布雷及雷数更新等。两个数组在程序中会时时交互。


程序拥有坐标合法性检查函数,保证输入不合法坐标及重复坐标时程序可以正常运行。


游戏简易思路: 创建两个char数组分别代表两个地图, 一个地图为游戏地图呈现给玩家,一个地图用来布雷(用rand()函数初始化雷坐标)。考虑到需要检测边界处周围雷个数,因此布雷数组比游戏数组多两行两列。 限于win32 平台下 ,因此用输入坐标形式进行交互(输入坐标与数组坐标不同,在程序中有注释)。 玩家每输入一个坐标, 不同函数中两个数组进行传参交互,判断输赢,坐标是否合法,显示坐标周围雷个数, 更新数组, 重新打印地图等。 


程序实现后并未进行优化,所以可能存在下许问题:代码或许会有些冗杂,函数或许未很好的封装导致重复,或本为一个函数模块却分多个函数实现等。尽请见谅。


程序中有详尽注释。


源码如下:

SaoLei.h:

/*此自定义头文件包含SaoLei.c与Function.c所需头文件及函数原型声明*/#ifndef __SaoLei_h__#define __SaoLei_h__//程序用到标准输入输出函数#include <stdio.h>/*程序随机产生雷坐标*/#include <stdlib.h>#include <time.h>#define ROWS 11        //定义数组行数(注意! 实际显示给用户的地图行数为ROWS - 2)#define COLS 11        //定义数组列数(注意! 实际显示给用户的地图列数为COLS - 2)#define NUM  10//定义雷个数//打印游戏选择菜单void menu(void);//初始化两块地图void init_map(char gamemap[][COLS - 2], char map[][COLS], int rows);//此处传来的参数rows为map的行数,gamemap的行数应为rows - 2//打印最新游戏地图void print_gamemap(char gamemap[][COLS - 2], int rows);//此处传来的参数rows为gamemap的行数ROWS - 2//进行游戏void playgame(char gamemap[][COLS - 2], char map[][COLS], int rows);//此处传来的参数rows为map的行数,gamemap的行数应为rows - 2//检测玩家输入坐标是否合法int check(char gamemap[][COLS - 2], int rows, int x, int y);//此处传来的参数rows为gamemap的行数ROWS - 2 x y 为玩家输入坐标//判断雷是否已排完int count(char gamemap[][COLS - 2], int rows, int num);//此处传来的参数rows为gamemap的行数ROWS - 2 num为已定义的雷个数//判断输入坐标身边雷情况int pailei(char map[][COLS], int x, int y);//返回-1则此坐标为雷,返回0-8代表此坐标身边雷个数                        //参数x y 为玩家输入坐标//更新gamemapvoid gxgamemap(char gamemap[][COLS - 2], int x, int y, int ret);        //x, y为输入坐标, ret为输入坐标身边雷个数//打印map地图(供测试用)void print_map(char map[][COLS], int rows);//此处传来的参数rows为map的行数ROWS#endif

SaoLei.c:

/*扫雷游戏逻辑*/#include "SaoLei.h"int main(void){int input;//用来接受用户输入char gamemap[ROWS - 2][COLS - 2];//gamemap用来向用户展示的地图char map[ROWS][COLS];//map    用来显示雷位置地图,不向用户展示menu();//打印游戏选择菜单scanf("%d", &input);    <span style="white-space:pre"></span>//接收用户输入 1为进行游戏 0为退出游戏while( input )//对用户输入进行判断{init_map(gamemap, map, ROWS);/*初始化两块地图  此处传过去的参数ROWS为map的行数,gamemap的行数应为ROWS - 2*/print_gamemap(gamemap, ROWS - 2);//打印最新游戏地图//print_map(map, ROWS);//打印map(用于测试)playgame(gamemap, map, ROWS);//进行游戏menu();//再次打印游戏菜单scanf("%d", &input);<span style="white-space:pre"></span>//再次接收用户输入 1为进行游戏 0为退出游戏<span style="white-space:pre"></span>}//游戏结束printf("\nBye!\n");return 0;//程序结束}


Function.c:


/*SaoLei.c中函数实现*/#include "SaoLei.h"//打印游戏菜单void menu(void){printf("********************\n");printf("****** 1.play ******\n");printf("****** 0.exit ******\n");printf("********************\n");}//初始化两块地图void init_map(char gamemap[][COLS - 2], char map[][COLS], int rows)//此处传来的参数rows为map的行数,gamemap的行数应为rows - 2{int r;int c;int x;        //保存随机产生雷行标int y;//保存随机产生雷列标int count = 0;//计算雷个数 已定义NUM为雷个数srand((unsigned)time(NULL));for( r = 0; r < rows - 2; r++ )<span style="white-space:pre"></span>//初始化gamemap地图,每个位置设为'*'表示此位置未知for( c = 0; c < COLS - 2; c++ )gamemap[r][c] = '*';for( r = 0; r < rows; r++ )//初始化没有雷的map棋盘,每个位置设为'0'表示无雷for( c = 0; c < COLS; c++ )map[r][c] = '0';for( count = 0; count < NUM; )<span style="white-space:pre"></span>        //对map地图进行布雷,位置为'1'表示有雷{/*map中首行首列末行末列不放雷,所以x y坐标有限制*/x = rand() % 9 + 1;//随机产生雷行标 1 - 9y = rand() % 9 + 1;//随机产生雷列标 1 - 9if( map[x][y] != '1' ){/*如果此坐标未被设置雷, 则将count++, 并将此位置坐标设为雷('1')*/map[x][y] = '1';count++;}}//退出for循环}//init_map函数结束//打印最新游戏地图void print_gamemap(char gamemap[][COLS - 2], int rows)//此处传来的参数rows为gamemap的行数,ROWS - 2{int i;int r;int c;/*打印行标号与列标号*/putchar(' ');for( i = 0; i < COLS - 2; i++ )printf("%d ", i + 1);putchar('\n');/*打印gamemap*/for( r = 0; r < rows; r++ ){printf("%d", r + 1);for( c = 0; c < COLS - 2; c++ )printf("%c ", gamemap[r][c]);printf("\n");}}//打印map地图(供测试用)void print_map(char map[][COLS], int rows)//此处传来的参数rows为map的行数ROWS{int i;int r;intc;putchar('\n');printf(" ");for( i = 0; i < ROWS; i++ )printf("%d ", i + 1);putchar('\n');for( r = 0; r < rows; r++ ){printf("%d", r + 1);for( c = 0; c < COLS; c++ )printf("%c ", map[r][c]);putchar('\n');}}//检测玩家输入坐标是否合法int check(char gamemap[][COLS - 2], int rows, int x, int y)//此处传来的参数rows为gamemap的行数ROWS - 2. x y 为玩家输入行列坐标{if( ((x >= 1) && (x <= 9)) && ((y >= 1) && (y <= 9)) )//x y范围是否满足if( gamemap[x - 1][y - 1] == '*' )//此坐标是否已被使用过return 0;return 1;//返回0输入坐标合法, 返回1输入坐标不合法!}//判断雷是否已排完int count(char gamemap[][COLS - 2], int rows, int num)//此处传来的参数rows为gamemap的行数ROWS - 2 num为已定义的雷个数{int r;int c;int n = 0;//目前雷数目for( r = 0; r < rows; r++ )for( c = 0; c < COLS - 2; c++ )if( gamemap[r][c] == '*')n++;if( n == num )return 0;return 1;//返回0 则雷已排完 返回 1 则雷未排完 }/*判断输入坐标身边雷情况返回-1则此坐标为雷,返回0-8代表此坐标身边雷个数参数 x y 为玩家输入坐标'1'代表雷*/int pailei(char map[][COLS], int x, int y){int ret = 0;//保存雷个数if( map[x][y] == '1' )//此坐标为雷,返回-1return -1;/*计算雷个数,并返回值*/if( map[x][y + 1] == '1')ret++;if( map[x + 1][y + 1] == '1')ret++;if( map[x - 1][y + 1] == '1')ret++;if( map[x][y - 1] == '1')ret++;if( map[x + 1][y - 1] == '1')ret++;if( map[x - 1][y - 1] == '1')ret++;if( map[x + 1][y] == '1')ret++;if( map[x - 1][y] == '1')ret++;return ret;}//更新gamemapvoid gxgamemap(char gamemap[][COLS - 2], int x, int y, int ret)//ret为输入坐标身边雷个数, x y为输入坐标{while( 1 ){if( ret == 0 ){gamemap[x - 1][y - 1] = ' ';break;}gamemap[x - 1][y - 1] = '0' + ret;break;}}//进行游戏void playgame(char gamemap[][COLS - 2], char map[][COLS], int rows)//此处传来的参数rows为map的行数,gamemap的行数应为rows - 2{int x;//int y;//存放用户输入坐标int ret;//存放返回数值,用来说明用户输入的坐标处情况while( count(gamemap, ROWS - 2, NUM) )        //返回0则雷已排完,游戏胜利,返回1则雷未排完. {printf("请输入坐标:");scanf("%d %d", &x, &y);while( check(gamemap, ROWS - 2, x, y) )        //检测玩家输入坐标是否合法{printf("坐标不合法!\n请重新输入坐标:");scanf("%d %d", &x, &y);}ret = pailei(map, x, y);//返回-1则此坐标为雷,返回0-8代表此坐标身边雷个数if( ret == -1 )//游戏失败{printf("呵呵!\n");break;}gxgamemap(gamemap, x, y, ret);//根据返回值更新gamemap, x y 为输入的坐标print_gamemap(gamemap, ROWS - 2);        //打印最新游戏地图//print_map(map, ROWS);//打印map地图(用于测试)}//退出最外层while循环if( (count(gamemap, ROWS - 2, NUM)) == 0 )//判断是胜利后跳出while循环还是失败后跳出,若是胜利,函数返回值为0printf("你赢了!\n");}//退出playgame函数





0 0
原创粉丝点击