前言
本文章主要介绍扫雷游戏的代码实现,能实现大部分功能。
一、函数库的引用
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
二、函数及其功能介绍
1.meau() // 菜单
void meau()
{
printf("***************************\n");
printf("***************************\n");
printf("********* 1.play **********\n");
printf("********* 0.exit **********\n");
printf("***************************\n");
printf("***************************\n");
}
2.Initboard() // 初始化棋盘
void Initboard(char board[ROWS][COLS], int rows, int cols, char ch)
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
board[i][j] = ch;
}
}
}
其中,代码中有两个棋盘,一个用于看雷的位置,一个用于给玩家看
第一个全部初始化为0,有雷的位置设为1,第二个全部设为*。
3.Displayboard() // 打印棋盘
void Displayboard(char board[ROWS][COLS], int row, int col)
{
printf("-------------------\n");
for (int k = 0; k <= col; k++) {
printf("%d ", k);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j = 1; j <= col; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("-------------------\n");
}
4. Setboard() // 随机设雷
void Setboard(char board[ROWS][COLS], int row, int col)
{
int x,y;
int count = 0;
while (count < COUNT) {
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0') {
board[x][y] = '1';
count++;
}
}
}
5.get_mine_count() // 计算落子位置周围雷的个数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return 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] + board[x - 1][y + 1] + board[x - 1][y] - 8 * '0';
}
6.Fun() // 计算周围棋子的周围雷的个数,直到周围存在雷
void Fun(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{
int count;
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (show[x][y] != '*' && show[x][y] != '#') {
return;
}
else if (mine[x - 1][y - 1] == '1' || mine[x][y - 1] == '1' || mine[x + 1][y - 1] == '1' || mine[x + 1][y] == '1' || mine[x + 1][y + 1] == '1' || mine[x][y + 1] == '1' || mine[x - 1][y + 1] == '1' || mine[x - 1][y] == '1') {
count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
return;
}
else
{
show[x][y] = '0';
Fun(mine, show, ROW, COL, x - 1, y - 1);
Fun(mine, show, ROW, COL, x, y - 1);
Fun(mine, show, ROW, COL, x + 1, y - 1);
Fun(mine, show, ROW, COL, x + 1, y);
Fun(mine, show, ROW, COL, x + 1, y + 1);
Fun(mine, show, ROW, COL, x, y + 1);
Fun(mine, show, ROW, COL, x - 1, y + 1);
Fun(mine, show, ROW, COL, x - 1, y);
}
}
}
7.PlayerMove() // 玩家移动的逻辑实现以及标记功能
void PlayerMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y,win=0,a,b;
char ch;
Displayboard(show, ROW, COL);
while (win < row*col-COUNT) {
while (1) {
printf("请输入你要下的位置:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
break;
}
else {
printf("你输入的坐标不规范,请重新输入!\n");
}
}
//判断游戏进行情况
if (mine[x][y] == '1') {
printf("你被炸死了,哈哈!\n");
Displayboard(mine, ROW, COL);
break;
}
else {
if (show[x][y] == '*' || show[x][y] == '#') {
Fun(mine, show, ROW, COL, x, y);
Displayboard(show, ROW, COL);
//标记功能
getchar();//吸取空格
while (1) {
printf("请选择是否进行标记(y/n):");
scanf("%c", &ch);
if (ch == 'y') {
printf("请选择标记的位置:");
scanf("%d %d", &a, &b);
show[a][b] = '#';
Displayboard(show, ROW, COL);
break;
}
else if (ch == 'n') {
break;
}
else {
printf("选择有误,请重新进行选择!\n");
}
}
}
else if(show[x][y] != '*' && show[x][y] != '#') {
printf("这个位置已经下过了/这个位置已经知道了\n");
}
}
}
if (win == row * col - COUNT)
printf("恭喜你,赢了!\n");
}
8.game() // 游戏的整体逻辑
void game()
{
//后台
char mine[ROWS][COLS] = { 0 };
//展示
char show[ROWS][COLS] = { 0 };
Initboard(mine, ROWS, COLS, '0');
Initboard(show, ROWS, COLS, '*');
Setboard(mine, ROW, COL);
//Displayboard(mine, ROW, COL);
PlayerMove(mine, show, ROW, COL);
}
三、全部代码
game.h
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
//ROWS COLS 在原有的基础上加2,将棋盘周围的空间初始化,防止出界判断
#define ROWS ROW+2
#define COLS COL+2
#define COUNT 20
void meau();
void game();
game.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//菜单
void meau()
{
printf("***************************\n");
printf("***************************\n");
printf("********* 1.play **********\n");
printf("********* 0.exit **********\n");
printf("***************************\n");
printf("***************************\n");
}
//初始化棋盘
void Initboard(char board[ROWS][COLS], int rows, int cols, char ch)
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
board[i][j] = ch;
}
}
}
//打印棋盘
void Displayboard(char board[ROWS][COLS], int row, int col)
{
printf("-------------------\n");
for (int k = 0; k <= col; k++) {
printf("%d ", k);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j = 1; j <= col; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("-------------------\n");
}
//随机设雷
void Setboard(char board[ROWS][COLS], int row, int col)
{
int x,y;
int count = 0;
while (count < COUNT) {
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0') {
board[x][y] = '1';
count++;
}
}
}
//这是判断落子位置周围雷的个数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return 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] + board[x - 1][y + 1] + board[x - 1][y] - 8 * '0';
}
//判断玩家落子的位置的周围位置的情况
//主要借助递归来实现判断
void Fun(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{
int count;
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (show[x][y] != '*' && show[x][y] != '#') {
return;
}
else if (mine[x - 1][y - 1] == '1' || mine[x][y - 1] == '1' || mine[x + 1][y - 1] == '1' || mine[x + 1][y] == '1' || mine[x + 1][y + 1] == '1' || mine[x][y + 1] == '1' || mine[x - 1][y + 1] == '1' || mine[x - 1][y] == '1') {
count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
return;
}
else
{
show[x][y] = '0';
Fun(mine, show, ROW, COL, x - 1, y - 1);
Fun(mine, show, ROW, COL, x, y - 1);
Fun(mine, show, ROW, COL, x + 1, y - 1);
Fun(mine, show, ROW, COL, x + 1, y);
Fun(mine, show, ROW, COL, x + 1, y + 1);
Fun(mine, show, ROW, COL, x, y + 1);
Fun(mine, show, ROW, COL, x - 1, y + 1);
Fun(mine, show, ROW, COL, x - 1, y);
}
}
}
//玩家移动
void PlayerMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y,win=0,a,b;
char ch;
Displayboard(show, ROW, COL);
while (win < row*col-COUNT) {
while (1) {
printf("请输入你要下的位置:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
break;
}
else {
printf("你输入的坐标不规范,请重新输入!\n");
}
}
//判断游戏进行情况
if (mine[x][y] == '1') {
printf("你被炸死了,哈哈!\n");
Displayboard(mine, ROW, COL);
break;
}
else {
if (show[x][y] == '*' || show[x][y] == '#') {
Fun(mine, show, ROW, COL, x, y);
Displayboard(show, ROW, COL);
//标记功能
getchar();//吸取空格
while (1) {
printf("请选择是否进行标记(y/n):");
scanf("%c", &ch);
if (ch == 'y') {
printf("请选择标记的位置:");
scanf("%d %d", &a, &b);
show[a][b] = '#';
Displayboard(show, ROW, COL);
break;
}
else if (ch == 'n') {
break;
}
else {
printf("选择有误,请重新进行选择!\n");
}
}
}
else if(show[x][y] != '*' && show[x][y] != '#') {
printf("这个位置已经下过了/这个位置已经知道了\n");
}
}
}
if (win == row * col - COUNT)
printf("恭喜你,赢了!\n");
}
//游戏的整体逻辑
void game()
{
//后台
char mine[ROWS][COLS] = { 0 };
//展示
char show[ROWS][COLS] = { 0 };
Initboard(mine, ROWS, COLS, '0');
Initboard(show, ROWS, COLS, '*');
Setboard(mine, ROW, COL);
//Displayboard(mine, ROW, COL);
PlayerMove(mine, show, ROW, COL);
}
test.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
int main()
{
int input;
do {
meau();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 0:
break;
case 1:
game();
break;
default:
printf("输入错误,请重新输入。\n");
}
} while (input);
return 0;
}
总结
整体来说比较简单,相对较难的主要是实现算出落子位置周围棋子及棋周围棋子的周围棋子的周围雷的个数,这个可以采用递归的方法来实现,递归结束的条件是周围存在雷。