初級 C 言語: 楽しいマインスイーパー ゲーム

目次

序文

 メニューを作る

ゲーム選択フレームワークの構築

ゲーム機能を実現する

モジュール式プログラミング: 3 つのチェスの前のセクションの内容を参照してください。

初期化地雷原

編集

ボードを最適化する

ランダムに埋められた地雷

クリック後の決定

 この関数コードを実装します

ゲーム(); アレンジメント


 

序文

「マインスイーパー」は1992年に発売された人気パズルゲームです。ゲームの目的は、グリッドをクリックすると表示される数字に従って、地雷ではないすべてのグリッドを最短時間で見つけ出し、同時に地雷を踏まないようにすることです。すべてを失うことになります。

プレイヤーは地雷原にあるすべての地雷を 1 つずつチェックする必要があります: 9x9 仕様

      test.c - - - - ゲームロジックをテストする

      game.c - - - - ゲームコードの実装

      game.h - - - - ゲームコードの宣言(関数宣言、シンボル定義)

 メニューを作る

  ゲームをプレイする場合、ゲームの開始、ゲームの起動、その他の指示を選択するときに、ゲームの開始時にメニュー オプションが表示されます。選択に関しては、まずループに基づいて基本的なフレームワークの設計を完了し、私たちが学んだ分岐ステートメント。

まず、ゲームに入ると、まず選択肢が表示され、選択をして、ゲームをプレイしながらプレイすることになりますが、プレイしたい場合はどうすればよいでしょうか(条件を満たす事前知識の構造を考える)最初にゲームに入ってからメニューをリサイクルする必要があります)) それは do...while のループ構造がより適切である必要があります。その場合は、最初に関数を使用してメニュー オプションを出力します

void menu()
{
	printf("*****************************\n");
	printf("*****************************\n");
	printf("**********1.play^************\n");
	printf("**********0.exit^************\n");//菜单
	printf("*****************************\n");
	printf("*****************************\n");
}
 
int main()
{int a = 0;
    do
 {
  menu();
  printf("请选择:");
  scanf("%d",&a);
 
 
 }while();  
return 0;
}

ゲーム選択フレームワークの構築

ゲームメニューが画面に表示されたら、選択を完了して、ゲームをプレイしながらゲームをプレイする必要があります。プレイしたい場合はどうすればよいですか。

このとき、ブロガーが前に説明したswitch ステートメントを適用する必要があります。


int main()
{
	int input = 0;
	do
	{
		menu();
		printf("PLEASE SELECT:");
		scanf("%d", &input);
		switch(input)
		{
		case 1:
			game();    //以上为界面的选择
			break;
		case 0:
			printf("Exit\n");
			break;
		default:
			printf("ERRO,PLEASE CHOOSE AGAIN\n");
			break;
		}
	} while (input);//while循环可以利用0为假,其余为来实现用户可反复选择
//直到选到合适为止
	return 0;
}              

ゲーム機能を実現する

モジュール式プログラミング: 3 つのチェスの前のセクションの内容を参照してください。


 test.c: ゲームロジックを実現するために使用されます game.c: ゲーム関数を実現するために使用される関数 game.h: ゲーム関数を宣言するために使用されます function (引用符で囲むこともできます)

モジュール式プログラミングを使用すると、コードの可読性、保守性、移植性などが大幅に向上します。

これは game.h ファイルです

#pragma once
#define _CRT_SECURE_NO_WARNINGS//使用scanf函数的报错处理方式 
#include <stdio.h>//打印函数的使用工具箱
#include<Windows.h>//颜色函数和清屏指令的工具箱
#include<stdlib.h>//在使用rand的时候需要用到srand,	srand((unsigned int)time(NULL))随机函数,调用一次就可以
#include<time.h>
#define row 9//常量
#define col 9
#define cols col+2//定义常量
#define rows row+2
void initboard(char board[rows][cols],int hang, int lie,char set);//形参数
void displayboard(char board[rows][cols], int hang, int lie);//只设置9*9格子
void setmine(char board[rows][cols], int hang, int lie);//埋入地雷
void panduan(char show[rows][cols], char mine[rows][cols],int hang, int lie);

後で 1 つずつ分析します。

test.c ファイル内での参照に使用されます

初期化地雷原

最初に目を引くのは、9×9の地雷原、81の覆われたグリッド、

グリッドをクリックすると、次の 2 つの状況が表示されます。

① 開いたグリッドが地雷の場合、プレイヤーは爆弾によって「死亡」し、ゲームが終了します。

② 開いたグリッドが地雷でない場合、グリッドには周囲の 8 つのグリッド内の地雷の数が表示されます。

この伝説から、9×9 の掃海艇ゲームを実現するには、9 行 9 列の 2 次元配列を作成するのは適切ではないと結論付けることができます。

9 行 9 列の 2 次元配列の境界要素に対する操作は配列の境界外アクセスにつながるため、単純に 2 次元配列を 1 つの円で拡張し、その範囲を含めます。これは、ソースで問題を解決する非常に賢い方法です。

したがって、2つの配列(2次元配列)を設定する必要があります

(1) 1つは地雷データの保存用(地雷を踏むかどうかの判断に使用)

(2) プレイヤーに表示するチェス盤 (上の青い未知の四角形に似ており、クリックすると周囲に 8 つの灰色の数字が表示されます)

2 つの配列を同時に初期化する必要があるinitboard サブ関数

void initboard(char board[rows][cols], int hang, int lie,char set)
{
	int i = 0;

	int j = 0;

	for (i = 0; i < hang; i++)
	{
		for (j = 0; j < lie; j++)
		{
			board[i][j] = set;
		}
	}
}//initboard(mine, rows, cols, '0');//在test.c中引用的函数
//initboard(show, row, col, '*');

ボードを最適化する

地雷原では行番号が長いため、行と列ごとにシリアル番号表示ボードのサブ機能をマークする必要があります。

void displayboard(char board[rows][cols], int hang, int lie)
{
	int i = 0;
	int j = 0; 
		printf("---------------------------------------\n");
	for(j = 0; j <=lie; j++)
	{
		printf("%d ",j);
	}
	printf("\n");
	for (i = 1; i <=hang; i++)
	{
		printf("%d ", i);
		for (j = 1; j <=lie; j++)
		{
			printf("%c ", board[i-1][j-1]);
		}
		printf("\n");
	}
	    printf("---------------------------------------\n");
}	

 レンダリング

 

ランダムに埋められた地雷

これは9x9の地雷原なので、地雷は10個あれば十分です。しかし、適切なエリアにランダムに地雷を設置するにはどうすればよいでしょうか?

C言語で乱数を生成する方法:

void setmine(char board[rows][cols], int hang, int lie)//随机埋入地雷
{
	int count = 10;
	while (count)
	{
		int x = rand() % hang ;
		int y = rand() % lie ;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
		}
		count--;
	}

}//srand((unsigned int)time(NULL));//布置雷的随机时间函数,在test.c主函数
中引用一次就够

クリック後の決定

展開後の周囲の地雷の数 

マインスイーパゲームでは、クリックしたマスが地雷ではなく、周囲に地雷がない場合、直接地雷原が拡張され、具体的な効果は下図の通りです。

 

マインスイーパゲームでは、プレイヤーがマス目をめくると、そのマス目が地雷でない場合は、周囲の 8 つのマス目の地雷の数が表示されます。正方形の周囲の 8 つの座標に地雷がない場合は、9 つ​​の正方形すべてが拡張され、以下同様に、正方形の周囲の 8 つの座標に地雷が存在し、拡張が停止します。2 つのケースを次の図に示します。

 この機能を実現するには、プレイヤーが入力した座標を中心に8つの座標をたどり、その座標の周囲にある地雷の数をカウントする必要があります。

int get_mine(char board[rows][cols],int x, int y)
{
	return (board[x - 1][y - 1]
		+ board[x - 1][y]
		+ board[x - 1][y + 1]
		+ board[x][y + 1]
		+ board[x][y - 1]
		+ board[x + 1][y + 1]
		+ board[x + 1][y]
		+ board[x + 1][y - 1] - 8* '0');//周围8个坐标相加
}

 

 

 この関数コードを実装します

void Mark(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("\n请输入要标记的坐标>>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)       //判断玩家输入坐标是否合法
		{
			if (board[x][y] == '!')       //若坐标元素为 '!' 则表示该坐标已被标记过
			{
				printf("\n<该坐标已标记,无需重复标记,请重新输入>\n");
			}
			else       //该坐标未被标记
			{
				board[x][y] = '!';       //将 '!' 赋值给该坐标元素
				DisplayBoard(board, row, col);       //将标记地雷后的雷区展示于玩家
				break;
			}
		}
		else
		{
			printf("\n<坐标非法,请重新输入>\n\n");
		}
	}
}

ゲーム(); アレンジメント

void game()
{
	char mine[rows][cols] = { 0 };//存放雷的信息
	char show[rows][cols] = { 0 };//显示给玩家的游戏界面信息
	initboard(mine, rows, cols, '0');
	initboard(show, row, col, '*');
	//displayboard(mine, row, col);
	setmine(mine, row,col);
	displayboard(show, row, col);
	panduan(show,mine, row, col);
}

さて、以上の内容は今日で終わります、たくさん応援していただければ幸いです!

一部のコンテンツはブロガーから借用していますが、ご理解いただければ幸いです。

おすすめ

転載: blog.csdn.net/fcccfffg/article/details/132504711