赞
踩
c语言实现扫雷游戏,非雷位置可以递归展开,且为保证游戏体验,用户第一次扫雷时不能踩中雷。
扫雷游戏大家都玩过,具体规则我也就不再赘述。要实现扫雷游戏,我们至少得需要两个棋盘,一张给用户展示,让用户输入在这张棋盘上进行扫雷,另一张为埋雷棋盘,这张棋盘上埋藏若干个雷,将用户输入的坐标与这张棋盘上对应的坐标进行对比,如果是雷,则游戏结束,如果不是雷则继续。
程序需要实现的功能以及实现该功能的函数。
menu函数,指引用户做出选择。
game函数,游戏从这里开始。
setmine函数,实现埋雷,并找到一个没有雷的坐标,用于保护用户第一次不能踩中雷。
show函数,展示棋盘。
minecount函数,计算该位置周围雷的个数。
open函数,对非雷位置进行递归展开。
judge函数,判断用户是否扫雷成功。
#ifndef __GAME_H__ #define __GAME_H__ #include <stdio.h> #include <windows.h> #include <time.h> #pragma warning(disable:4996) #define ROW 12 #define COL 12 #define MINENUM 20 void menu(); void setmine(char mineboard[][COL],int * x, int * y); void show(char board[][COL]); int minecount(char mineboard[][COL], int x, int y); void game(); void open(char mineboard[][COL], char sweepboard[][COL], int x, int y); int judge(char sweepboard[][COL]); #endif
#include "game.h"
int main()
{
menu();
system("pause");
return 0;
}
void menu() //menu函数,指引用户做出选择。 { int quit = 1; while (quit) { printf("###############################\n"); printf("####### 欢迎来到扫雷 ########\n"); printf("###############################\n"); printf("#####1:play ####\n"); printf("#####2:exit ####\n"); printf("###############################\n"); printf("###############################\n"); int k = 0; scanf("%d", &k); switch (k) { case 1: game();//输入1,调用game函数,游戏开始。 break; case 2: quit = 0; printf("Bye bye!\n");//输入0,程序运行结束。 break; default: printf("输入有误,请重新输入:\n"); break; } } }
void game()// game函数,游戏开始。 { int flag = 1; int x0 = 0; int y0 = 0; char sweepboard[ROW][COL];//第一个二维数组,扫描棋盘,用于给用户展示。为方便计算 // 定义数组为12 * 12,实际用到的是10 * 10的棋盘,后续棋盘均指10 * 10棋盘。 char mineboard[ROW][COL];//第二个二维数组,埋雷棋盘,用于埋雷。 memset(sweepboard, '*', sizeof(sweepboard));//扫描棋盘初始化均为‘*’ memset(mineboard, '0', sizeof(mineboard));//埋雷棋盘初始化均为‘0’ setmine(mineboard, &x0, &y0);//调用setmine函数,系统随机埋雷,整型变量x0和y0用于传回一个非雷的坐标。 while (1) { system("cls"); show(sweepboard); //show函数,展示棋盘。 printf("请输入坐标:"); int x = 0; int y = 0; scanf("%d %d", &x, &y); if (x < 1 || x > 10 || y < 1 || y > 10) { printf("输入坐标有误,请重新输入!\n"); Sleep(1500); continue; } if (sweepboard[x][y] != '*') { printf("该位置已被扫过,请重新输入!\n"); Sleep(1500); continue; } if (mineboard[x][y] == '1') { if (flag == 1) { mineboard[x][y] = '0'; mineboard[x0][y0] = '1'; flag = 0; }//用户踩到雷了,如果是第一次,就与x0,y0坐标进行交换。 else { printf("很遗憾,你输了!\n"); Sleep(1500); printf("雷达:(1代表有雷,0代表没雷)\n"); Sleep(1500); show(mineboard);//游戏结束,输出埋雷棋盘,让用户明白输在哪里。 break; } } open(mineboard, sweepboard, x, y);//若没有踩到雷,调用open函数,判定是否需要展开。 if (judge(sweepboard) == 1) { //调用judge函数,判定是否扫雷成功。 printf("恭喜你,扫雷成功!\n"); break; } flag = 0;//用户第一次扫完,不在有第一次不可能踩中雷的保护。 } }
void setmine(char mineboard[][COL],int * x, int * y )//setmine函数,开始埋雷。 { int times = MINENUM;//循环执行次数,即雷的个数。 srand((unsigned long)time(NULL)); while (times) { int x = rand() % (ROW - 2) + 1; int y = rand() % (COL - 2) + 1; if (mineboard[x][y] != '1') { mineboard[x][y] = '1'; times--; } } while (1) { *x = rand() % (ROW - 2) + 1; *y = rand() % (COL - 2) + 1; if (mineboard[*x][*y] == '0') { break; } }//在埋雷棋盘中找到一个随机非雷坐标。 }
void show(char board[][COL])//show函数,展示棋盘。 { int i = 1; int j = 0; printf(" ");//调整列标位置。 for (; i < 11; i++) { printf("%d ", i);//输出列标。 } printf("\n"); for (i = 1; i < 11; i++) { printf(" ----------------------------------------\n");//输出每一行之间分割线。 printf("%2d|", i);//输出行标。 for (j = 1; j < 11; j++) { printf(" %c |", board[i][j]);//输出棋盘元素。 } printf("\n"); } printf(" ----------------------------------------\n");//输出最后一行分割线。 }
int minecount(char mineboard[][COL], int x, int y)//minecount函数,统计该坐标周围雷的个数。
{
int c = mineboard[x - 1][y - 1] + mineboard[x - 1][y] + mineboard[x - 1][y + 1] +\
mineboard[x][y - 1] + mineboard[x][y + 1] + mineboard[x + 1][y - 1] +\
mineboard[x + 1][y] + mineboard[x + 1][y + 1] - 8 * '0';//棋盘是字符型的,把该坐标周围8个坐标里的字符加起来
//再减去8 * '0',计算时用的是acsii值,所得结果就是雷的个数。
return c;
}
void open(char mineboard[][COL], char sweepboard[][COL], int x, int y)//open函数,判断是否需要递归式展开。 { if (!minecount(mineboard, x, y))//调用minecount函数,计算周围雷的个数,若为0,则需要展开。 { sweepboard[x][y] = ' '; int i = 0; int j = 0; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++) { if (sweepboard[i][j] == '*' &&\ i > 0 && i < 11 && j > 0 && j < 11)//若该位置未被扫过且在棋盘范围内则继续递归调用open函数。 open(mineboard, sweepboard, i, j); } } } else { sweepboard[x][y] = minecount(mineboard, x, y) + '0';//若不需要展开,则为该位置赋值周围雷的个数, //棋盘是字符型的,需要加'0'才是对应数字的字符。 } }
int judge(char sweepboard[][COL]) //judge函数,判定用户是否扫雷成功。 { int i = 1; int j = 1; int count = 0; for (; i <= ROW - 2; i++) { for (j = 1; j <= COL - 2; j++) { if (sweepboard[i][j] == '*') { count++; }//遍历棋盘元素,若该位置未被扫过,则记录下来。 if (count > MINENUM) { return 0; }//若未被扫过的个数大于雷的个数,则游戏继续。 } } return 1; }
还是多动手吧,写的过程中好多小错误。如循环时不记得给循环变量赋值。还有就是这个程序还可以优化一下,比如做成闯关模式,或者让用户自己选择棋盘大小和雷的个数。应该会很有意思。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。