扫雷游戏
程序员文章站
2024-03-16 22:53:22
...
一.题目分析
扫雷游戏的具体实现思路:
写这一模块时应该注重梳理,应该一步步写,如:绘制界面 --> 显示界面 --> 初始化盘 --> 检测雷周围的数字 --> 打印数字(0或其他)--> 标记雷 --> 扩展功能
二.程序
头文件:game.h
#ifndef _GAME_H_
#define _GAME_H_
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 10
#define COL 10
void ShowaBoard (char panel[ROW][COL]);
void InitBoard (int num, char panel[ROW][COL], char panel2[ROW][COL]);
void FillNumber(char panel[][COL]);
void ShowNum(char panel[][COL], int row, int col, char panel2[][COL]);
int Find(char panel[][COL], char panel2[][COL], int row, int col, int flag);
int MoveMine(char panel[][COL], char panel2[][COL],int row,int col);
#endif //_GAME_H_
游戏的具体实现:game.c
#include "game.h"
//输出横向坐标
void PrintX() {
int row = 0;
printf(" ");
for (row = 0; row < ROW; row++)
{
printf("%4d", row + 1);
}
printf("\n");
}
//输出横向框
void PrintH() {
int col = 0;
printf(" +");
for (col = 0; col < COL *2; col++)
{
if (!((col + 1) % 2)){
printf("+");
}
else {
printf("---");
}
}
printf("\n");
}
//显示盘
void ShowBoard(char panel[ROW][COL])
{
int row = 0, col = 0;
PrintX();
PrintH();
for (row = 0; row < ROW; row++)
{
printf("%2d ", row + 1); //输出竖向坐标
printf("| ");
for (col = 0; col < COL; col++)
{
printf("%c ", panel[row][col]);
printf("| ");
}
printf("%d\n", row +1); //输出竖向坐标
PrintH(); //横向框
}
PrintX();
}
//初始化盘
void InitBoard(int num, char panel[ROW][COL], char panel2[ROW][COL])
{
int i = 0;
int row = 0;
int col = 0;
for (row = 0; row < ROW; row++)
{
for (col = 0; col < COL; col++)
{
panel[row][col] = ' ';
panel2[row][col] = ' ';
}
}
for (i = 0; i < num; i++)
{
row = rand() % ROW;
col = rand() % COL;
if (panel[row][col] == '*')
{
i--;
}
else
{
panel[row][col] = '*';
}
}
}
//根据布置好的雷计算雷周围的数字
void FillNum(char panel[][COL])
{
//填充数字
int row = 0, col = 0;
for (row = 0; row < ROW; row++)
{
for (col = 0; col < COL; col++)
{
int count = 0;
//如果是雷,则不需要计算该位置周围的雷数
if (panel[row][col] == '*')
continue;
if ((row - 1) >= 0 && (col - 1) >= 0)
{
//检测左上角是否在盘内
if (panel[row - 1][col - 1] == '*')
count++; //检测到雷,则count加1
}
if ((row + 1) < ROW && (col - 1) >= 0)
{
//左下角
if (panel[row + 1][col - 1] == '*')
count++;
}
if ((row - 1) >= 0 && (col + 1) < COL)
{
//右上角
if (panel[row - 1][col + 1] == '*')
count++;
}
if ((row + 1) < ROW && (col + 1) < COL)
{
//右下角
if (panel[row + 1][col + 1] == '*')
count++;
}
if ((row - 1) >= 0)
{
//正上方
if (panel[row - 1][col] == '*')
count++;
}
if ((row + 1) < ROW)
{
//正下方
if (panel[row + 1][col] == '*')
count++;
}
if ((col - 1) >= 0)
{
//左边
if (panel[row][col - 1] == '*')
count++;
}
if ((col + 1) < COL)
{
//右边
if (panel[row][col + 1] == '*')
count++;
}
panel[row][col] = '0' + count; //将计算出的周围的雷数整型转换成字符型
}
}
}
//点到0,显示多个数字
void ShowNum(char panel[][COL], int row, int col, char panel2[][COL])
{
panel2[row][col] = panel[row][col]; //显示数字
//检测相邻点是否超出棋盘 若相邻点为0且没有雷则以该点为中心继续显示
//正上方
if ((row - 1) >= 0)
{
if (panel[row - 1][col] == '0' && panel2[row - 1][col] == ' ')
ShowNum(panel, row - 1, col, panel2);
else
panel2[row - 1][col] = panel[row - 1][col];
}
//正下方
if ((row + 1) < ROW)
{
if (panel[row + 1][col] == '0' && panel2[row + 1][col] == ' ')
ShowNum(panel, row + 1, col, panel2);
else
panel2[row + 1][col] = panel[row + 1][col];
}
//左边
if ((col - 1) >= 0)
{
if (panel[row][col - 1] == '0' && panel2[row][col - 1] == ' ')
ShowNum(panel, row, col - 1, panel2);
else
panel2[row][col - 1] = panel[row][col - 1];
}
//右边
if ((col + 1) < COL)
{
if (panel[row][col + 1] == '0' && panel2[row][col + 1])
ShowNum(panel, row, col + 1, panel2);
else panel2[row][col + 1] = panel[row][col + 1];
}
//左上角
if ((row - 1) >= 0 && (col - 1) >= 0)
{
if (panel[row - 1][col - 1] == '0' && panel2[row - 1][col - 1] == ' ')
ShowNum(panel, row - 1, col - 1, panel2);
else
panel2[row - 1][col - 1] = panel[row - 1][col - 1];
}
//左下角
if ((row + 1) < ROW && (col - 1) >= 0)
{
if (panel[row + 1][col - 1] == '0' && panel2[row + 1][col - 1] == ' ')
ShowNum(panel, row + 1, col - 1, panel2);
else panel2[row + 1][col - 1] = panel[row + 1][col - 1];
}
//右上角
if ((row - 1) >= 0 && (col + 1) < COL)
{
if (panel[row - 1][col + 1] == '0' && panel2[row - 1][col + 1] == ' ')
ShowNum(panel, row - 1, col + 1, panel2);
else panel2[row - 1][col + 1] = panel[row - 1][col + 1];
}
//右下角
if ((row + 1) < ROW && (col + 1) < ROW)
{
if (panel[row + 1][col + 1] == '0' && panel2[row + 1][col + 1] == ' ')
ShowNum(panel, row + 1, col + 1, panel2);
else
panel2[row + 1][col + 1] = panel[row + 1][col + 1];
}
}
//找雷
int Find(char panel[][COL], char panel2[][COL],int row, int col, int flag)
{
if (flag == 1)
{
//标记可能是雷的位置
//是雷返回 1 不是返回 0
panel2[row][col] = 'F'; //如果是雷标记‘F'
if (panel[row][col] == '*')
{
return 1;
}
else
{
return 0;
}
}
else
{
//猜测不是雷
if (panel[row][col] == '*')
{
//点到雷,游戏失败
return 2;
}
else if (panel[row][col] == '0')
{
//点击到0,显示多个数字
ShowNum(panel, row, col, panel2);
return 0;
}
else
{
panel2[row][col] = panel[row][col]; //显示数字
return 0;
}
}
}
//防止第一次踩雷
int MoveMine(char panel[][COL], char panel2[][COL], int row, int col)
{
int row2 = 0;
int col2 = 0;
//找到没有雷的位置与输入位置交换
for (row2 = 0; row2 < ROW; row++)
{
for (col2 = 0; col2 < COL; col++)
{
int tmp = 0;
if (panel[row2][col2] == '*')
continue;
else
{
//将雷移走
tmp = panel[row][col];
panel[row][col] = panel[row2][col2];
panel[row2][col2] = tmp;
//更新
FillNum(panel);
//ShowBoard(panel);
panel2[row][col] = panel[row][col];
return panel2[row][col];
}
}
}
}
三.总结感悟
最初不能实现使第一次不会踩到雷的功能,后经借鉴代码,通过位置交换实现了此功能。
下一篇: 16进制和字符串的相互转换