この記事は【Kuin Advent Calendar 2016】の15日目の記事です。
【記事中で紹介しているコードについて】
コンパイルが通らない場合など、不具合があれば、@tatt61880まで連絡いただけると助かります。よろしくお願いいたします。
{ 15パズル }
func main()
assert @pieceSize % @piecePerFrame = 0 {この条件が満たされている前提で駒の移動処理を行います}
var finishedFont: draw@Font :: draw@makeFont("Meiryo", @finishedFontSize, false, false, true, 0.0)
{駒の初期化}
do @pieces :: #[16]@Piece
for i(0, 15)
do @pieces[i] :: (#@Piece).init(i)
end for
do @voidPiece :: @pieces[15]
do @shufflePieces()
const wndSizeW: int :: @pieceSize * 4
const wndSizeH: int :: @pieceSize * 4 + @finishedFontSize * 2
var wndMain: wnd@Wnd :: wnd@makeWnd(null, %normal, wndSizeW, wndSizeH, "The 15 puzzle")
var drawMain: wnd@Draw :: wnd@makeDraw(wndMain, 0, 0, wndSizeW, wndSizeH, %fix, %fix, false)
while a(wnd@act())
do draw@render(30)
do drawPieces()
if(@completeCheck())
do finishedFont.draw(10.0, @pieceSize $ float * 4.0, "Congratulations!", 0xFFFFFFFF)
end if
for i(0, ^@pieces - 1) {移動アニメーション用のループです}
var p: @Piece :: @pieces[i]
if(p.dir <> %stay)
do p.move(@piecePerFrame)
skip a {移動中にマウス入力を受け付けないように、ここでwhileループの先頭に戻ります}
end if
end for
do @setDirection(false)
if(input@pad(0, %a) > 10) {スペースキー長押しでシャッフル}
do @shufflePieces()
end if
end while
func drawPieces()
for i(0, ^@pieces - 1)
var p: @Piece :: @pieces[i]
if(p <>& @voidPiece)
do p.draw()
end if
end for
end func
end func
const pieceSize: int :: 100
const shuffleNum: int :: 1000
const piecePerFrame: int :: @pieceSize / 4
const fontSize: int :: 48
const finishedFontSize: int :: 20
enum Dir
stay
left :: 1
right :: 2
up :: 3
down :: 4
end enum
class Piece()
var id: int
var num: int
var font: draw@Font
+var posId: int
+var pos: Pos
+var dir: @Dir
+func init(id: int): @Piece
do me.id :: id
do me.num :: id + 1
do me.font :: draw@makeFont("Meiryo", @fontSize, false, false, false, @fontSize $ float)
do me.posId :: id
do me.pos :: (#Pos).init(me.posId)
do me.dir :: %stay
ret me
end func
+func getId(): int
ret me.id
end func
+func move(pixelPerFrame: int)
if(me.dir = %left)
do me.pos.x :- pixelPerFrame
elif(me.dir = %right)
do me.pos.x :+ pixelPerFrame
elif(me.dir = %up)
do me.pos.y :- pixelPerFrame
elif(me.dir = %down)
do me.pos.y :+ pixelPerFrame
end if
if(me.pos.x % @pieceSize = 0 & me.pos.y % @pieceSize = 0)
do me.dir :: %stay
end if
end func
+func draw()
do draw@rect(me.pos.x $ float + 2.0, me.pos.y $ float + 2.0, @pieceSize $ float - 4.0, @pieceSize $ float - 4.0, 0xFF0000FF)
do me.font.draw(me.pos.x $ float + (@pieceSize $ float - (^me.num.toStr() * @fontSize) $ float) / 2.0, me.pos.y $ float, me.num.toStr(), 0xFFFFFFFF)
end func
class Pos()
+var x: int
+var y: int
+func init(posId: int): Pos
do me.x :: @pieceSize * (posId % 4)
do me.y :: @pieceSize * (posId / 4)
ret me
end func
end class
end class
var pieces: []@Piece
var voidPiece: @Piece
{駒の位置情報を元にその駒のidを返します}
func findPieceId(posId: int): int
for i(0, ^@pieces - 1)
var p: @Piece :: @pieces[i]
if(p.posId = posId)
ret p.getId()
end if
end for
assert false {駒が見つかりません。これはおかしいです。}
end func
func setDirection(shuffleMode: bool)
var id: int
var dir: @Dir :: %stay
if(shuffleMode)
do dir :: lib@rnd(1, 4) $ @Dir
else
if(input@pad(0, %left) % 15 = 1)
do dir :: %left
elif(input@pad(0, %right) % 15 = 1)
do dir :: %right
elif(input@pad(0, %up) % 15 = 1)
do dir :: %up
elif(input@pad(0, %down) % 15 = 1)
do dir :: %down
end if
end if
switch d(dir)
case %left
if(@voidPiece.posId % 4 <> 3)
do id :: @findPieceId(@voidPiece.posId + 1)
do @pieces[id].dir :: d
do @voidPiece.posId :$ @pieces[id].posId
end if
case %right
if(@voidPiece.posId % 4 <> 0)
do id :: @findPieceId(@voidPiece.posId - 1)
do @pieces[id].dir :: d
do @voidPiece.posId :$ @pieces[id].posId
end if
case %up
if(@voidPiece.posId / 4 <> 3)
do id :: @findPieceId(@voidPiece.posId + 4)
do @pieces[id].dir :: d
do @voidPiece.posId :$ @pieces[id].posId
end if
case %down
if(@voidPiece.posId / 4 <> 0)
do id :: @findPieceId(@voidPiece.posId - 4)
do @pieces[id].dir :: d
do @voidPiece.posId :$ @pieces[id].posId
end if
end switch
if(shuffleMode)
do @pieces[id].move(@pieceSize)
end if
end func
func shufflePieces()
for i(1, @shuffleNum)
do @setDirection(true)
end for
end func
func completeCheck(): bool
for i(0, ^@pieces - 1)
var p: @Piece :: @pieces[i]
if(p.getId() <> p.posId)
ret false
end if
end for
ret true
end func