一.实现功能 首先显示一个小菜单,选择是否玩游戏。当用户选择退出时,程序运行结束,当用户选择玩游戏时,将提示用户输入扫雷位置坐标。当用户输入坐标超出棋盘范围或者位置之前已经进行扫雷时,将提示用户重新输入。当用户输入正确坐标时,如果输入位置没雷将会显示当前位置周边有几个雷,直到将所有雷找出后,重新显示菜单。当输入位置有雷时,游戏结束,重新显示菜单。
二.分析与介绍 首先编写程序开始前,我们要清楚知道棋盘时二维的,所以这里会要用到二维数组来保存棋盘状态。由于这里我们要一张显示给用户看的棋盘,一张电脑随机埋雷的棋盘,所以我们要定义两个二维数组。然后我们只需要根据功能一步步进行程序的编写,如下。
理清思路:
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
|