HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2017
0124
ぜろクロスワードをつくりたいんですけどどうやってやるのが一番いいですか7未解決


ぜろ

リンク

2017/1/24(Tue) 02:55:19|NO.78029

自分のやり方でもやってるんですけど、できないことばかりで、なかなか完成しそうにありません。おすすめのやりかたあったら教えてくれませんか。僕は初心者です。



この記事に返信する


ぜろ

リンク

2017/1/24(Tue) 02:56:11|NO.78030

randomize
screen 2,300,100,,510,0
sdim buf_input,1000
input buf_input,195,18,0
objsize 45,20 : objmode 1,1;サイズとフォントを指定
button gosub "決定",*決定

screen 0,500,500,,0,0


dim alphabet,25,25
for x,0,25
for y,0,25
alphabet(x,y)=0
next
next

sdim buf_mesbox,1000
notesel buf_mesbox
noteload "単語集.txt"

maru_x = -999
maru_y = -999




//ここまでロード

*hata0
redraw 0
color 255,255,255
boxf
color 200,200,200
for x,0,25
line x*20,500,x*20,0
next
for y,0,25
line 500,y*20,0,y*20
next

;まずは座標を決める


color 0,0,0
pos 0,400
mes "x座標" + x座標
mes "y座標" + y座標


pos maru_x,maru_y
mes "●"



*hata1
stick left_click,0
if left_click = 256{

maru_x = (mousex/20)*20
maru_y = (mousey/20)*20

x座標=((mousex/20)*20)/20
y座標=((mousey/20)*20)/20

redraw 1
await 10


goto *hata0

}

redraw 1
await 10
goto *hata1









stop
*アルファベット表
color 0,0,0
if alphabet(x,y) = 0 :mes "A"
if alphabet(x,y) = 1 :mes "B"
if alphabet(x,y) = 2 :mes "C"
if alphabet(x,y) = 3 :mes "D"
if alphabet(x,y) = 4 :mes "E"
if alphabet(x,y) = 5 :mes "F"
if alphabet(x,y) = 6 :mes "G"
if alphabet(x,y) = 7 :mes "H"
if alphabet(x,y) = 8 :mes "I"
if alphabet(x,y) = 9 :mes "J"
if alphabet(x,y) = 10 :mes "K"
if alphabet(x,y) = 11 :mes "L"
if alphabet(x,y) = 12 :mes "M"
if alphabet(x,y) = 13 :mes "N"
if alphabet(x,y) = 14 :mes "O"
if alphabet(x,y) = 15 :mes "P"
if alphabet(x,y) = 16 :mes "Q"
if alphabet(x,y) = 17 :mes "R"
if alphabet(x,y) = 18 :mes "S"
if alphabet(x,y) = 19 :mes "T"
if alphabet(x,y) = 20 :mes "U"
if alphabet(x,y) = 21 :mes "V"
if alphabet(x,y) = 22 :mes "W"
if alphabet(x,y) = 23 :mes "X"
if alphabet(x,y) = 24 :mes "Y"
if alphabet(x,y) = 25 :mes "Z"
return

*決定



KA

リンク

2017/1/24(Tue) 06:18:26|NO.78034

まず
1:何を作るのか
2:それには、どういう手順が必要か
3:その手順を項目で分ける
4:それぞれの項目に必要な処理を具体的に考える
5:項目ごとに完成させる
6:組み合わせる
7:ひとまず完成

取りあえず1〜4まで考えて下さい。



MillkeySoftware

リンク

2017/1/24(Tue) 09:31:42|NO.78035

ワードは縦と横となっているので縦と横の文字が重なるところを同じ文字にすればいいだけ。
■■あ■■
■■い■■
あかうんと
■■え■■
■■お■■
この場合、縦ワードの「あいうえお」の3文字目の「う」が重なる文字で、横ワードの「あかうんと」の3文字目の「う」が重なる文字。
んで、問題の単語を単語帳から検索するには、3文字目に「う」がある5文字の単語という事になるよね。



ぜろ

リンク

2017/1/24(Tue) 13:13:19|NO.78036

ブロックを適当に並べられるプログラムは作れたんですけど、その単語帳からとってきて重ねて表示するのはまだ僕はできたことないです。
それと、並べた文字を単語として判定するのもできたことないです。



syam

リンク

2017/1/24(Tue) 14:14:12|NO.78037

