質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

2回答

2570閲覧

【再】オセロプログラムの添削をお願いします

the_saidaa

総合スコア27

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2015/10/17 14:42

編集2015/10/17 14:47

前回の質問では、オセロプログラムを添削していただき本当にありがとうございました。
自身の無知も相まって、前回は非常に多数のご指摘を受けたため、
その点をなるべく修正したものを、もう一度投稿することに致しました。

しかし大変恐縮ながら、前回とは違い、今回全てのソースコードが完成しておりません。
主な理由として、「処理を分ける」内容が実現できなかったことが挙げられます。

Javaにある継承ができれば解決できそうなのですが、
そのような機能が備わっていないJavaScriptでうまくまとめる方法が分からなかったのです。
また、「グローバル変数を減らす」内容も実現できたとは言い難い状態です。

未完成なコードでお恥ずかしい限りですが、「自分だったらこう書く」といったような点があれば、
些細な内容でも全く構いませんので、ご指摘のほどよろしくお願いいたします。
###ソースコード

HTML

1<!DOCTYPE html> 2<html> 3<head> 4<meta http-equiv="content-language" content="ja"> 5<meta charset="UTF-8"> 6</head> 7 8<body> 9<div id="othello"></div> 10<script type="text/javascript" src="othello.js"></script> 11</body> 12</html>

JavaScript

1// 黒と白の画像を変数に格納 2var STONE_BLACK = 'url("http://i.imgur.com/CLEpdaJ.png")'; 3var STONE_WHITE = 'url("http://i.imgur.com/VZgXNBM.png")'; 4 5var BLACK = 1; 6var WHITE = 2; 7 8var turn = BLACK; // 先手は黒 9 10/* 10×10のフィールドを作る */ 11var field = [ 12 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9], 13 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 14 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 15 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 16 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 17 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 18 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 19 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 20 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 21 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 22]; 23/* ------------------------------------------------------- */ 24// 黒と白の初期配置 25function setStone() { 26 field[4][5] = BLACK; 27 field[5][4] = BLACK; 28 field[4][4] = WHITE; 29 field[5][5] = WHITE; 30} 31 32// 盤面を描写する処理 33function showBoard() { 34 var element = document.getElementById("othello"); 35 var df = document.createDocumentFragment(); 36 37 for(var y = 1; y <= 8; y++){ 38 for(var x = 1; x <= 8; x++) { 39 var board = document.createElement("div"); 40 board.id = "p" + y + x; 41 board.setAttribute("style", "border: 1px solid black; float: left; height: 60px;\ 42 width: 60px; background: green; style: pointer"); 43 board.addEventListener("click", clickEvent, false); 44 45 // 8ピース毎に改行する 46 if((x % 8) == 1) board.style.clear = "both"; 47 48 // 初期配置の黒と白を描写する 49 if(field[y][x] !== 0){ 50 var image = (field[y][x] == BLACK) ? STONE_BLACK : STONE_WHITE; 51 board.style.backgroundImage = image; 52 } 53 df.appendChild(board); 54 } 55 } 56 element.appendChild(df); 57} 58 59// 現在の手番が石を置けるかどうか判別する 60function isReversible(y, x, player) { 61 var opponent = (player == BLACK) ? WHITE : BLACK; 62 var delta_y = [-1, -1, 0, 1, 1, 1, 0, -1]; 63 var delta_x = [0, 1, 1, 1, 0, -1, -1, -1]; 64 65 // 選択した箇所に既に石が置かれている場合、以降の処理を行わない 66 if(field[y][x] !== 0) return false; 67 68 // 選択した箇所の周囲8箇所に石が置けるかどうか判別する 69 for(var pos = 0; pos < 8; pos++){ 70 var n = y + pos_y[pos]; 71 var m = x + pos_x[pos]; 72 73 // 周囲8箇所に相手の石がない場合、以降の処理を行わない 74 if(field[n][m] !== opponent) continue; 75 76 // 周囲8箇所の延長線上に相手の石がある間繰り返す 77 while(field[n][m] === opponent){ 78 n += pos_y[pos]; 79 m += pos_x[pos]; 80 81 // 相手の石を挟んで自分の石がある場合、trueを返す 82 if(field[n][m] === player) return true; 83 } 84 } 85} 86 87function stoneReverse() { 88 /* TODO: 89 * 石をひっくり返す処理 90 * (isReversible()メソッドとソースコードはほぼ同じ) */ 91} 92 93function stoneNavigation() { 94 /* TODO: 95 * 自分の石を置くことができるマス目の色を変更する 96 * (field[1][1]~field[8][8]まで全てのマス目に対して 97 * "isReversible();"を実行、trueが返れば背景色変更) */ 98} 99 100function clickEvent() { 101 var element = document.getElementById(this.id); 102 103 // 設定したdividから配列の要素を得る 104 var y = parseInt(element.id.substr(-2, 1)); 105 var x = parseInt(element.id.substr(-1, 1)); 106 107 var check = isReversible(y, x, turn); 108 109 if(check){ 110 stoneReverse(); 111 turn = (turn == BLACK) ? WHITE : BLACK; 112 stoneNavigation(); 113 } 114} 115 116onload = function() { 117 setStone(); 118 showBoard(); 119}

