|
|
2016/4/15(Fri) 20:24:24|NO.75229
○と×をマス目においていって縦横斜めに3つなどそろったら勝ちという
普通の丸罰ゲームをつくっているのですが、
どうやって揃うことの判定をしたらいいでしょうか。
マス目に番号を当てて、○が入っているか、
×が入っているかの判定はつきます。
|
|
2016/4/15(Fri) 20:50:28|NO.75230
3x3のマスを○と×で埋めるゲームですね。
1列そろうパターンは8パターンしかありませんよね。
これぐらいなら毎回、全ての「そろうパターン」を調べてしまっていいのではないでしょうか?
|
|
2016/4/16(Sat) 14:47:51|NO.75231
答えになっているかはわかりませんが、つくりました。
定数の数値を変更すればプレイヤーの数と縦横の大きさを変えられます。
// 丸三角バツゲーム
// プレイヤー数
// 増やす場合などは msgs_btns もいっしょにかきかえる
#const int NUM_PLAYER 3
// 1行のボタンの数
#const int NUM_BTN_LINE 11
#const int NUM_BTN (NUM_BTN_LINE * NUM_BTN_LINE)
// ボタンサイズ
#const int X_SIZE_BTN 30
#const int Y_SIZE_BTN 30
#const int X_SIZE_WIN (X_SIZE_BTN * NUM_BTN_LINE)
#const int Y_SIZE_WIN (Y_SIZE_BTN * (NUM_BTN_LINE + 1))
#const int LEN_FLAG_BTNS (NUM_BTN / 32 + 1)
// フラグ設定マクロ
#define set_flag_btn(%1,%2) flags_btns((%2)/32, (%1)) |= 1<<((%2)\32)
#define ctype get_flag_btn(%1,%2) ( (flags_btns((%2)/32, (%1)) >> ((%2)\32)) & 1 )
#define del_flag_all_btn(%1) memset flags_btns(0, (%1)),, LEN_FLAG_BTNS * 4
// ボタンが押されたかどうかのフラグ
#define set_flag_pushed_btn(%1) flags_pushed_btns((%1)/32) |= 1<<((%1)\32)
#define ctype get_flag_pushed_btn(%1) ( (flags_pushed_btns((%1)/32) >> ((%1)\32)) & 1 )
#define del_flag_all_pushed_btn memset flags_pushed_btns,, LEN_FLAG_BTNS * 4
// 全部のボタンが押されたかのチェック
#define CHECK_PUSHED_ALL_BTNS _check_pushed_all_btns_( flags_pushed_btns, NUM_BTN)
#module
#defcfunc _check_pushed_all_btns_ array flags, int num,\
local tmp
tmp = 1
repeat num/32
if flags(cnt) != -1 {
tmp = 0 : break
}
loop
return tmp * ((flags(num/32) | (-1 << (num\32))) == -1)
#global
// 変数
dim flags_btns, LEN_FLAG_BTNS, NUM_PLAYER
msgs_btns = "○", "△", "×" // プレイヤーの数に合わせる
dim flags_pushed_btns, LEN_FLAG_BTNS
turn_player = 0
// 画面
screen 0, X_SIZE_WIN, Y_SIZE_WIN,,,, X_SIZE_WIN, Y_SIZE_WIN
objsize X_SIZE_BTN, Y_SIZE_BTN
repeat NUM_BTN
pos X_SIZE_BTN * (cnt\NUM_BTN_LINE), Y_SIZE_BTN * (cnt/NUM_BTN_LINE)
button gosub "", *check_btn
loop
pos 0, ginfo_cy
objsize X_SIZE_WIN, Y_SIZE_BTN
button gosub "初期化", *init_btns
gosub *init_btns
stop
// 初期化
*init_btns
repeat NUM_BTN
objprm cnt, ""
loop
repeat NUM_PLAYER
del_flag_all_btn cnt
loop
del_flag_all_pushed_btn
turn_player = 0
gosub *title_window
return
// ウィンドウタイトル
*title_window
title msgs_btns(turn_player) + "の番"
return
// ダイアログメッセージの作成
*make_msg_dialog
msg_dialog = ""
is_win--
if is_win {
msg_dialog = msgs_btns(turn_player) + "のかち!\n" + is_win + "本そろいました"
}else{
msg_dialog = "引き分け!"
}
return
// ボタンにチェック
*check_btn
idx_btn = stat
do
if get_flag_pushed_btn(idx_btn) : _break
set_flag_pushed_btn idx_btn
set_flag_btn turn_player, idx_btn
objprm idx_btn, msgs_btns(turn_player)
gosub *check_win
// 結果表示
if is_win == 0 : is_win = CHECK_PUSHED_ALL_BTNS : else :is_win++
// 引き分けまたはかち
if is_win {
gosub *make_msg_dialog
dialog msg_dialog
gosub *init_btns
_break
}
turn_player++
if turn_player == NUM_PLAYER : turn_player=0
until
gosub *title_window
return
// 勝ち判定
*check_win
is_win = 0
// 横の判定
if get_flag_btn(turn_player, idx_btn - (idx_btn \ NUM_BTN_LINE)) {
is_win ++
repeat NUM_BTN_LINE, idx_btn - (idx_btn \ NUM_BTN_LINE)
if get_flag_btn(turn_player, cnt) == 0 {
is_win -- : break
}
loop
}
// 縦の判定
if get_flag_btn(turn_player, idx_btn \ NUM_BTN_LINE) {
is_win ++
repeat NUM_BTN_LINE
if get_flag_btn(turn_player, cnt*NUM_BTN_LINE + (idx_btn \ NUM_BTN_LINE)) == 0 {
is_win -- : break
}
loop
}
// 左斜めの判定
if (idx_btn / NUM_BTN_LINE) == (idx_btn \ NUM_BTN_LINE) {
is_win ++
repeat NUM_BTN_LINE
if get_flag_btn(turn_player, cnt*NUM_BTN_LINE + cnt) == 0 {
is_win -- : break
}
loop
}
// 右斜めの判定
if (idx_btn / NUM_BTN_LINE) == (NUM_BTN_LINE - (idx_btn \ NUM_BTN_LINE) -1) {
is_win ++
repeat NUM_BTN_LINE
if get_flag_btn(turn_player, cnt*NUM_BTN_LINE + (NUM_BTN_LINE - cnt -1)) == 0 {
is_win -- : break
}
loop
}
return