「単語帳からクロスワードパズルを自動的に作る」
「表示したパズルを解くゲーム」
たぶん、どちらもやりたいのだと思うのですが、まずはゲーム部分だけに集中して作ってみてはどうでしょうか?
解くべきパズルは毎回同じものをファイルから読み込むなりスクリプト内で直接代入するなりしておいて、ゲーム部分ができたらそこを自動的に作るプログラムも足せばよいのです。



Drip

リンク

2017/1/25(Wed) 00:38:53|NO.78055

Dripです。

ぜろさん、こんにちは。
syamさんの仰るとおり、確かにご質問の意味がゲームを作りたいのか、
それともクロスワードを自動生成して画像を表示したいだけなのかが釈然としませんが、
今回はクロスワードの自動生成に焦点を絞って解説させていただこうと思います。

まずクロスワードのルールからになりますが、単語がパズル内に存在できる条件として、
・パズルからはみ出ない・全ての単語はどこか別の単語と必ずクロスしている
・単語の頭文字と末尾文字は他の単語に融合してはならない
などがあり、これらを全て満たして作成しなければなりません。
かなり複雑であり、初心者には少々ハードな解説になることを覚悟されてください。

以下にランダムにクロスワードを作成するサンプルを示します。処理の流れとしては、
まずinit命令で単語帳をHSP内の適当なファイルから取得し、画面サイズでパズルフィールドを初期化します。
次に再起のシードとなる最初の単語をパズルフィールド中央付近にmake命令で配置し、
単語の各文字から枝のように別の単語をmake命令内でmake命令を再起的に呼び出して生やしていきます。
この単語を生やすときに、make命令内からchk命令を呼び出し、その単語が存在できるか事前にチェックします。
これを理解するためには、まず「モジュール」と「再起」を理解している必要があります。
(そういうのを使わないで!となりますと、更に複雑なプログラムが必要になります。)
スクリプトにコメントをかなり詳しく書きましたが、初心者にとっては非常にハードルが高いものになるかと思います。
まずは目的のハードルを下げ、どういう順序でプログラムをすれば何ができそうか、
順を追って考えながら学習することをお勧めします。スクリプトの意味がわからなくても、流れだけでも理解するために、
★で強調されたコメントだけ読んでいくのも良いかもしれません。…ご健闘をお祈りします^^;;;

