#はじめに
Hello Worldは公式サイトなどで提供されていますが、次に何をしようか悩む人も多いのではないかと思います。
これまで私はc,Visual C++,objective-c++,java,C#,javascript,phpなどで仕事をしてきましたが、
Hello Worldの次にマインスイーパーを実装することで言語習得してきました。
なぜこの記事を書いたかというと、先日このような記事を読みました。
プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべし
こちらで紹介されていたブラックジャックで言語習得というのは良い課題だと思いました。
ソースの量が少なく、処理も実践的、そして楽しみながら覚えられる。
これに刺激されて、私の実践している機雷処理言語学習法について、まとめることでメリット、デメリットを把握しておこうと思ったからです。
機雷処理言語学習法
私がマインスイーパを作る理由は
・基本的な文法を一通り使うことができる
・それなりにシンプルなコードになる
・リストや配列を使った再帰的処理で実装するので、わりと実践向け
・CUIでもGUIでもそんなに入出力が難しくない
・デバッグしながら遊べる
・OS標準で入ってることが多いので、新人とかに教える場合「これと同じ動作をするアプリ作れ」という課題にできる。
・好きだから
のような感じです。
デメリットは、
・エラーや例外はあまり覚えることができない
・勉強してるのに遊んでると思われる
というところでしょうか。
以下の項目を覚えるつもりで調べながら実装しています。
- 基本文法
- 分岐
- ループ
- 変数
- 定数
- 列挙型
- 配列、リスト
- クラス、構造体
- メソッド、メンバ変数
- public,private
- コンストラクタ
- 四則演算、ビット演算
- ライブラリの使い方
- import,include
- 文字列操作、文字列表示
- 乱数
例としてpythonで作成したのをあげておきます。
pythonは2か月前くらいに仕事で初めて使ったくらいの感じなので恥ずかしいですが上げときます。
# coding: utf-8
import random
import os
class Cell:
__isMine = False
__isOpen = False
def __init__(self,isMine):
self.__isMine = isMine
def open(self):
self.__isOpen = True
def isOpen(self):
return self.__isOpen
def isMine(self):
return self.__isMine
class Field:
__cells = []
__x = 0
__y = 0
__mine = 0
def __init__(self,x,y,mine):
self.__x = x
self.__y = y
self.__mine = mine
for i in range(x*y):
cellMine = False
if i < mine:
cellMine = True
self.__cells.append(Cell(cellMine))
random.shuffle(self.__cells)
# 標準出力にテキストで表示する。左と上にヘッダとして座標用の数を表示する。開いてない="/" 開いた=1~8 or " "(スペース)
def printField(self):
header1 = " |"
header2 = "--"
for ix in range(self.__x):
header1 += str(ix % 10)
header2 += "-"
print(header1)
print(header2)
for iy in range(self.__y):
line = str(iy % 10)
line += "|"
for ix in range(self.__x):
item = self.__cells[iy * self.__x + ix]
if True == item.isOpen():
if True == item.isMine():
line += "*"
elif self.__roundNum(ix,iy) ==0:
line += " "
else:
line += str(self.__roundNum(ix,iy))
else:
line += "/"
print(line)
def open(self,x,y):
if x < 0:
return
elif x >= self.__x:
return
elif y < 0:
return
elif y >= self.__y:
return
else:
item = self.__cells[y * self.__x + x]
if item.isOpen():
return
item.open()
if item.isMine() == False:
if self.__roundNum(x,y) == 0: #0なら隣接cellをOpenする
self.open(x-1,y-1) #左上
self.open(x ,y-1) #中上
self.open(x+1,y-1) #右上
self.open(x-1,y ) #左中
self.open(x+1,y ) #右中
self.open(x-1,y+1) #左下
self.open(x ,y+1) #中下
self.open(x+1,y+1) #右下
def __roundNum(self,x,y):
round = 0
if self.__isMine(x-1,y-1): #左上
round += 1
if self.__isMine(x ,y-1): #中上
round += 1
if self.__isMine(x+1,y-1): #右上
round += 1
if self.__isMine(x-1,y ): #左中
round += 1
if self.__isMine(x+1,y ): #右中
round += 1
if self.__isMine(x-1,y+1): #左下
round += 1
if self.__isMine(x ,y+1): #中下
round += 1
if self.__isMine(x+1,y+1): #右下
round += 1
return round
#指定セルが存在してmine状態の場合にTrueを返す
def __isMine(self,x,y):
if x < 0:
return False
elif x >= self.__x:
return False
elif y < 0:
return False
elif y >= self.__y:
return False
return self.__cells[y * self.__x + x].isMine()
def isOver(self):
overFlag = False
for i in range(self.__x * self.__y):
item = self.__cells[i]
if item.isOpen() and item.isMine():
overFlag = True
break
return overFlag
def isClear(self):
closeCount = 0
overFlag = False
for i in range(self.__x * self.__y):
item = self.__cells[i]
if item.isOpen() == False:
closeCount += 1
if closeCount == self.__mine:
overFlag = True
return overFlag
def cleanScreen():
os.system('cls') # windows
# os.system('clear') # linux
def main():
fieldWidth = 20
fieldHeight = 8
fieldMine = 30
field = Field(fieldWidth,fieldHeight,fieldMine)
while field.isOver() == False and field.isClear() == False:
cleanScreen()
field.printField()
print( "input:x y" )
ix, iy = map(int, input().split())
field.open(ix,iy)
cleanScreen()
field.printField()
if field.isOver():
print( "==over==" )
if field.isClear():
print( "==clear==" )
if __name__ == "__main__":
main()
時間がかけられる時は、以下の追加仕様を実装しています。
中級編
旗を立てる機能
数字と旗の数が一致している場合に、旗が無い場所を開く(Windows版の左右同時クリックのやつ)
上級編
自動プレイ機能
1.確定している場所にフラグを立てる
2.すべてフラグを立てたら、安全な場所を開く
3.安全な場所がない場合、ランダムで開く
1~3繰り返し
まとめ
何を作るかよりも、同じ仕様のアプリを別な言語で作成していくことに意味があると思っています。
別な言語を覚えるときに、またQiitaにアップして特徴を比較していければと思います。