| |
|
2016/4/16(Sat) 21:50:58|NO.75233
ありがとうございます。
Noapさんのスプりクトですが、残念ながら実行
できませんでした。
結果レポート
#HSP script preprocessor ver3.4 / onion software 1997-2014(c)
#Use file [hspdef.as]
#Error:symbol in use [int] in line 7 [???]
#Fatal error reported.
スプりクトを参考にやってみます。
|
|
2016/4/16(Sat) 23:06:22|NO.75235
>#HSP script preprocessor ver3.4 / onion software
HSP3.5β3で#constにint指定が追加されたので3.4じゃ動かない
>2016/01/19 3.5 beta3
>[hspcmp] #constの後に「double」「int」の型を指定できるように修正
|
|
2016/4/17(Sun) 13:30:51|NO.75238
Dripです。
yuyuさん、こんにちは。
可読性を加味してどこまで簡素化できるか挑戦したくなったので作ってみました^^;
参考になれば幸いです。
#define max 3 //縦横マスの数
#define btnsz 64 //ボタンサイズ
objsize btnsz,btnsz //ボタンのサイズを設定
font "",btnsz/2:objmode 2 //ボタンの文字を大きくしておく
dim masu,max*max //マスの状態を管理する変数(0:空白 1:○ 2:× )
repeat max*max //ボタンを正方形に配置
pos cnt\max*btnsz,cnt/max*btnsz
button "",*push
loop
stop
*push //★ボタンが押されたときの処理
id=stat //押されたボタンIDがstatに返るのでidにボタンIDを確保しておく
objprm id,"○" //押されたボタンを○に書き換える
masu(id)=1 //押されたボタンのIDと同じmasuの配列に情報を反映しておく(1が○)
objenable id,0 //押されたボタンをもう押せなくする
prm=1:gosub *chk //○が並んだか判定する
if ans:mes "○のかち!":goto *gameset //○が並んでたらゲームセット
repeat max*max,rnd(max*max) //適当に敵が× を配置する処理
id=cnt\(max*max) //調べるマスのid
if masu(id)=0:{ //マスが空白だったら配置処理
objprm id,"×" //ボタンを× に書き換える
masu(id)=2 //ボタンのIDと同じmasuの配列に情報を反映しておく(2が× )
objenable id,0 //敵が押したボタンをもう押せなくする
prm=2:gosub *chk //× が並んだか判定する(結果をansに代入、ansが1なら並んだ)
break
}
loop
if ans:mes "×のかち!":goto *gameset //× が並んでたらゲームセット
if prm!2:mes "引き分け!":goto *gameset //敵が配置できなかったのでゲームセット
stop
*chk //★prm(1:○ 2:× )の記号が並んでるか判定してansに結果を返すサブルーチン
ans=0,0,0 //ansが1になればprmの記号が並んだことを示す
//ans(1)は左上から右下に向かってprmの記号が斜めに並んだ量
//ans(2)は右上から左下に向かってprmの記号が斜めに並んだ量
repeat max
id=cnt //縦横方向の検索シードとなる数値
ans(3)=0,0 //ans(3)は縦に向かってprmの記号が並んだ量(シード毎にリセット)
//ans(4)は横に向かってprmの記号が並んだ量(シード毎にリセット)
repeat max
if masu(id+cnt*max)=prm:ans(3)++ //縦に並んでる数をカウント
if masu(id*max+cnt)=prm:ans(4)++ //横に並んでる数をカウント
loop
if ans(3)=max | ans(4)=max:ans=1:break //縦、あるいは横にprmの記号が全て並んだらansを1にして処理終了
if masu(cnt+cnt*max)=prm:ans(1)++ //左上から右下に向かってprmの記号が並んだ数をカウント
if masu(max-cnt-1+cnt*max)=prm:ans(2)++ //右上から左下に向かってprmの記号が並んだ数をカウント
loop
if ans(1)=max | ans(2)=max:ans=1 //斜めにprmの記号が全て並んだらansを1にする
return
*gameset //★ゲームセット、全てのボタンを押せなくする
repeat max*max:objenable cnt,0:loop
stop

