c语言实现小游戏-扫雷
程序员文章站
2022-04-07 14:32:53
...
扫雷大家都玩过吧,没玩过的可以在自己电脑上玩一下,我实现在这个扫雷不像电脑上那种是直接用鼠标点,而是自己输入坐标来排雷。
头文件game.h
#ifndef _GAME_H_
#define _GAME_H_//这两句以及下面的#endif//_GAME_H_是为了防止头文件重复被多次编译
#include<stdio.h>
#include<windows.h>
#include<time.h>
#include <stdlib.h>
#define ROW 10
#define COL 10
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 10 //雷的个数
enum
{
Exit,
Game
};
void DisPlayBoard(char board[ROWS][COLS],int row,int col);//打印棋盘
void InitBoard(char board[ROWS][COLS],int row,int col,char set);//初始化棋盘
void SetMine(char mine[ROWS][COLS], int count, int row, int col);//放雷函数
int GetMineCount(char mine[ROWS][COLS], int x, int y);//统计周围雷的个数
void ExpandMine(char mine[ROWS][COLS],char show[ROWS][COLS],int x,int y,int *num);//展开无雷区
void SignMine(char show[ROWS][COLS], int x, int y);//标记雷
void UnsignMine(char show[ROWS][COLS], int x, int y);//取消标记
#endif//_GAME_H_
源文件game.c
#include"game.h"
void InitBoard(char board[ROWS][COLS], int row, int col,char set)//初始化棋盘
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;//初始化的字符
}
}
}
void DisPlayBoard(char board[ROWS][COLS], int row, int col)//打印棋盘
{
system("cls");
printf(" 排雷棋盘图\n");
int i = 0;
int j = 0;
printf(" ");
for (j = 1; j <= col; j++)//打印列坐标
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%2d ", i);//打印行坐标
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
void SetMine(char mine[ROWS][COLS], int count, int row, int col)//布雷
{
int x = 0;
int y = 0;
while (count)//count为所布置的雷数
{
x = rand() % row + 1;//随机生成1~10内坐标
y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)//统计周围雷的个数
{
return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] +
mine[x][y - 1] + mine[x][y + 1] +
mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0';
//四周围八个字符相加,减去8*'0'让字符变为整型返回
}
void ExpandMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int *num)//展开雷区
{
int i = 0;
int j = 0;
if (show[x][y] == '*')//表示此处没有排过,可以排雷
{
(*num)++;
int count = GetMineCount(mine, x, y);
if (count != 0)//周围有雷,不能扩展
{
show[x][y] = count + '0';//做标记记录周围雷数,表示该处排过
}
else
{
show[x][y] = '0';//该位置显示为字符0,并开始扩展
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
if (x + i >= 1 && x + i <= ROW && y + j >= 1 && y + j <= COL)
{
if (i != 0 || j != 0)//排除自身坐标
{
ExpandMine(mine, show, x + i, y + j, num);//开始递归展开
}
}
}
}
}
}
}
void SignMine(char show[ROWS][COLS], int x, int y)//标记雷
{
if (show[x][y] == '*')
{
show[x][y] = '#';
}
}
void UnsignMine(char show[ROWS][COLS], int x, int y)//取消标记
{
if (show[x][y] == '#')
{
show[x][y] = '*';
}
}
测试文件:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu1()
{
printf("*******************************\n");
printf("**** 1.新游戏 0.退出 ****\n");
printf("*******************************\n");
}
void menu2()
{
printf("***********************************\n");
printf("**** 0.返回上层 1.继续排雷 ****\n");
printf("**** 2.标记 3.取消标记 ****\n");
printf("***********************************\n");
}
void game()
{
int x = 0;
int y = 0;
int win = 0;
char show[ROWS][COLS] = { 0 };//显示数组//需要两个数组,即两个棋盘,一个布雷用,一个显示排雷用
char mine[ROWS][COLS] = { 0 };//布雷数组
InitBoard(show, ROWS, COLS,'*');//初始化排雷结果棋盘
InitBoard(mine, ROWS, COLS, '0');//排雷显示棋盘
SetMine(mine, EASY_COUNT, ROW, COL);//布雷函数
DisPlayBoard(show, ROW, COL);//打印函数
while (win < (ROW*COL-EASY_COUNT))//终止条件:当排雷次数>=棋盘大小减去雷数时,排雷成功
{
int n = 0;
DisPlayBoard(show, ROW, COL);
menu2();
printf("请选择->");
scanf("%d", &n);
fflush(stdin);//清空输入缓冲区,为了确保不影响后面的数据读取
if (n == 1)
{
printf("请输入坐标->");
scanf("%d%d", &x, &y);
fflush(stdin);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (mine[x][y] == '1')
{
if (win == 0)//第一次就踩到雷,保证不死,增加游戏可玩性
{
printf(" 哇,第一次你就踩着雷了,看你天赋异禀,老夫给你把雷换了\n");
Sleep(2000);
mine[x][y] = '0';
SetMine(mine, 1, ROW, COL);//重新布一个雷
ExpandMine(mine, show, x, y, &win);
}
else//不是第一次踩雷
{
printf("你被炸死了,继续修炼扫雷秘籍吧\n");
DisPlayBoard(mine, ROW, COL);
return;
}
}
else
{
ExpandMine(mine, show, x, y, &win);
}
}
else
{
printf("输入坐标不合法,请重新输入\n");
}
}
else if (2 == n)//标记
{
printf("请输入坐标->");
scanf("%d%d", &x, &y);
SignMine(show, x, y);
DisPlayBoard(show, ROW, COL);
}
else if (3 == n)//取消标记
{
printf("请输入坐标->");
scanf("%d%d", &x, &y);
UnsignMine(show, x, y);
DisPlayBoard(show, ROW, COL);
}
else if (0 == n)
{
return;
}
else
{
printf("输入错误,请重新输入\n");
continue;
}
}
if (win >= (ROW*COL - EASY_COUNT))
{
DisPlayBoard(mine, ROW, COL);//显示雷函数
printf("恭喜你,排雷成功\n");
}
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do{
system("cls");
menu1();
printf("请选择->");
scanf("%d", &input);
switch (input)
{
case Game:
game();
break;
case Exit:
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
system("pause");
return 0;
}
测试一下结果: