見出し画像

PowerShellでマインスイーパーを作る

Windowsユーザーお馴染みのマインスイーパーをPowerShellで作ってみました。


function minesweeper(){
	$masu_size = 8 #マスの大きさ
	$boom_cnt = 8 #爆弾の数
	$unopened_cnt = $masu_size*$masu_size #未開封の数
	$boom_char = '*' #爆弾の文字
	$unopened_char = '+' #開いていないマスの文字
	$turn = 0 #ターン数


	#####
	# マスの作成

	#爆弾マス
	$masu_boom = New-Object "System.Object[,]"$masu_size,$masu_size
	#表示用マス
	$masu_disp = New-Object "System.Object[,]"$masu_size,$masu_size

	#表示用マス 未開封マーク
	for($i=0;$i -lt $masu_size;$i++){
		for($j=0;$j -lt $masu_size;$j++){
			$masu_boom[$i,$j] = " "
			$masu_disp[$i,$j] = $unopened_char
		}
	}

	#爆弾を置く処理
	for($i=0;$i -lt $boom_cnt;$i++){
		$x = Get-Random -Maximum $masu_size -Minimum 0
		$y = Get-Random -Maximum $masu_size -Minimum 0
		#同じ場所に置かない処理
		if($masu_boom[$y,$x] -eq $boom_char){
			$i--  #同じ場所に爆弾を置くときは再度処理するためにループカウンタを減らす
		} else {
			$masu_boom[$y,$x] = $boom_char
		}
	}

	#周りの爆弾の数を数え、マスに書き込む処理
	$dx=@(-1,-1, 0, 1, 1, 1, 0,-1)
	$dy=@(0 ,-1,-1,-1, 0, 1, 1, 1)
	for($i=0;$i -lt $masu_size;$i++){
	  for($j=0;$j -lt $masu_size;$j++){
		if($masu_boom[$i,$j] -ne $boom_char){
			$cnt=0
			for($k=0;$k -lt 8;$k++){
				if( ($($i+$dy[$k]) -ge 0) -and ($($i+$dy[$k]) -lt $masu_size) -and ($($j+$dx[$k]) -ge 0) -and ($($j+$dx[$k]) -lt $masu_size)){
					if($masu_boom[$($i+$dy[$k]),$($j+$dx[$k])] -eq $boom_char){
						$cnt+=1
					}
				}
			}
			if($cnt -ne 0) { # 0個の場合は書き込まない
				$masu_boom[$i,$j]=$cnt
			}
		}
	  }
	}

	# マスの表示関数
	function disp-masu($masu,$size){

		$disp_tmp="  ABCDEFGH"

		write-host " "
		write-host $disp_tmp

		for($i=0;$i -lt $size;$i++){
			write-host " $($i+1)" -NoNewline
			for($j=0;$j -lt $size;$j++){
				if($masu[$i,$j] -eq $boom_char){
					write-host  $masu[$i,$j] -NoNewline
				} elseif($masu[$i,$j] -eq $unopened_char) {
					write-host  $masu[$i,$j] -NoNewline -BackgroundColor DarkGray 
				} elseif($masu[$i,$j] -eq '1') {
					write-host  $masu[$i,$j] -NoNewline -ForegroundColor Blue 
				} elseif($masu[$i,$j] -eq '2') {
					write-host  $masu[$i,$j] -NoNewline -ForegroundColor DarkGreen 
				} elseif($masu[$i,$j] -eq '3' -or $masu[$i,$j] -eq '4' -or $masu[$i,$j] -eq '5' -or $masu[$i,$j] -eq '6' -or $masu[$i,$j] -eq '7' -or $masu[$i,$j] -eq '8' ) {
					write-host  $masu[$i,$j] -NoNewline -ForegroundColor red 
				} else {
					write-host  $masu[$i,$j] -NoNewline
				}
			}
   			write-host ""

		}
	}

	# 未開封のカウント関数
	function cnt-unopened($masu,$size){
		$cnt=0
		for($i=0;$i -lt $size;$i++){
			for($j=0;$j -lt $size;$j++){
				if($masu[$i,$j] -eq $unopened_char){
					$cnt+=1
				}
			}
		}
		return $cnt
	}

	#disp-masu $masu_boom $masu_size


	#####
	# 解答の入力

	#未開封の数
	$unopened_cnt = (cnt-unopened $masu_disp $masu_size)

	#タイマーセット
	$start_time = Get-Date
	$flg_loop=$True
	while($flg_loop){
		$turn+=1
		disp-masu $masu_disp $masu_size
		write-host "残り爆弾数 $boom_cnt"
		write-host "未開封の数 $unopened_cnt"
		$Input_x = '?'
		while( ($Input_x.Length -ne 1) -or ([Byte][Char]($Input_x) -lt 65) -or ([Byte][Char]($Input_x) -gt 72)){
			$Input_x = Read-Host "調べる座標 横位置(A~H)"
		}
		$Input_y = -1
		while( ($Input_y -lt 1) -or ($Input_y -gt $masu_size)  ){
			$Input_y = Read-Host "調べる座標 縦位置(1~$masu_size)"
		}
		write-host "入力されたのは 横 $Input_x 縦 $Input_y"
		write-host ""

		#入力補正
		$x = [Byte][Char]($Input_x) - 65
		$y = $Input_y - 1

		$flg_out = $False

		if($masu_boom[$y,$x] -eq $boom_char){
			#爆弾
			$flg_loop = $False
		} else {
			#周りの表示
			$search_que=@()
			$search_que+=,($y,$x)
			while($search_que.length -ne 0){
				$y = $search_que[0][0];
				$x = $search_que[0][1];
				$search_que = $search_que[1..($search_que.length)] #キューの先頭を削除
				$masu_disp[$y,$x] = $masu_boom[$y,$x]

				for($k=0;$k -lt 8;$k++){
					if( ($($y+$dy[$k]) -ge 0) -and ($($y+$dy[$k]) -lt $masu_size) -and ($($x+$dx[$k]) -ge 0) -and ($($x+$dx[$k]) -lt $masu_size)){
						#未開封マス
						if($masu_disp[$($y+$dy[$k]),$($x+$dx[$k])] -eq $unopened_char){
							#爆弾発見判定
							if($masu_boom[$($y+$dy[$k]),$($x+$dx[$k])] -eq $boom_char){
								$boom_cnt-=1
							}
							#空白発見判定 検索キューに加える
							if($masu_boom[$($y+$dy[$k]),$($x+$dx[$k])] -eq ' '){
								$search_que+= ,($($y+$dy[$k]),$($x+$dx[$k]))
							}
							#マスを開く
							$masu_disp[$($y+$dy[$k]),$($x+$dx[$k])] = $masu_boom[$($y+$dy[$k]),$($x+$dx[$k])]
						}
					}
				}
			}

			$unopened_cnt = (cnt-unopened $masu_disp $masu_size)
			if(($boom_cnt -eq 0) -or ($unopened_cnt -eq $boom_cnt)){
				$flg_loop = $False
			}
		}
	}


	if(($boom_cnt -eq 0) -or ($unopened_cnt -eq $boom_cnt)){
		write-host "★★★爆弾を全て発見しました★★★"
	} else {
		write-host "☆☆☆爆弾に当たってしまいました☆☆☆"
	}
	write-host "調べた数:$turn"
	$rap_time=(Get-Date) - $start_time
	write-host "掛かった時間(時:分:秒):$rap_time"

	disp-masu $masu_boom $masu_size
}


上のコードをコピーしてPowerShell の画面に貼り付け、Enter。


そしてコマンド minesweeper とエンターキーを押すと遊べます。


だいたいマインスイーパーです。

#PowerShell #マインスイーパー #コマンドレット #プログラミング初心者 #プログラミング学習 #毎日Note

この記事が気に入ったらサポートをしてみませんか?