ss
整体思路
设计一个可以通过坐标一直玩的扫雷游戏,并且一把游戏结束后,可以通过输入0结束游戏退出。该代码可以处理无效输入。
具体步骤
目录
一、打印目录
二、初始化棋盘
三、打印棋盘
四、布置雷
五、排查雷
一、打印菜单
选择进入游戏或者退出游戏
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu1()
{
printf("************************************\n");
printf("******** 1. play *********\n");
printf("******** 0. exit *********\n");
printf("************************************\n");
}
void game()
{
//1. 需要存放布置好的雷的信息,存放排查出的雷的信息,我们需要2个二维数组
//2. 排查坐标的时候,为了防止坐标越界,我们给数组的行增加2行,列增加了2列
char mine[ROWS][COLS] = { 0 };//布置好的雷的信息
char show[ROWS][COLS] = { 0 };//排查出的雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
void test()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu1();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
二、初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
三、打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("---------扫雷----------\n");
//控制列号
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("---------扫雷----------\n");
}
四、布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
//1. 生成随机下标
int x = rand() % row + 1;
int y = rand() % col + 1;
//2. 布置雷
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
五、排查雷
void menu2()
{
printf("************************************\n");
printf("******* 输入 '1' 或 '2' ***********\n");
printf("************ 1.排除雷 **************\n");
printf("************ 2.标记雷 **************\n");
printf("************ 3.撤销标记雷 **********\n");
printf("************************************\n");
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int k = 0;
int l = 0;
int win = 0;
int input = 0;
while (win < (row * col - EASY_COUNT))
{
menu2();
scanf("%d",&input);
switch(input)
{
case 1:
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if(win==0 and mine[x][y]=='1') //防止第一次被炸死
{
mine[x][y] = '0';
while(1)
{
k = rand()%row + 1;
l = rand()%col + 1;
if(mine[k][l] == '0')
{
mine[k][l] = '1';
break;
}
}
}
if (show[x][y] == 'X')
{
printf("该坐标被标记过了\n");
continue;
}
if (show[x][y] != '*')
{
printf("该坐标被排查过了\n");
continue;
}
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
//int n = get_mine_count(mine, x, y);
//show[x][y] = n + '0';
Open_up(mine, show, row, col, x, y);
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("坐标非法,重新输入\n");
}
break;
case 2:
while(1)
{
printf("请输入要标记的坐标:>\n");
scanf("%d %d", &x, &y);
if(show[x][y]=='*')
{
show[x][y]='X';
DisplayBoard(show, ROW, COL);
break;
}
printf("坐标非法,重新输入\n");
}
break;
case 3:
while(1)
{
printf("请输入要撤销标记的坐标:>\n");
scanf("%d %d", &x, &y);
if(show[x][y]=='X')
{
show[x][y]='*';
DisplayBoard(show, ROW, COL);
break;
}
printf("坐标非法,重新输入\n");
}
default:
printf("选择错误,重新选择!\n");
break;
}
if (is_win(mine, show, ROW, COL) == true)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
}
bool is_win(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col)
{
bool ret = true;
for(int i = 1;i <= row;i++)
{
for(int j = 1;j <= col;j++)
{
if(show[i][j] == 'X' and mine[i][j] !='1')
{
ret = false;
}
}
}
return ret;
}
六、递归展开雷
void Open_up( char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)//周围无雷时展开一片
{
int ret = 0;
ret = get_mine_count(mine, x, y);
if(ret == 0)
{
show[x][y] = '0';
if(x - 1>0 && y>0 && show[x - 1][y] == '*') //左上
Open_up(mine, show, row, col, x - 1, y);
if(x - 1>0 && y + 1 <= col && show[x - 1][y + 1] == '*')//正上
Open_up(mine, show, row, col, x - 1, y + 1);
if(x - 1>0 && y - 1>0 && show[x - 1][y - 1] == '*')//右上
Open_up(mine, show, row, col, x - 1, y - 1);
if(x>0 && y + 1 <= col && show[x][y + 1] == '*')//左
Open_up(mine, show, row, col, x, y + 1);
if(x>0 && y - 1>0 && show[x][y - 1] == '*')//右
Open_up(mine, show, row, col, x, y - 1);
if(x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == '*')//右下角
Open_up(mine, show, row, col, x + 1, y + 1);
if(x + 1 <= row && y>0 && show[x + 1][y] == '*')//下
Open_up(mine, show, row, col, x + 1, y);
if(x + 1 <= row && y - 1>0 && show[x + 1][y - 1] == '*')//左下角
Open_up(mine, show, row, col, x + 1, y - 1);
}
else
{
show[x][y] = get_mine_count(mine, x, y) + '0';
}
}
七、头文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.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 SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//展开扫雷
void Open_up( char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y);
//判断是否获胜
bool is_win(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col);
八、扫雷总代码
#include <stdio.h>
#include <stdlib.h>
#include <time.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 SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//展开扫雷
void Open_up( char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y);
//判断是否获胜
bool is_win(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col);
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
//1. 生成随机下标
int x = rand() % row + 1;
int y = rand() % col + 1;
//2. 布置雷
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int get_mine_count(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');
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("---------扫雷----------\n");
//控制列号
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("---------扫雷----------\n");
}
void mine1()
{
printf("************************************\n");
printf("******** 1. play *********\n");
printf("******** 0. exit *********\n");
printf("************************************\n");
}
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void game()
{
//1. 需要存放布置好的雷的信息,存放排查出的雷的信息,我们需要2个二维数组
//2. 排查坐标的时候,为了防止坐标越界,我们给数组的行增加2行,列增加了2列
char mine[ROWS][COLS] = { 0 };//布置好的雷的信息
char show[ROWS][COLS] = { 0 };//排查出的雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
void test()
{
srand((unsigned int)time(NULL));
int input;
do
{
mine1();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("进入游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
void menu2()
{
printf("************************************\n");
printf("******* 输入 '1' 或 '2' ***********\n");
printf("************ 1.排除雷 **************\n");
printf("************ 2.标记雷 **************\n");
printf("************ 3.撤销标记雷 **********\n");
printf("************************************\n");
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int k = 0;
int l = 0;
int win = 0;
int input = 0;
while (win < (row * col - EASY_COUNT))
{
menu2();
scanf("%d",&input);
switch(input)
{
case 1:
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if(win==0 and mine[x][y]=='1') //防止第一次被炸死
{
mine[x][y] = '0';
while(1)
{
k = rand()%row + 1;
l = rand()%col + 1;
if(mine[k][l] == '0')
{
mine[k][l] = '1';
break;
}
}
}
if (show[x][y] == 'X')
{
printf("该坐标被标记过了\n");
continue;
}
if (show[x][y] != '*')
{
printf("该坐标被排查过了\n");
continue;
}
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int n = get_mine_count(mine, x, y);
show[x][y] = n + '0';
Open_up(mine, show, row, col, x, y);
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("坐标非法,重新输入\n");
}
break;
case 2:
while(1)
{
printf("请输入要标记的坐标:>\n");
scanf("%d %d", &x, &y);
if(show[x][y]=='*')
{
show[x][y]='X';
DisplayBoard(show, ROW, COL);
break;
}
printf("坐标非法,重新输入\n");
}
break;
case 3:
while(1)
{
printf("请输入要撤销标记的坐标:>\n");
scanf("%d %d", &x, &y);
if(show[x][y]=='X')
{
show[x][y]='*';
DisplayBoard(show, ROW, COL);
break;
}
printf("坐标非法,重新输入\n");
}
default:
printf("选择错误,重新选择!\n");
break;
}
if (is_win(mine, show, ROW, COL) == true)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
}
bool is_win(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col)
{
bool ret = true;
for(int i = 1;i <= row;i++)
{
for(int j = 1;j <= col;j++)
{
if(show[i][j] == 'X' and mine[i][j] !='1')
{
ret = false;
}
}
}
return ret;
}
void Open_up( char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)//周围无雷时展开一片
{
int ret = 0;
ret = get_mine_count(mine, x, y);
if(ret == 0)
{
show[x][y] = '0';
if(x - 1>0 && y>0 && show[x - 1][y] == '*')
Open_up(mine, show, row, col, x - 1, y);
if(x - 1>0 && y + 1 <= col && show[x - 1][y + 1] == '*')
Open_up(mine, show, row, col, x - 1, y + 1);
if(x>0 && y + 1 <= col && show[x][y + 1] == '*')
Open_up(mine, show, row, col, x, y + 1);
if(x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == '*')
Open_up(mine, show, row, col, x + 1, y + 1);
if(x + 1 <= row && y>0 && show[x + 1][y] == '*')
Open_up(mine, show, row, col, x + 1, y);
if(x + 1 <= row && y - 1>0 && show[x + 1][y - 1] == '*')
Open_up(mine, show, row, col, x + 1, y - 1);
if(x>0 && y - 1>0 && show[x][y - 1] == '*')
Open_up(mine, show, row, col, x, y - 1);
if(x - 1>0 && y - 1>0 && show[x - 1][y - 1] == '*')
Open_up(mine, show, row, col, x - 1, y - 1);
}
else
{
show[x][y] = get_mine_count(mine, x, y) + '0';
}
}