絵クロス

皆さん絵クロスって知っていますか?

書き方が様々(?)あるようですのでピンと来ない方もいらっしゃいますよね…。

こう書いた方がわかりやすいかな?「イラストロジック」とか「マリ●のピクロス(爆」

マス目を塗りつぶして行き1つの絵にするものです。

下記スクリーンショットを見ていただければどんな感じのものか想像できますよね。

 

#define cols 15 ; 1辺のマス数
	dim data,cols,cols ; クリックしてスイッチONになったマス
	dim msgx,cols+1/2,cols ; 横に書かれる塗りつぶすマスのヒント
	dim msgy,cols+1/2,cols ; 横に書かれる塗りつぶすマスのヒント
;------ ココから問題となるマス --------- msgx.0.0=2,2,2 msgx.0.1=7,3,2 msgx.0.2=7,2,2 msgx.0.3=2,2,2 msgx.0.4=2,3 msgx.0.5=5,6 msgx.0.6=4,5 msgx.0.7=3 msgx.0.8=6,3,2 msgx.0.9=10,2 msgx.0.10=2,2,2,1 msgx.0.11=2,2,2,1 msgx.0.12=3,3,2,1 msgx.0.13=4,2,4 msgx.0.14=3,2,3 msgy.0.0=2,2,2 msgy.0.1=2,2,2,4 msgy.0.2=3,2,2,4 msgy.0.3=6,2,2 msgy.0.4=5,7 msgy.0.5=3,6 msgy.0.6=1,1,1,2 msgy.0.7=3,3 msgy.0.8=6,2,2 msgy.0.9=5,2,3 msgy.0.10=2,2 msgy.0.11=7,2 msgy.0.12=7,3 msgy.0.13=2,5 msgy.0.14=4,4
;-------------- ココまで -------------

初めに一辺の数を定義しています。とりあえず縦横15×15マス位でいいでしょう。

問題マスと書かれたコメントから下は埋めるマスのヒントとなるものを表示する数字です。

例えば「msgx.0.0=2,2,2」は横キーの一番上段のヒントに「2」「2」「2」を入れるということです。

イメージ的には下記の感じです。

	┌────┬─┬─┬─┬
	│    │ │4│4│
	│    │1│2│2│
	│    │2│2│2│
	│    │2│2│3│
	├────┼─┼─┼─┼
	│ 222│ │ │ │
	├────┼─┼─┼─┼
	│ 732│ │ │ │
	├────┼─┼─┼─┼

今回初めて2次元配列が出てきました。

	a.0.0=1,2,3
	a.0.1=4,5,6

上記例は「dim a,3,2」と既に宣言されているものとして、下記の様に書いたものと全く同じです。

	a.0.0=1
	a.1.0=2
	a.2.0=3
	a.0.1=4
	a.1.1=5
	a.2.1=6

縦横共に1次元目が「一辺のマス数+1÷2」と宣言されているのは何でしょう?

これは表示するヒントの最大数です。

つまり長さ15マスでは「1,1,1,1,1,1,1,1」左記の8個あるのが限界ですね。

埋めるマスの間には1マス以上空きがないと繋がった状態になってしまいますし、

2以上の数値が入っているとヒントの最大数が減ってしまいます。

で偶数マス数も偶数に1引いた奇数マス数も最大数は同じです。ココでは15マスも16マスも同じです。

「÷2」とされているのは「最少1マス+空ける最少1マス」を割ったものです(分かりにくい...)。

コレで問題部分の準備は出来ました。

 

それでは次に上記の問題(ヒント)となる数字やマスの描画処理部分に入ります。

	screen 0,cols*20+100,cols*20+100
	title ""
	font "MS ゴシック",13
	redraw 0
	color 192,192,192
	boxf 0,0,winx,100
	boxf 0,0,100,winy
	color
	boxf 0,0,100,100
	repeat cols
		line cnt*20+100,-1,cnt*20+100,winy
		line -1,cnt*20+100,winx,cnt*20+100
	loop
	repeat cols
		repeat cols+1/2
			tmp=cols+1/2-cnt-1
			if msgx.tmp.cont=0 : continue
			cont.1+
			pos 105-(cont.1*20),104+(cont*20) : mes msgx.tmp.cont ; ヒント描画
		loop
		cont+
		cont.1=0
	loop
	cont=0
	repeat cols
		repeat cols+1/2
			if msgy.cnt.cont=0 : continue
			cont.1+
			pos 106+(cont*20),102-(cont.1*20) : mes msgy.cnt.cont ; 端からつめてヒントを描画
		loop
		cont+
		cont.1=0
	loop
	redraw
	stop

ココで注意すべき(?)点は一点くらいですね。

ヒントの描画位置・順番なのですが、

通常の順番(左,上が先)ではなく最後・奥(右,下)から始めます。

ソレはマスに近い所にヒントを表示させるためです。

先ほどのイメージだと縦キー左端に「1,2,2」がありますけど「1」(上)側に詰めると不細工ですね^^;

 

それではユーザーがクリックでマスを埋めて行ける様にキー判定を入れましょう。

左クリックでマスの塗りつぶし、右クリックで塗りつぶしキャンセルとなっています。

塗りつぶし位置ですが、脱初心者ということでif文の多用による塗りつぶし位置チェックをしていません。


*main
	wait 5
	stick key,768,1
	if key&768 {
		mx=mousex-100/20
		my=mousey-100/20
		if mx<0|(my<0)|(mx>=cols)|(my>=cols) : goto *main
		if key&256 : color 100,100,100 : data.mx.my = 1 : boxf mx * 20 + 101, my * 20 + 101, mx * 20 + 119, my * 20 + 119
		if key&512 : color 255,255,255 : data.mx.my = 0 : boxf mx * 20 + 101, my * 20 + 101, mx * 20 + 119, my * 20 + 119
	}
	goto *main

 

それではコレを拡張していきましょうか…。

塗りつぶさないと決定しているマスにチェックを入れておけるとわかりやすくなりますね?

問題もファイルとして保存させて読み込ませるようにしましょうか…。

…ということで問題となるファイルを作成するものが必要となってきますよね。

その問題の作成部分から作って行きましょうか。

ファイルとして保存させておかなければならない情報は何があるでしょう?

まずは縦と横の塗りつぶす数ですね、それも連続している場合は連続した数値を分ける必要もでてきます。

塗りつぶしを1と表わしデータが「1101」の場合、塗るのは「2,1」となってほしいわけです。

また縦横の長さも保存する必要がありますね…大体はコレくらいでしょうか?

では上記のものをファイルとして保存するスクリプトを書いてみましょう。


 size=15 ; 1辺のマス数
	dim data,size,size
	sdim filename,256
	screen 0,150,50
	title "問題作成ツール"
	objsize 150,25
	button"保存",save
	objsize 100,25
	input size,50,,2
	pos 50,25 : button"変更",change
	ginfo 2
	screen 2,size*20,size*20,,prmx+155,prmy
	title ""
	redraw 0
	gosub *drawline
	redraw

*main
	wait 1
	stick key,768,1
	if key&768 {
		ginfo 1
		if prmx=0 : goto *main
		mx=mousex/20
		my=mousey/20
		if mx>=size|(my>=size) : goto *main
		if key&256 : data.mx.my=1
		if key&512 : data.mx.my=0
		gosub *drawmasu
	}
	goto *main

*drawline
	color
	repeat size
		line -1,cnt*20,size*20,cnt*20
	loop
	repeat size
		line cnt*20,-1,cnt*20,size*20
	loop
	return

*drawmasu
	redraw 0
	if key&512 : color 255,255,255 : boxf : gosub *drawline
	color 100,100,100
	cont=0
	repeat size
		repeat size
			if data.cnt.cont=1 : boxf cnt*20+1,cont*20+1,cnt*20+19,cont*20+19
		loop
		cont+
	loop
	redraw
	return

*save
	dialog"crs",17
	if stat=0 : goto *main
	filename=refstr
	sdim savedata,6144
	savedata=""+size+"\n"
	cont=0
	repeat size
		cont.1=0
		repeat size
			if data.cnt.cont = 1 {
				cont.1+
			} else {
				if cont.1 : str cont.1,2 : savedata += "" + cont.1 : cont.1 = 0
			}
		loop
		if cont.1 : str cont.1,2 : savedata+=""+cont.1
		savedata+="\n"
		cont+
	loop
	cont=0
	repeat size
		cont.1=0
		repeat size
			if data.cont.cnt = 1 {
				cont.1+
			} else {
				if cont.1 : str cont.1,2 : savedata += "" + cont.1 : cont.1 = 0
			}
		loop
		if cont.1 : str cont.1,2 : savedata+=""+cont.1
		if cont<size : savedata+="\n"
		cont+
	loop
	strlen len,savedata
	strmid tmp,filename,-1,4
	if tmp!=".crs" : filename+=".crs"
	bsave filename,savedata,len
	goto *main

*change
	if size<10 : dialog"10マス未満は指定できません" : goto *main
	if size>36 : dialog"36マス以上は指定できません" : goto *main
	dim data,size,size
	gsel 0
	ginfo 2
	screen 2,size*20,size*20,,prmx+155,prmy
	redraw 0
	gosub *drawline
	redraw
	goto *main

説明するところは…特にないですよね…。

塗りつぶし部分の処理は本体の方とほぼ同じでいけますので、重要な部分はやはり保存だけでしょう。

重要と言っても決して難しいわけではなく(人によっては難しいかもしれませんが…)、

塗りつぶす部分が続いていればループカウンタとは別にカウンタを設けておいてやるだけですね。

そのカウンタの保存の形式ですが、

連続した数が1桁や2桁あったりするのでこれは1桁、あれは2桁とわかるようにしないといけません。

例えば「132104」は「1,3,2,10,4」「13,2,10,4」「1,3,21,10,4」「1,32,10,4」なのかわかりませんね。

ですのでコンマで区切り、コンマまでが1つの数値である、とか決めておきましょう。

私は10未満のものも2桁にしてしまい2桁取り出して数値化すればわかるようにしてみました。

右記の感じで。「13021004」と保存することで「13,2(02),10,4(04)」とわかる。

一列のマス数も分かるようにしておかなければなりません。列数も同時に保存しておきます。

 

それではこれで作成したファイルを読み込むタイプの絵クロスを完成させましょう。

また微妙にいろいろな部分が変わったりしていますので初めから最後まで書きます。

	dialog"crs",16,"絵クロス問題データ"
	if stat=0 : end
	sdim filename,256
	filename=refstr
	exist filename
	sdim filedata,strsize+1
	bload filename,filedata
	notesel filedata
	noteget cols,0 ; 列数読み込み
	int cols
	dim data,cols,cols
	dim msgx,cols+1/2,cols
	dim msgy,cols+1/2,cols
; ---------- 問題読み込み ---------- repeat cols linex+ noteget tmpstr,linex strlen len,tmpstr len=len/2 arrangement=linex-1 repeat len strmid tmp,tmpstr,cnt*2,2 int tmp if tmp=0 : break msgx.cnt.arrangement=tmp loop loop repeat cols linex+ noteget tmpstr,linex strlen len,tmpstr len=len/2 arrangement=linex-cols-1 repeat len strmid tmp,tmpstr,cnt*2,2 int tmp if tmp=0 : break msgy.cnt.arrangement=tmp loop loop
; ------------ ココまで ------------ screen 0,cols*20+(cols*8),cols*20+(cols*8) title "" font "MS ゴシック",12 redraw 0 color 192,192,192 boxf 0,0,winx,(cols*8) boxf 0,0,(cols*8),winy color boxf 0,0,(cols*8),(cols*8) repeat cols line cnt*20+(cols*8),-1,cnt*20+(cols*8),winy line -1,cnt*20+(cols*8),winx,cnt*20+(cols*8) loop repeat cols repeat cols+1/2 tmp=cols+1/2-cnt-1 if msgx.tmp.cont=0 : continue cont.1+ pos cols*8-(cont.1*15),cols*8+(cont*20)+5 : mes msgx.tmp.cont loop cont+ cont.1=0 loop cont=0 repeat cols repeat cols+1/2 tmp=cols+1/2-cnt-1 if msgy.tmp.cont=0 : continue cont.1+ pos cols*8+(cont*20)+5,cols*8-(cont.1*16) : mes msgy.tmp.cont loop cont+ cont.1=0 loop redraw *main wait 1 stick key,256,1 if key&768 { mx=mousex-(cols*8)/20 my=mousey-(cols*8)/20 if mx<0|(my<0)|(mx>=cols)|(my>=cols) : goto *main if key&256 { data.mx.my=1 color 100,100,100 boxf mx*20+(cols*8)+1,my*20+(cols*8)+1,mx*20+(cols*8)+19,my*20+(cols*8)+19 } if key&512 { if data.mx.my=0 { data.mx.my=-1 color 255 line mx*20+(cols*8),my*20+(cols*8),mx*20+19+(cols*8),my*20+19+(cols*8) ; ×印 line mx*20+(cols*8)+19,my*20+(cols*8),mx*20+(cols*8)+1,my*20+(cols*8)+19 ; ×印 goto *main } data.mx.my=0 color 255,255,255 boxf mx*20+(cols*8)+1,my*20+(cols*8)+1,mx*20+(cols*8)+19,my*20+(cols*8)+19 } } goto *main

このサンプルはただ単にマスを塗りつぶしていくだけのもので出来上がってもクリアというものがありません。

その辺は各自いろいろと工夫してください。

またバグ等もありましたら頑張って取り除いてください(--;

スクリプトはコチラをどうぞ。経過時間表示が付いただけです。

それでは〜。