一.实现功能
首先显示一个小菜单,选择是否玩游戏。当用户选择退出时,程序运行结束,当用户选择玩游戏时,将提示用户输入扫雷位置坐标。当用户输入坐标超出棋盘范围或者位置之前已经进行扫雷时,将提示用户重新输入。当用户输入正确坐标时,如果输入位置没雷将会显示当前位置周边有几个雷,直到将所有雷找出后,重新显示菜单。当输入位置有雷时,游戏结束,重新显示菜单。
二.分析与介绍
首先编写程序开始前,我们要清楚知道棋盘时二维的,所以这里会要用到二维数组来保存棋盘状态。由于这里我们要一张显示给用户看的棋盘,一张电脑随机埋雷的棋盘,所以我们要定义两个二维数组。然后我们只需要根据功能一步步进行程序的编写,如下。
理清思路:
1.将数组初始化
2.电脑随机埋雷 Minelay();
3.展示棋盘 Showboard();
4.让用户扫雷,判断输入坐标是否合理
5.计算次数,返回显示给用户
三.代码编写
首先确定主函数main()的编写确定主要逻辑,首先显示菜单供用户选择是否玩游戏,后面对用户的选择进行判断是否玩游戏。代码块如下:
#include"minesweep.h"
int main(){
int quit = 0;//退出标志
while (!quit){
int select = 0;
Menu();
printf("Please Enter Your Select#");
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 2:
quit = 1;
break;
default:
printf("Enter Error!\n");
break;
}
}
printf("Byebye\n");
system("pause");
return 0;
}
菜单函数Menu()代码:
void Menu(){
printf("+------------------+\n");
printf("+-1.Play 2.Exit-+\n");
printf("+------------------+\n");
}
当用户选择玩游戏时,Game()函数是主要游戏逻辑的编写,首先对棋盘进行初始化,再电脑随机埋雷,展示棋盘让用户输入扫雷的坐标值。此时要进行判断输入坐标值是否超过棋盘范围,是否已经扫过雷,如果用户输入坐标有雷直接游戏结束。如果没雷,计算出周边雷的个数后显示出来,再进行上面的操作,直到扫完雷为止。
void Game(){
srand((unsigned long)time(NULL));//生成时间随机数种子
char show_board[ROW][COL];
char mine_board[ROW][COL];
int count = (ROW - 2)*(COL - 2) - MINE;//不是雷的数量
memset(show_board, INIT, sizeof(show_board));//初始化
memset(mine_board, '0', sizeof(mine_board));
Minelay(mine_board, ROW, COL);
while (count){ //
//system("cls");
Showboard(show_board, ROW, COL);
int x = 0;
int y = 0;
printf("Please Enter Your Postion<x,y>#");
scanf("%d %d", &x, &y);
if (x<1 || x>10 || y<1 || y>10){//判断是否越界
printf("Potion is error\n");
continue;
}
if (show_board[x][y] != INIT){//判断是否已经扫过
printf("Repeat Postion\n");
continue;
}
if (mine_board[x][y] == '1'){//判断是否是雷
Showboard(mine_board, ROW, COL);
printf("Game over!\n");
break;
}
char result = Countmine(mine_board, x, y);
show_board[x][y] = result;
count--;
system("cls");
}
if (count == 0){
printf("You win!\n");
}
}
再电脑随机埋雷Minelay(),此时利用随机数种子(Game函数中已经种下),随机生成棋盘X,Y坐标,如果埋雷棋盘在该位置没雷,将字符‘1’赋予该位置。字符‘0’代表有雷,字符‘1’代表有雷。
static void Minelay(char board[][COL], int row, int col){//电脑随机埋雷
int count = MINE;//埋雷数
while (count){
int x = rand() % (row - 2) + 1;
int y = rand() % (col - 2) + 1;
if (board[x][y] == '0'){//防止重复埋雷
board[x][y] = '1';
count--;
}
}
}
后将棋盘展示Shows_board(),提示用户输入扫雷坐标。后面如果扫雷位置有雷时,显示埋雷棋盘给用户看。
static Drawline(int col){ //画线
for (int i = 0; i < col+2; i++){
printf("---");
}
printf("\n");
}
static void Showboard(char board[][COL], int row, int col){//展示棋盘
printf(" ");
for (int i = 1; i < row - 1; i++){
printf("|%2d ", i);;
}
printf("\n");
Drawline(col);
for (int j = 1; j < col - 1; j++){
printf("%-2d", j);
for (int k = 1; k < col - 1; k++){
printf("| %c ", board[j][k]);
}
printf("\n");
Drawline(col);
}
}
最后如果扫雷位置没雷还要将周边雷的个数显示出来给用户。计数方式:将周围字符全部加起来减去周围全是字符‘0’的情况。因为用的字符‘1’表示有雷,字符‘1’与字符‘0’只ascll只相差1,用此方法相减后就得到了雷数。
static char Countmine(char board[][COL], int x, int y){//返回周边雷数
return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \
board[x][y + 1] + board[x + 1][y + 1] + board[x + 1][y] + board[x + 1][y - 1] + \
board[x][y - 1] - 8 * '0' + '0'; //i表示有雷,0表示没雷,用周边字符相加减去周边没雷情况,等于雷数,加字符0,整形转字符。
}
整体代码如上所述,由于使用的时多文件编码的方式,还需要对函数,变量和头文件进行声明。
#ifndef __MINESWEEP_H__
#define __MINESWEEP_H__
#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include<time.h>
#pragma warning(disable:4996)
//字符1 表示有雷 字符0表示没雷
//用12*12的数组,取中间10*10的棋盘,好计算周边雷数
#define ROW 12//行数
#define COL 12//列数
#define INIT '?'//shou_board 初始化
#define MINE 20//雷数
extern void Menu();
extern void Game();
#endif
四.效果展示
至此用C语言编写的扫雷代码结束,如想应用复制代码即可,如有缺陷请多多批评。