###未完成部分のコードについて
主にstoneReverse()について、具体的な解説をいただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんな風に書き換えてみました。
↓は動作例です。
イメージ説明

javascript

1// 黒と白の画像を変数に格納 2var STONE_BLACK = 'url("http://i.imgur.com/CLEpdaJ.png")'; 3var STONE_WHITE = 'url("http://i.imgur.com/VZgXNBM.png")'; 4 5var BLACK = 1; 6var WHITE = -1; 7 8var turn = BLACK; // 先手は黒 9 10/* 10×10のフィールドを作る */ 11var field = [ 12 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9], 13 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 14 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 15 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 16 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 17 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 18 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 19 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 20 [9, 0, 0, 0, 0, 0, 0, 0, 0, 9], 21 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 22]; 23var DELTAS = [[ 1, -1], [ 1, 0], [ 1, 1], 24 [ 0, -1], [ 0, 1], 25 [-1, -1], [-1, 0], [-1, 1] 26 ]; 27 28function getOpponent(player) { 29 return player * (-1); 30} 31function getImage(player) { 32 return (player === BLACK) ? STONE_BLACK : STONE_WHITE; 33} 34/* ------------------------------------------------------- */ 35// 黒と白の初期配置 36function initField() { 37 for (var y = 1; y <= 8; y++) { 38 for (var x = 1; x <= 8; x++) { 39 field[y][x] = 0; 40 } 41 } 42 field[4][5] = BLACK; 43 field[5][4] = BLACK; 44 field[4][4] = WHITE; 45 field[5][5] = WHITE; 46} 47 48// 盤面の初期化 49function initBoard() { 50 var element = document.getElementById("othello"); 51 var df = document.createDocumentFragment(); 52 var base_style = "border: 1px solid black; float: left; height: 60px; width: 60px; background: green; style: pointer"; 53 54 for (var y = 1; y <= 8; y++) { 55 for (var x = 1; x <= 8; x++) { 56 var cell = document.createElement("div"); 57 cell.id = "p" + y + x; 58 cell.setAttribute("style", base_style); 59 cell.addEventListener("click", clickEvent, false); 60 df.appendChild(cell); 61 62 // 8ピース毎に改行する 63 if ((x % 8) === 1) { 64 cell.style.clear = "both"; 65 } 66 } 67 } 68 element.appendChild(df); 69} 70 71function redisplayBoard() { 72 for (var y = 1; y <= 8; y++) { 73 for (var x = 1; x <= 8; x++) { 74 if (field[y][x] !== 0) { 75 putStone(y, x, field[y][x]); 76 } 77 } 78 } 79} 80 81// player が石をおける場所の一覧を得る。 82function getValideHands(player) { 83 var ans = []; 84 var opponent = getOpponent(player); 85 86 for (var x = 1; x <= 8; x++) { 87 for (var y = 1; y <= 8; y++) { 88 // 選択した箇所に既に石が置かれている場合、以降の処理を行わない 89 if (field[y][x] !== 0) { 90 continue; 91 } 92 93 // 選択した箇所からの8つの方向に石が置けるかどうか判別する 94 for (var direction = 0; direction < 8; direction++) { 95 var dy = DELTAS[direction][0]; 96 var dx = DELTAS[direction][1]; 97 var py = y + dy; 98 var px = x + dx; 99 100 // 周囲8箇所に相手の石がない場合、以降の処理を行わない 101 if (field[py][px] !== opponent) { 102 continue; 103 } 104 // 周囲8箇所の延長線上に相手の石がある間繰り返す 105 while (field[py][px] === opponent) { 106 py += dy; 107 px += dx; 108 // 相手の石を挟んで自分の石がある場合、ans に追加する。 109 if (field[py][px] === player) { 110 ans.push([y, x]); 111 } 112 } 113 } 114 } 115 } 116 return ans; 117} 118 119// 現在の指手が [y][x] に石を置けるかどうか判別する。 120function isReversible(y, x, player) { 121 var validhands = getValideHands(player); 122 for (var i = 0; i < validhands.length; i++) { 123 if (validhands[i][0] === y && validhands[i][1] === x) { 124 return true; 125 } 126 } 127 return false; 128} 129 130// [y][x] に player が石を置く処理を行う。 131// 挟んだ石があれば、それをヒックリ返す。 132// (置く位置の妥当性はここではチェックしていない) 133function playHand(y, x, player) { 134 field[y][x] = player; 135 putStone(y, x, player); 136 reverseStones(y, x, player); 137} 138 139// 石をひっくり返す。 140function reverseStones(y, x, player) { 141 var opponent = getOpponent(player); 142 // 選択した箇所からの8つの方向に石が置けるかどうか判別する 143 for (var direction = 0; direction < 8; direction++) { 144 var dy = DELTAS[direction][0]; 145 var dx = DELTAS[direction][1]; 146 var py = y + dy; 147 var px = x + dx; 148 149 // 周囲8箇所に相手の石がない場合、以降の処理を行わない 150 if (field[py][px] !== opponent) { 151 continue; 152 } 153 // 周囲8箇所の延長線上に相手の石がある間繰り返す 154 while (field[py][px] === opponent) { 155 py += dy; 156 px += dx; 157 // 相手の石を挟んで自分の石がある場合、石をひっくり返す。 158 if (field[py][px] === player) { 159 var yy = py - dy; 160 var xx = px - dx; 161 while(field[yy][xx] === opponent) { 162 field[yy][xx] = player; 163 changeStone(yy, xx , player); 164 yy -= dy; 165 xx -= dx; 166 } 167 } 168 } 169 } 170} 171 172// 自分の石を置くことができるマス目の色を変更する 173// field[1][1]~field[8][8]まで全てのマス目に対して 174function showNavigation(player) { 175 var validhands = getValideHands(player); 176 for (var i = 0; i < validhands.length; i++) { 177 var f = getElement(validhands[i][0], validhands[i][1]); 178 f.style.background = "gray"; 179 } 180} 181 182// 自分の石を置くことができるマス目表示を消す。 183function clearNavigation() { 184 for (var y = 1; y <= 8; y++) { 185 for (var x = 1; x <= 8; x++) { 186 if (field[y][x] === 0) { 187 var f = getElement(y, x); 188 f.style.background = "green"; 189 } 190 } 191 } 192} 193 194// [y, x] に相当する DOM の element を得る。 195function getElement(y, x) { 196 return document.getElementById("p" + y + x); 197} 198 199// 石を置く。 200function putStone(y, x, player) { 201 var f = getElement(y, x); 202 f.style.backgroundImage = getImage(player); 203} 204 205// 石をひっくり返す。 206function changeStone(y, x, player) { 207 putStone(y, x, player); 208 // TODO: 石をひっくり返すアニメーションをするともっと良い。 209 // jquery を使うとアニメーションが簡単にできる。 210} 211 212// マウスクリック時の処理。 213// クリック位置が妥当なら、石をおいて、挟んだ石の反転を行う。 214// クリック位置が不正なら、何もしない。 215function clickEvent() { 216 var element = document.getElementById(this.id); 217 // 設定したdividからfiled の位置を得る。 218 var y = parseInt(element.id.substr(-2, 1)); 219 var x = parseInt(element.id.substr(-1, 1)); 220 221 var check = isReversible(y, x, turn); 222 if (check) { 223 clearNavigation(); 224 playHand(y, x, turn); 225 turn = getOpponent(turn); 226 showNavigation(turn); 227 } 228 debug_show_fields(); 229} 230 231// for debug: fiels[][] の内容を console に表示する。 232function debug_show_fields() { 233 for (var y = 1; y <= 8; y++) { 234 var s = "" + y + ":"; 235 for (var x = 1; x <= 8; x++) { 236 var c = "."; 237 if (field[y][x] === BLACK) { 238 c = "x"; 239 } else if (field[y][x] === WHITE) { 240 c = "o"; 241 } 242 s += c; 243 } 244 console.log(s); 245 } 246} 247 248onload = function() { 249 initBoard(); 250 initField(); 251 redisplayBoard(); 252};

投稿2015/10/18 05:09

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

the_saidaa

2015/10/19 06:00

前回に引き続き、非常に丁寧な回答ありがとうございます。 まだじっくり腰を据えてソースコードと向き合っていないため、 また改めてコメントを追加する予定です。反応が遅くなってしまい申し訳ありません。
guest

0

あくまでもアイデア出しということでご了解ください。

isReversibleは、置けるかチェックするメソッドではなく、
反転するマスを2次元配列のリストで返す内容にすると、
後続のstoneReverseの実装が容易になると思います。

投稿2015/10/17 21:00

TetsujiMiwa

総合スコア1124

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問