mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 69a4efaf66
			
		
	
	
		69a4efaf66
		
	
	
	
	
		
			
			not encoding. * sample/mine.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33239 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			176 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable file
		
	
	
	
	
| #! /usr/bin/ruby -Ku
 | ||
| # -*- coding: utf-8 -*-
 | ||
| 
 | ||
| class Board
 | ||
|   def clr
 | ||
|     print "\e[2J"
 | ||
|   end
 | ||
|   def pos(x,y)
 | ||
|     printf "\e[%d;%dH", y+1, x*2+1
 | ||
|   end
 | ||
|   def colorstr(id,s)
 | ||
|     printf "\e[%dm%s\e[0m", id, s
 | ||
|   end
 | ||
|   def put(x, y, col, str)
 | ||
|     pos(x,y); colorstr(43,str)
 | ||
|     pos(0,@hi); print "残り:",@mc,"/",@total,"   "
 | ||
|     pos(x,y)
 | ||
|   end
 | ||
|   private :clr, :pos, :colorstr, :put
 | ||
|   CHR=["・","1","2","3","4","5","6","7","8","★","●","@@"]
 | ||
|   COL=[46,43,45] # default,opened,over
 | ||
|   def initialize(h,w,m)
 | ||
|     # ゲーム盤の生成(h:縦,w:横,m:爆弾の数)
 | ||
|     @hi=h; @wi=w; @m=m
 | ||
|     reset
 | ||
|   end
 | ||
|   def reset
 | ||
|     # ゲーム盤を(再)初期化する
 | ||
|     srand()
 | ||
|     @cx=0; @cy=0; @mc=@m
 | ||
|     @over=false
 | ||
|     @data=Array.new(@hi*@wi)
 | ||
|     @state=Array.new(@hi*@wi)
 | ||
|     @total=@hi*@wi
 | ||
|     @total.times {|i| @data[i]=0}
 | ||
|     @m.times do
 | ||
|        loop do
 | ||
|          j=rand(@total-1)
 | ||
|          if @data[j] == 0 then
 | ||
|            @data[j]=1
 | ||
|            break
 | ||
|          end
 | ||
|        end
 | ||
|     end
 | ||
|     clr; pos(0,0)
 | ||
|     @hi.times{|y| pos(0,y); colorstr(COL[0],CHR[0]*@wi)}
 | ||
|     pos(@cx,@cy)
 | ||
|   end
 | ||
|   def mark
 | ||
|     # 現在のカーソル位置にマークをつける
 | ||
|     if @state[@wi*@cy+@cx] != nil then return end
 | ||
|     @state[@wi*@cy+@cx] = "MARK"
 | ||
|     @mc=@mc-1;
 | ||
|     @total=@total-1;
 | ||
|     put(@cx, @cy, COL[1], CHR[9])
 | ||
|   end
 | ||
|   def open(x=@cx,y=@cy)
 | ||
|     # 現在のカーソル位置をオープンにする
 | ||
|     # 爆弾があればゲームオーバー
 | ||
|     if @state[@wi*y+x] =="OPEN"  then return 0 end
 | ||
|     if @state[@wi*y+x] == nil then @total=@total-1 end
 | ||
|     if @state[@wi*y+x] =="MARK" then @mc=@mc+1 end
 | ||
|     @state[@wi*y+x]="OPEN"
 | ||
|     if fetch(x,y) == 1 then @over = 1; return end
 | ||
|     c = count(x,y)
 | ||
|     put(x, y, COL[1], CHR[c])
 | ||
|     return 0 if c != 0
 | ||
|     if x > 0 && y > 0         then open(x-1,y-1) end
 | ||
|     if y > 0                  then open(x,  y-1) end
 | ||
|     if x < @wi-1 && y > 0     then open(x+1,y-1) end
 | ||
|     if x > 0                  then open(x-1,y) end
 | ||
|     if x < @wi-1              then open(x+1,y) end
 | ||
|     if x > 0 && y < @hi-1     then open(x-1,y+1) end
 | ||
|     if y < @hi -1             then open(x,y+1) end
 | ||
|     if x < @wi-1 && y < @hi-1 then open(x+1,y+1) end
 | ||
