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


HSPTV!掲示板


未解決 解決 停止 削除要請

2012
0711
YSRなんでここで検索してもαβ法についての投稿が無いのよ・・・1未解決


YSR

リンク

2012/7/11(Wed) 19:47:20|NO.47614

最近オセロのプログラムを書いている。
で、αβ法……の前にとりあえずミニマックス法を実装しようと思っているが上手くいかない。

ソース一部↓

//思考ルーチン本体 #defcfunc board_value array board //盤面の静的評価 dim stones,2 :stonecount board,stones return stones(turn@-1)-stones(2-turn@) #defcfunc min_max array board, int turn, int depth //ミニマックス法による局面の評価 if depth=0 :return board_value(board) dim canmove,60,2 :canmovecount board,turn,canmove :cmnum_=stat if turn=turn@ { max=-99 for k,0,cmnum_ dim board_,10,10 :memcpy board_,board,400 move board_,turn,canmove(k,0),canmove(k,1) score=min_max(board_,3-turn,depth-1) if score>max :max=score next return max } else { min=99 for k,0,cmnum_ dim board_,10,10 :memcpy board_,board,400 move board_,turn,canmove(k,0),canmove(k,1) score=min_max(board_,3-turn,depth-1) if score<min :min=score next return min } #global #module #deffunc comthink array board, int turn, var mx, var my, int comkind //[関数]COMの思考ルーチン(指し手はmx,myに直接代入) ;正直言って、頓死or一手しか無かったら思考もクソもないよね canmovecount board,turn,canmove@ :cmnum=stat if cmnum=1 :mx=canmove@(0,0) :my=canmove@(0,1) :return sdflg=1 for k,0,cmnum if suddendeathflg(board,turn,canmove@(k,0),canmove@(k,1))=0 :sdflg=0 :_break next if sdflg=1 :mx=canmove@(0,0) :my=canmove@(0,1) :return ;思考ルーチン記述部 switch comkind //(中略) case 4 //最大数(3手読み) canmovecount board,turn,canmove@ :cmnum=stat dim board_,10,10 mx=0 :my=0 :max=-99 for k,0,cmnum memcpy board_,board,400 move board_,turn,canmove@(k,0),canmove@(k,1) rvnum=min_max(board_,3-turn,2) if rvnum>max { mx=canmove@(k,0) :my=canmove@(k,1) if suddendeathflg(board,turn,mx,my)=0 :max=rvnum } next swbreak swend return #global
※盤面はboard(0〜9,0〜9)の中のboard(1〜8,1〜8)に、黒・白・無しを1・2・0で管理。
 1周り大きめなのは番兵用(turnも黒は1、白は2)。comthinkは参照渡ししたmx,myに直接指し手を返している
「stonecount board,stones」……
 board内の白石・黒石数を取得してstones(0),(1)に返す(arrayで渡している)
「canmovecount board,turn,canmove」……
 canmove({番号},{横・縦の区別})にstat(返り値)だけ合法手の座標を返す
suddendeathflg(board,turn,{横座標},{縦座標})……
 その手を打つと次の相手のターンで自分が全滅させられるかを示す関数。1でアウト、0でセフセフ
move board,turn,{横座標},{縦座標}……
 その座標に石を打って返す(boardにturnの色の石を座標に置き、返す処理をarray渡しのboardに行う)

デバッガで追いかけたところ、どーもmin_max関数内のmemcpyが効いてないっぽい("board"がboard_にコピーされない)。
どう考えてもarrayで渡しているせいだと思うんだけど、そもそも配列相手じゃ参照渡ししか無いっぽいってのが……
(普通の変数なら、varとint・str等で参照渡しと値渡しを使い分けられる)
ググってもHSPのサンプルなんか出ないし、localとかモジュール変数?ってのはよく分からんし……
でも、1手読み(文中「min_max(board_,3-turn,2)」を「min_max(board_,3-turn,1)」に書き換える)は普通に動くんだぜ?
誰かご教示ください。お願いします。

あ、途中で

#global #module
と書いているのは変数被るからね。「同一モジュール内で使った変数が、
同一モジュール内の他の関数・命令で書き換えできる」とか、わけが分からないよ……



この記事に返信する


check

リンク

2012/7/11(Wed) 20:38:26|NO.47615

動くスクリプトを渡してもらえないとなんともいえないが。
愚痴られてもこっちにもどうしようもない。
別にモジュールに多次元配列を渡したところで機能しなくなるわけじゃないしな。

#module // わざわざモジュールを通してみる #deffunc copyarray array dist, array src, int size memcpy src, dist, size return #global dim array1, 10, 10 c1 = 0 : c2 = 0 repeat 100 array1(c1, c2) = cnt c1++ if (c1 >= 10) : c2++ : c1 = 0 loop dim array2, 10, 10 copyarray array1, array2, 10*10*4 c1 = 0 : c2 = 0 x = 0 : y = 0 repeat 100 pos x, y mes array2(c1, c2) c1++ if (c1 >= 10) : c2++ : c1 = 0 y += 16 if (y >= 480) : x+=60 : y = 0 loop

配列が参照しか渡せないのは仕様だ、あきらめてください。
開発者のおにたま氏のブログにでもコメントすればサポートされるようになる「かも」しれないけれど。
#deffunc constarray arr 見たいに定数の塊として渡されるようになるんじゃないかな。サポートされるとしたら。

#module〜#globalはC/C++の関数と同じものだと考えてはいけません。
#(シャープ)で始まるプリプロセッサなんだから。
実質gosubを使いやすくしたもの。変数の定義という概念がない以上ローカル変数の定義もない。
#deffunc local tmp とすればローカル変数を使えるようになる。

郷に入りては郷に従え、BASICとCの中間のような混沌とした言語使用に頭を抱えるときもあるかもしれないが仕方がない。



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