#module cross #define size 20 //マスのサイズ(小さいほど広くなる(可視性を加味して最低14くらいまで)) #define maxnest 2 //再起最大ネスト(多いほど複雑なパズルになる可能性を秘める) //★init 命令:単語とパズルフィールドを初期化する。 #deffunc init //★変数mypadに単語帳を作成する。(mypadの配列に200こくらいの単語を代入する) sdim data,30000 ts=dir_exe+"\\hsplet\\lib\\jl1.0-LICENSE.txt" exist ts:if strsize>-1:{ //HSPLetのライセンスファイルが見つかったのでそれを単語帳にする bload ts,data }else{ //Android関連のライセンスファイルが見つかればそれを単語帳にする ts=dir_exe+"\\android\\extlib\\src\\libpng\\LICENSE" exist ts:if strsize<1:dialog "単語データが格納されているテキストファイルがありません。":end bload ts,data } strrep data,"\n"," ":split data," ",word //テキストファイルの改行をスペースに置換してword配列に単語を取得 max=0 repeat stat:id=cnt if strlen(word(id))<2:continue //短すぎる単語排除 dis=0 //半角小文字以外を持つ単語を排除 repeat strlen(word(id)) if peek(word(id),cnt)<'a' | peek(word(id),cnt)>'z':dis=1:break loop:if dis:continue //既に登録済みの単語は排除 repeat max if mypad(cnt)=word(id):dis=1 loop:if dis:continue //過去形とか複数形っぽいのを排除 t=peek(word(id),strlen(word(id))-1):if t='s'| t='d':continue mypad(max)=word(id):max++ if max>=200:break loop //★パズルフィールドを画面サイズとマスサイズを元に初期化する fldSz=ginfo_winx/size , ginfo_winy/size sdim pzl,2,fldSz(0),fldSz(1) //マスの文字を管理する変数 dim used,max //使用済みの単語を管理する変数 dim idx,max //含めたい文字が単語内の何文字目に含まれるか管理する変数 return //★chk 命令: //パズルの座標nx,nyにある文字を含む単語を単語帳の中から調べ、その文字を含む場合、 //何文字目にその文字を含むか調べ、変数idxの配列にインデックスを代入する。 //ただし、その文字を持っていたとしても、パズルに配置しようとした場合、 //他の単語とぶつかって文字の矛盾が発生したりパズルからはみ出る場合はインデックスに-1を代入する。 //また、他の単語と末端が融合されてしまうような場合や、一度使われている単語も無条件に-1を代入する。 //angに単語を配置しようとしている方向(0:横 0以外:縦)を指定して実行すること。 //この命令が成功すると配置可能な単語をいくつ発見できたかをstatに返す。 #deffunc chk int nx,int ny,int ang,local myid pt=nx,ny //調査対象パズル座標X,Y(変数に入れておくことで縦・横の座標を参照しやすくなる) if pzl(nx,ny)="":return 0 //調査座標に文字が何も入っていなければ失敗とする。(≒含めたい文字が存在しない) count=0 //いくつの有効単語を発見できたか管理する変数 repeat max //単語帳に登録された全単語に対して調査を行う。 if used(cnt):idx(cnt)=-1:continue //一度使われた単語はもう使えない。 myid=cnt //調査対象単語の配列ID idx(cnt)=instr(mypad(myid),0,pzl(nx,ny)) //idxに調査対象文字が何文字目に含まれるかidxの配列に代入する。 if idx(cnt)>-1:{ //もし単語が調査対象文字を含んでいれば //★単語を配置しようとするとフィールドをはみ出てしまう場合は除外する if pt(ang)-idx(myid)<0 | pt(ang)-idx(myid)+strlen(mypad(myid))>=fldSz(ang):idx(myid)=-1:continue //★単語を配置しようとすると頭文字が他の単語に融合してしまうような場合は除外する if pt(ang)-idx(myid)>0:{ //単語の頭文字はフィールド末端より1文字以上内側に配置される if pzl(nx-(ang=0)*(idx(myid)+1),ny-(ang!0)*(idx(myid)+1))!"":{ //頭文字の一つ前に何らかの文字がある idx(myid)=-1:continue //融合してしまう配置はできないのでこの単語を除外する } } //★単語を配置しようとすると末尾文字が他の単語に融合してしまうような場合は除外する if pt(ang)-idx(myid)+strlen(mypad(myid))<fldSz(ang):{ //単語の末尾はフィールド末端より1文字以上内側に配置される //末端文字の一つ向こうに何らかの文字があるかチェック。あれば除外対象。 if pzl(nx+(ang=0)*(-idx(myid)+strlen(mypad(myid))),ny+(ang!0)*(-idx(myid)+strlen(mypad(myid))))!"":{ idx(myid)=-1:continue //融合してしまう配置はできないのでこの単語を除外する } } //★単語を配置しようとすると他の単語にかぶさって、矛盾してしまうような単語は除外する dis=0 repeat strlen(mypad(myid)) //単語の文字数分チェック if pzl(nx+(ang=0)*(cnt-idx(myid)),ny+(ang!0)*(cnt-idx(myid)))!"":{ //配置しようとした場所になんらかの文字がある //その文字はこれから代入しようとしている文字と異なるかチェック。異なれば除外対象。 if pzl(nx+(ang=0)*(cnt-idx(myid)),ny+(ang!0)*(cnt-idx(myid)))!strmid(mypad(myid),cnt,1):{ dis=1:break //他の単語にかぶさって単語が配置できないのでこの単語を除外する } } loop if dis:idx(myid)=-1:continue //除外が申請されているのでこの単語を除外する //★無事、ここまで来る事ができた単語のidx(cnt)には何文字目に含めたい文字(pzl(nx,ny)の文字)を持つかが代入されている。 count++ } loop return count //★make 命令 //単語帳のnid番目の単語をnx,nyの座標にangの方向(0:横 1:縦)に配置する。 //nestにこの関数を実行するネストを指定する。(モジュール外からの利用では無視してよい) #deffunc make int nid,int nx,int ny,int ang,int nest,local myid if used(nid):return //申請された単語が既に使用済みの単語の場合、配置を拒否する。 used(nid)=1 //これから書き込む単語を使用済みとして登録する。 //★単語をパズルフィールドに書き込む repeat strlen(mypad(nid)) if ang=0:{ //横書き pzl(nx+cnt,ny)=strmid(mypad(nid),cnt,1) }else{ //縦書き pzl(nx,ny+cnt)=strmid(mypad(nid),cnt,1) } ;redraw 0:draw:redraw 1:await 30 //★★ このコメントを解除するとどのように作成されていくかが見れます。 ★★ loop //★融合対策として単語の頭と末尾にダミーの文字を配置 if ang=0:{ //横書き if nx>0:pzl(nx-1,ny)="*" //単語の頭と末端にダミーの文字を配置(融合対策) if nx+strlen(mypad(nid))<fldSz(0):pzl(nx+strlen(mypad(nid)),ny)="*" }else{ //縦書き if ny>0:pzl(nx,ny-1)="*" //単語の頭と末端にダミーの文字を配置(融合対策) if ny+strlen(mypad(nid))<fldSz(1):pzl(nx,ny+strlen(mypad(nid)))="*" } //★再起処理を行い、単語の文字から枝を生やす(単語を差し込む) repeat strlen(mypad(nid)) //単語の文字数分繰り返す if ang=0:{ //横書きの場合 if (cnt+nx)\2=0 & ny\2=0 & nest<maxnest:{ //見た目の問題で枝を生やせるのは偶数マスのみ、再起ネスト範囲内のみ処理。 chk nx+cnt,ny,1:if stat:{ //配置できそうな単語を発見できた場合 repeat 10 //その中からランダムに単語を選出する。10回トライし、適当な単語が見つからなければ諦める。 myid=rnd(max):if idx(myid)>-1:break loop if idx(myid)>-1:{ //無事単語を選出できた場合、単語をパズルに配置する make myid,nx+cnt,ny-idx(myid),1,nest+1 } } } }else{ //縦書きの場合 if nx\2=0 & (cnt+ny)\2=0 & nest<maxnest:{ //見た目の問題で枝を生やせるのは偶数マスのみ、再起ネスト範囲内のみ処理。 chk nx,ny+cnt,0:if stat:{ //配置できそうな単語を発見できた場合 repeat 10 //その中からランダムに単語を選出する。10回トライし、適当な単語が見つからなければ諦める。 myid=rnd(max):if idx(myid)>-1:break loop if idx(myid)>-1:{ //無事単語を選出できた場合、単語をパズルに配置する make myid,nx-idx(myid),ny+cnt,0,nest+1 } } } } loop return //★draw 命令 //パズルを描画する #deffunc draw font msgothic,size-4 repeat fldSz(0)*fldSz(1) //全マス描画する if pzl(cnt\fldSz(0),cnt/fldSz(0))!"" & pzl(cnt\fldSz(0),cnt/fldSz(0))!"*":{ //マスに何かの単語が含まれる場合 pt=cnt\fldSz(0)*size,cnt/fldSz(0)*size //描画しようとしている座標 pos pt,pt(1) //マスを描画 color 128,128,128:boxf pt,pt(1),pt+size,pt(1)+size color 255,255,255:boxf pt+2,pt(1)+2,pt+size-2,pt(1)+size-2 pos -100,-100:mes pzl(cnt\fldSz(0),cnt/fldSz(0)) //文字の横サイズをginfo_mesx取得 color:pos pt+(size-ginfo_mesx)/2+2,pt(1)+2:mes pzl(cnt\fldSz(0),cnt/fldSz(0)) //文字をマスの中央に描画 } loop return #global //★お疲れ様でした。メイン処理ここからです。 //★最初に選ばれた単語が極端に短かったり、運が悪いと単語が1つ描画されて終わったりします^^;;; randomize //乱数初期化 init //単語帳を読み込み、パズルフィールドを初期化 //★真ん中あたりに最初の単語を配置(偶数マスしか枝が生えないので初期座標に注意) make rnd(max@cross),fldSz@cross(0)/4*2-2,fldSz@cross(1)/4*2 draw //パズルを描画 color 255,255,255:boxf 0,0,ginfo_winx,16 font msgothic,14,1:color:pos 2,2:mes "何度も実行してどのようなパターンが生まれるか試してみましょう。"



ぜろ

リンク

2017/1/25(Wed) 05:45:39|NO.78057

おお すばらしいアドバイスとサンプルをありがとうございます。



ONION software Copyright 1997-2023(c) All rights reserved.