|     pos(@cx,@cy)
 | ||
|   end
 | ||
|   def fetch(x,y)
 | ||
|     # (x,y)の位置の爆弾の数(0 or 1)を返す
 | ||
|     if x < 0 then 0
 | ||
|     elsif x >= @wi then 0
 | ||
|     elsif y < 0 then 0
 | ||
|     elsif y >= @hi then 0
 | ||
|     else
 | ||
|       @data[y*@wi+x]
 | ||
|     end
 | ||
|   end
 | ||
|   def count(x,y)
 | ||
|     # (x,y)に隣接する爆弾の数を返す
 | ||
|     fetch(x-1,y-1)+fetch(x,y-1)+fetch(x+1,y-1)+
 | ||
|     fetch(x-1,y)  +             fetch(x+1,y)+
 | ||
|     fetch(x-1,y+1)+fetch(x,y+1)+fetch(x+1,y+1)
 | ||
|   end
 | ||
|   def over(win)
 | ||
|     # ゲームの終了
 | ||
|     quit
 | ||
|     unless win
 | ||
|       pos(@cx,@cy); print CHR[11]
 | ||
|     end
 | ||
|     pos(0,@hi)
 | ||
|     if win then print "*** YOU WIN !! ***"
 | ||
|     else print "*** GAME OVER ***"
 | ||
|     end
 | ||
|   end
 | ||
|   def over?
 | ||
|     # ゲームの終了チェック
 | ||
|     # 終了処理も呼び出す
 | ||
|     remain = (@mc+@total == 0)
 | ||
|     if @over || remain
 | ||
|       over(remain)
 | ||
|       true
 | ||
|     else
 | ||
|       false
 | ||
|     end
 | ||
|   end
 | ||
|   def quit
 | ||
|     # ゲームの中断(または終了)
 | ||
|     # 盤面を全て見せる
 | ||
|     @hi.times do|y|
 | ||
|       pos(0,y)
 | ||
|       @wi.times do|x|
 | ||
| 	colorstr(if @state[y*@wi+x] == "MARK" then COL[1] else COL[2] end,
 | ||
| 		 if fetch(x,y)==1 then CHR[10] else CHR[count(x,y)] end)
 | ||
|       end
 | ||
|     end
 | ||
|   end
 | ||
|   def down
 | ||
|     # カーソルを下に
 | ||
|     if @cy < @hi-1 then @cy=@cy+1; pos(@cx, @cy) end
 | ||
|   end
 | ||
|   def up
 | ||
|     # カーソルを上に
 | ||
|     if @cy > 0 then @cy=@cy-1; pos(@cx, @cy) end
 | ||
|   end
 | ||
|   def left
 | ||
|     # カーソルを左に
 | ||
|     if @cx > 0 then @cx=@cx-1; pos(@cx, @cy) end
 | ||
|   end
 | ||
|   def right
 | ||
|     # カーソルを右に
 | ||
|     if @cx < @wi-1 then @cx=@cx+1; pos(@cx, @cy) end
 | ||
|   end
 | ||
| end
 | ||
| 
 | ||
| bd=Board.new(10,10,10)
 | ||
| system("stty raw -echo")
 | ||
| begin
 | ||
|   loop do
 | ||
|     case STDIN.getc
 | ||
|     when ?n  # new game
 | ||
|       bd.reset
 | ||
|     when ?m  # mark
 | ||
|       bd.mark
 | ||
|     when ?j
 | ||
|       bd.down
 | ||
|     when ?k
 | ||
|       bd.up
 | ||
|     when ?h
 | ||
|       bd.left
 | ||
|     when ?l
 | ||
|       bd.right
 | ||
|     when ?\s
 | ||
|       bd.open
 | ||
|     when ?q,?\C-c  # quit game
 | ||
|       bd.quit
 | ||
|       break
 | ||
|     end
 | ||
|     if bd.over?
 | ||
|       if STDIN.getc == ?q then break end
 | ||
|       bd.reset
 | ||
|     end
 | ||
|   end
 | ||
| ensure
 | ||
|   system("stty -raw echo")
 | ||
| end
 | ||
| print "\n"
 |