C语言实现扫雷小游戏
2018-09-20 21:11
681 查看
扫雷游戏也算是一个简单的小项目,这儿是之前写的代码,来写成博文回顾一下。首先,代码要实现几个功能:
- 第一下扫雷时,即使踩中了雷也不能直接炸死;
- 扫雷时,坐标周围没有雷的地方可以实现展开;
- 统计展开的地方边缘处可能存在的雷的个数;
- 每次进入游戏,雷分布的地方都是随机的。
1.效果图
1)、程序总的构架:
2)、设计两个棋盘,一个是置放雷的棋盘,在测试中可以查看雷分布在哪些地方,不打印,如果玩家最终失败或者取得胜利,可以打印出来给玩家展示雷的分布。一个是展示给玩家的棋盘,打印,且会不断更新。
3)、游戏效果:
2.菜单
[code]// 菜单 menu() { printf("*******************************\n"); printf("**** 欢迎来到扫雷游戏! ****\n"); printf("**** 1.进入游戏 ****\n"); printf("**** 0.退出游戏 ****\n"); printf("*******************************\n"); }
3.初始化棋盘
把棋盘初始化为0:
[code]//初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { memset(board, set, rows*cols*sizeof(board[0][0])); }
4.打印棋盘
棋盘的打印要用到二维数组的知识,这里会涉及到数组越界的问题,比如我们如果要打印 (10 x 10)的棋盘,我们在设计算法时需要统计周围 8 个方位的雷的个数,那么在统计边界周围雷的个数时就产生了数组越界的问题。为了解决这个问题,在棋盘周围多加一圈,即是如果是10x10,就变成了12x12,多出来的已全部打印出来。
[code]//打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf(" "); for (i = 0; i < row; i++) { printf(" %d ", i + 1); } printf("\n"); for (j = 0; j < col+1; j++) { printf("---|"); } printf("\n"); for (i = 0; i < row; i++) { printf(" %d |", i + 1); for (j = 0; j < col; j++) { printf(" %c |", board[i][j]); } printf("\n"); printf(" |", i + 1); for (j = 0; j < col; j++) { printf("---|"); } printf("\n"); } printf("\n"); }
5.在棋盘上布雷
利用函数 strand() 函数和 rand() 函数在棋盘上随机地方布置雷,有雷的地方标记为 1 ,没有雷的地方标记为 0。
[code]//布置雷 void ScMinc(char board[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = EASY_COUNT; while (count) { x = rand() % 9 + 1; y = rand() % 9 + 1; if (board[x][y] == '0') { board[x][y] = '1'; count--; } } }
6.一次展开周围无雷的地方
扫雷时,坐标周围没有雷的地方展开,并统计展开的地方边缘处可能存在的雷的个数。
先设计一个函数 GetMineCount()用来统计雷周围雷的的数,如果为 0,则排除这个区域即置为 ‘ ’ ,并递归周围的 8 个位置,如果还出现为 0 的情况则继续递归,递归完成后打印展开的地方边缘处可能存在的雷的个数。
[code]//统计周围雷的个数 static int GetMineCount(char mine[ROWS][COLS],int x,int y) { return mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0'; } //用递归排除周围没有雷的区域 static void NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { int ret = GetMineCount(mine, x, y); if (ret == 0) { show[x][y] = ' '; if ((x-1)>0 && (y-1)>0 && (show[x-1][y-1] == '*')) NoMine(mine, show, x - 1, y - 1); if ((x - 1)>0 && (y)>0 && (show[x - 1][y] == '*')) NoMine(mine, show, x - 1, y); if ((x - 1)>0 && (y + 1)>0 && (show[x - 1][y + 1] == '*')) NoMine(mine, show, x - 1, y + 1); if ((x)>0 && (y - 1)>0 && (show[x][y - 1] == '*')) NoMine(mine, show, x, y - 1); if ((x)>0 && (y + 1)>0 && (show[x][y + 1] == '*')) NoMine(mine, show, x, y + 1); if ((x + 1)>0 && (y - 1)>0 && (show[x + 1][y - 1] == '*')) NoMine(mine, show, x + 1, y - 1); if ((x + 1)>0 && (y)>0 && (show[x + 1][y] == '*')) NoMine(mine, show, x + 1, y); if ((x + 1)>0 && (y + 1)>0 && (show[x + 1][y + 1] == '*')) NoMine(mine, show, x + 1, y + 1); } else show[x][y] = ret + '0'; }
7.排雷
在排雷过程中,用一个循环,如果踩中的不是雷,用 win 来统计非雷个数 ,如果踩中雷,立即炸死,结束循环。在循环结束后,如果非雷个数 win 正好等于使用的棋盘区域个数减去雷的个数的值,则成功排雷。
[code]//排雷 void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0; //统计不是雷的个数 int ret = 0; //统计周围雷的个数 while (win < ROW*COL - EASY_COUNT) { int select = 0; system("CLS"); //清屏,优化界面 DisplayBoard(show, ROW, COL); printf("----- 1.扫雷 --- 2.标记雷 -----\n"); printf("请选择:>"); scanf("%d", &select); if (select == 1) { printf("请输入要排查的坐标:>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x-1][y-1] == '0' && show[x-1][y-1] == '*') { NoMine(mine, show, x-1, y-1); DisplayBoard(show, ROW, COL); win = win + 8; } if (mine[x-1][y-1] == '1' && show[x-1][y-1] == '*') { show[x-1][y-1] = 'S'; DisplayBoard(show, ROW, COL); printf("很遗憾,你被炸死了\n\n"); DisplayBoard(mine, row, col); break; } } else { printf("坐标非法\n"); } } if (select == 2) { printf("请输入要标记雷的坐标:>"); scanf("%d %d", &x, &y); if (show[x-1][y-1] == '*') { show[x-1][y-1] = '@'; //用于玩家标记已经确定的雷 DisplayBoard(show, ROW, COL); } else { printf("坐标非法\n"); } } } //只剩下有雷的区域(EASY_COUNT:雷的总个数) if (win = ROW*COL - EASY_COUNT) { printf("恭喜你,排雷成功!\n"); DisplayBoard(mine, row, col); } }
8.游戏执行
[code]void game() { char mine[ROWS][COLS] = { 0 }; //置放雷的棋盘 char show[ROWS][COLS] = { 0 }; //展示给玩家的棋盘 InitBoard(mine, ROWS, COLS,'0'); InitBoard(show, ROWS, COLS, '*'); ScMinc(mine, ROW, COL); //置雷 DisplayBoard(mine, ROW, COL); DisplayBoard(show, ROW, COL); FindMind(mine, show, ROW, COL);//排雷 } void test() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("输入错误\n"); } } while (input); } int main() { test(); return 0; }
9.头文件
[code]#ifndef __GAME_H__ #define __GAME_H__ # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); void DisplayBoard(char board[ROWS][COLS], int row, int col); void ScMinc(char board[ROWS][COLS], int row, int col); void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); char FistStep(char mine[ROWS][COLS], int row, int col, int x, int y); #endif __GAME_H__
10.附:game.c 的源码
[code]#include "game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { memset(board, set, rows*cols*sizeof(board[0][0])); } //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf(" "); for (i = 0; i < row; i++) { printf(" %d ", i + 1); } printf("\n"); for (j = 0; j < col+1; j++) { printf("---|"); } printf("\n"); for (i = 0; i < row; i++) { printf(" %d |", i + 1); for (j = 0; j < col; j++) { printf(" %c |", board[i][j]); } printf("\n"); printf(" |", i + 1); for (j = 0; j < col; j++) { printf("---|"); } printf("\n"); } printf("\n"); } //布置雷 void ScMinc(char board[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = EASY_COUNT; while (count) { x = rand() % 9 + 1; y = rand() % 9 + 1; if (board[x][y] == '0') { board[x][y] = '1'; count--; } } } //统计周围雷的个数 static int GetMineCount(char mine[ROWS][COLS],int x,int y) { return mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0'; } //用递归排除周围没有雷的区域 static void NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { int ret = GetMineCount(mine, x, y); if (ret == 0) { show[x][y] = ' '; if ((x-1)>0 && (y-1)>0 && (show[x-1][y-1] == '*')) NoMine(mine, show, x - 1, y - 1); if ((x - 1)>0 && (y)>0 && (show[x - 1][y] == '*')) NoMine(mine, show, x - 1, y); if ((x - 1)>0 && (y + 1)>0 && (show[x - 1][y + 1] == '*')) NoMine(mine, show, x - 1, y + 1); if ((x)>0 && (y - 1)>0 && (show[x][y - 1] == '*')) NoMine(mine, show, x, y - 1); if ((x)>0 && (y + 1)>0 && (show[x][y + 1] == '*')) NoMine(mine, show, x, y + 1); if ((x + 1)>0 && (y - 1)>0 && (show[x + 1][y - 1] == '*')) NoMine(mine, show, x + 1, y - 1); if ((x + 1)>0 && (y)>0 && (show[x + 1][y] == '*')) NoMine(mine, show, x + 1, y); if ((x + 1)>0 && (y + 1)>0 && (show[x + 1][y + 1] == '*')) NoMine(mine, show, x + 1, y + 1); } else show[x][y] = ret + '0'; } //排雷 void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0; //统计不是雷的坐标数 int ret = 0; //统计周围雷的个数 while (win < ROW*COL - EASY_COUNT) { int select = 0; //system("CLS"); //清屏,优化界面 DisplayBoard(show, ROW, COL); printf("----- 1.扫雷 --- 2.标记雷 -----\n"); printf("请选择:>"); scanf("%d", &select); 20000 if (select == 1) { printf("请输入要排查的坐标:>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x-1][y-1] == '0' && show[x-1][y-1] == '*') { NoMine(mine, show, x-1, y-1); DisplayBoard(show, ROW, COL); win = win + 8; } if (mine[x-1][y-1] == '1' && show[x-1][y-1] == '*') { show[x-1][y-1] = 'S'; DisplayBoard(show, ROW, COL); printf("很遗憾,你被炸死了\n\n"); DisplayBoard(mine, row, col); break; } } else { printf("坐标非法\n"); } } if (select == 2) { printf("请输入要标记雷的坐标:>"); scanf("%d %d", &x, &y); if (show[x-1][y-1] == '*') { show[x-1][y-1] = '@'; //用于玩家标记已经确定的雷 DisplayBoard(show, ROW, COL); } else { printf("坐标非法\n"); } } } if (win > ROW*COL - EASY_COUNT) { printf("恭喜你,排雷成功!\n"); DisplayBoard(mine, row, col); } }
阅读更多
相关文章推荐
- C语言实现小游戏--扫雷
- 小游戏---扫雷(C语言实现)
- 用c语言实现经典小游戏———扫雷
- c语言实现小游戏-扫雷
- 小项目 : C语言实现扫雷小游戏
- [置顶] 小游戏:扫雷 (C语言实现扫雷的基本功能)
- 【扫雷】编写一个小游戏--扫雷的c语言实现
- 小游戏三子棋的C语言代码实现
- 用C语言实现扫雷小程序
- 简单小游戏-剪刀石头布的c语言实现
- C语言二维数组实现扫雷游戏
- C语言实现简易版扫雷游戏
- 简单c语言小游戏实现原理
- C语言实现的一个简单的猜数小游戏
- 一步一步实现扫雷游戏(C语言实现)(一)
- c语言小程序之三子棋小游戏的实现
- 用C语言实现简单的三子棋小游戏
- C语言*扫雷实现
- 扫雷游戏(C语言实现)
- C语言实现扫雷。可以标记。