| |
|
2016/4/19(Tue) 19:42:45|NO.75270
んじゃ私は勝ち負けの判定が特殊なものを書きましょか。
仕組みがわかるともう少しループの回数をへらせるはず、、、
#enum XO_STATE_NONE = 0
#enum XO_STATE_X
#enum XO_STATE_O
#enum XO_PLAYER_MAX
max = 3 // 縦横の数,奇数しか対応してないれす
buttonWidth = 30 // ボタンの大きさ
buttonHeight = 30
xoText = "", "×", "○" // 表示する文字
playerXO = XO_STATE_X // 最初の状態
playerWon = 0
dim xPlayerCount, max, XO_PLAYER_MAX // x が押された数
dim yPlayerCount, max, XO_PLAYER_MAX // y が押された数
dim xoXYFromButtonId, max * max // x と y からボタンIDを取得
dim xoButtonIdList, max, max // ボタンIDから y*max+x を取得
dim xoState, max, max // ボタンの状態
screen 0, buttonWidth * max, buttonHeight * max + buttonHeight
objsize buttonWidth, buttonHeight
for i, 0, max, 1
repeat max
pos cnt*buttonWidth, i*buttonHeight +buttonHeight/2
button gosub xoText.0, *pushedButton
xoButtonIdList( cnt, i ) = stat
xoXYFromButtonId(stat) = i*max + cnt
loop
next
objsize buttonWidth*max, buttonHeight/2
pos 0
button gosub "最初から", *init
pos 0, 0
button gosub ""+ xoText.playerXO +"の番です", *dummy :displayId = stat
objenable displayId, 0
stop
*dummy
return
*init
// 初期化
for i, 0, max, 1
repeat XO_PLAYER_MAX-1
xPlayerCount(i, 1+cnt) = 0
yPlayerCount(i, 1+cnt) = 0
loop
repeat max
objprm xoButtonIdList( cnt, i ), xoText.XO_STATE_NONE
objenable xoButtonIdList( cnt, i ), 1
xoState( cnt, i ) = XO_STATE_NONE
loop
next
objprm displayId, ""+ xoText.playerXO +"の番です"
playerWon = 0
allCount = 0
return
*pushedButton
buttonId = stat
objprm buttonId, xoText.playerXO
objenable buttonId, 0
allCount++
// プレイヤーの押した場所を記録
x = xoXYFromButtonId(buttonId)\max
y = xoXYFromButtonId(buttonId)/max
xoState( x, y ) = playerXO
// プレイヤーがその列を押した回数を記録
xPlayerCount( x, playerXO )++
yPlayerCount( y, playerXO )++
repeat XO_PLAYER_MAX-1, 1
checkWin cnt
if stat {
objprm displayId, ""+ xoText(cnt) +" の勝ち"
repeat max*max
objenable xoButtonIdList(cnt\max, cnt/max), 0
loop
break
}
loop
if playerWon :return
if allCount == max*max {
objprm displayId, "引き分けです"
return
}
playerXO = ((playerXO-1)+1)\(XO_PLAYER_MAX-1)+1
objprm displayId, ""+ xoText.playerXO +"の番です"
return
#deffunc checkWin int checkState
playerWon = 0
// 縦横の判定 (プレイヤーがその列を押した回数で判定)
repeat max
if max == xPlayerCount(cnt, checkState) || max == yPlayerCount(cnt, checkState) {
playerWon = 1
break
}
loop
if playerWon :return 1
// 斜めの判定 (中央と斜めの反対を見るだけでいい)
// プレイヤーが中央を取ってない場合は判定すらしない
if checkState == xoState( max/2, max/2 ) {
// 一つは x と y が同じ場所
slantCount = 0
repeat max/2
if checkState == xoState( cnt, cnt ) :slantCount++
if checkState == xoState( max-1-cnt, max-1-cnt ) :slantCount++
loop
if max-1 == slantCount :playerWon = 1 :return 1
// もう一つは x と y を足して max-1 の場所、かつ x と y が反転している場所
slantCount = 0
repeat max/2
if checkState == xoState( cnt, max-1-cnt ) :slantCount++
if checkState == xoState( max-1-cnt, cnt ) :slantCount++
loop
if max-1 == slantCount :playerWon = 1 :return 1
}
return 0

| |
|