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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

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

Q&A

解決済

1回答

3865閲覧

JavaScript 二次元配列の要素比較

michael-ilcsy

総合スコア180

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

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

0グッド

0クリップ

投稿2018/05/07 14:04

前提・実現したいこと

あみだくじ
上記のようなあみだくじをランダムに生成し、クリックで横棒を消したり出したりするのが目標です。現在クリックで横棒を出せるところまでできていて、今は横棒を消す処理と横棒同士で繋がらないようにする処理をするための配列検索で詰まっています。

発生している問題・エラーメッセージ

今回横棒の情報を二次元配列で[左の棒(0~11),右の棒(0~11),y座標]という感じで以下のように配列に保管しています。

コンソールログ 0:(3) [0, 1, 90] 1:(3) [0, 1, 110] 2:(3) [0, 1, 190] 3:(3) [0, 1, 210] 4:(3) [0, 1, 230] 5:(3) [0, 1, 250] 6:(3) [0, 1, 290] 7:(3) [0, 1, 350] 8:(3) [0, 1, 370] 9:(3) [0, 1, 410] 10:(3) [1, 2, 150] 以下略

クリックで新しい横棒を生成するときに左右に横棒があると繋がってしまうので、左右に横棒がないときにだけ新しく生成したいのですが
indexOf([0, 1, 230])のように要素を検索しようとしても上手くいかず調べたところ配列で検索できないとのことで困っています。
後々横棒を消したり生成したりするたびに配列の最後にpushで入れたりするので↑のように綺麗に並んでるわけではないので、完全一致で検索できる方法がないとだめなんじゃないかなと思っています。
[a,b,y]のように配列で検索できる方法があるのか、もしくはまた違うアプローチがあるのかどうかお助け願いたいです
以下長いですがJSとhtmlのソース

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4<meta charset="UTF-8" /> 5<title>あみだ</title> 6<link rel="stylesheet" href="test.css" type="text/css" /> 7<script type="text/javascript" src="test.js"></script> 8</head> 9<body> 10<canvas id="stage" width="500" height="500"></canvas> 11</body> 12</html>

javascript

1window.addEventListener( "load", loadFunc, false ); 2 3function loadFunc() { 4 var canvas = document.getElementById( "stage" ); 5 var ctx = canvas.getContext( "2d" ); 6 7 ctx.strokeStyle = "#339933"; 8 ctx.lineWidth = 2; 9 10 for( var i = 0; i < 11; i++ ) { //縦棒描画 11 ctx.beginPath(); 12 ctx.moveTo( 50 + i * 40, 50 ); 13 ctx.lineTo( 50 + i * 40, 450 ); 14 ctx.closePath(); 15 ctx.stroke(); 16 } 17 18 var ran = new Array(); //横棒が重ならないようにするための二元配列 19 for(i=0;i<11;i++) { 20 ran[i] = new Array(); 21 } 22 23 var cross = new Array(); //横棒情報を保管するための二元配列 24 for(var j = 0; j<10;j++){ //横棒描画 25 for(var i = 0; i<19; i++) { 26 ran[j][i] = Math.floor( Math.random() * 2 ); 27 if (j == 0) { 28 if(ran[j][i]==0) { 29 draw(i, j);; 30 } 31 } else { 32 if(ran[j-1][i]==0) { 33 } else { 34 if(ran[j][i]==0) { 35 draw(i, j);; 36 } 37 } 38 } 39 } 40 } 41 var x = 0; 42 var y = 0; 43 var tate = 0; 44 var yoko = 0; 45 function onClick(e) { 46 var rect = e.target.getBoundingClientRect(); 47 x = e.clientX - rect.left; 48 y = e.clientY - rect.top; 49 for(var i=0;; i++) { 50 var leftLine = 50 + i*40; //i+1本目の縦棒 51 var rightLine = 90 + i*40; //i+2本目の縦棒 52 53 if(x<leftLine || x>450) { //枠外をクリックしたら無効に 54 x = -1; 55 break; 56 } 57 if(x>=leftLine && x<rightLine) { //i+1とi+2の間にいたらx座標をi+1本目の縦棒と一緒にする 58 x = leftLine; 59 tate = i; 60 break; 61 } 62 } 63 64 for(var j=0;; j++) { 65 var topLine = 60 + j*20; //70に横線があるとして上下10ずつの空間にいれば70とみなす処理 66 var bottomLine = 80 + j*20; 67 68 if(y<topLine || y>440) { 69 y = -1; 70 break; 71 } 72 if(y>=topLine && y<bottomLine) { 73 y = topLine+10; 74 yoko = j; 75 break; 76 } 77 } 78 79 if(x>0 && y>0) { 80 draw(yoko, tate); 81 } 82 } 83 84 function draw(i, j) { // 描画処理 85 /***↓以下のような検索ではちゃんと検索できない***/ 86 var left = cross.indexOf([j-1, j, 70 + i * 20]); 87 var right = cross.indexOf([j+1, j+2, 70 + i * 20]); 88 89 console.log(left,right) 90 if(left == -1 && right == -1) { 91 ctx.beginPath(); 92 ctx.moveTo( 50 +j * 40 , 70 + i * 20 ); 93 ctx.lineTo( 90 +j * 40, 70 + i * 20 ); 94 ctx.closePath(); 95 ctx.stroke(); 96 cross.push([j, j+1, 70 + i * 20]) //配列に横棒情報保存 97 } 98 } 99 canvas.addEventListener('click', onClick, false); 100}

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

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

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

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

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

guest

回答1

0

ベストアンサー

斜めはないんですね?
重複条件を整理しましょう。

まず、3・4本目間にy座標100の線を引きます[3, 4, 100]
そうすると、何・何本目にy座標100の線が引けなくなりますか?
答えは[2, 3, 100][4, 5, 100]の2種類です。

ポイントはy座標の値が一致するのが必須条件、
更に何本目かの情報が一つでも被っている事が追加条件です。

描画可能ってことで、isDroableという関数でも実装してみましょうかね。
戻り値はBoolean型でtrueが返ってきたら描画しても良い、falseは駄目。

JavaScript

1var isDrowable = function (lines, line) { 2 for (var i = 0; i < lines.length; i++) { 3 var it = lines[i]; 4 // y座標が一致していなければスキップ 5 if (it[2] !== line[2]) continue; 6 // n本目の組み合わせが一つでも被っていればアウト 7 if (it[0] === line[0]) return false; 8 if (it[0] === line[1]) return false; 9 if (it[1] === line[0]) return false; 10 if (it[1] === line[1]) return false; 11 } 12 // 描画駄目な条件を満たして居ないのでこの線は引いても良いと認定されました。 13 return true; 14} 15 16var lines = [ 17 [2, 3, 100], 18 [4, 5, 120] 19]; 20console.log(isDrowable(lines, [1, 2, 100])); // false 21console.log(isDrowable(lines, [2, 3, 100])); // false 22console.log(isDrowable(lines, [3, 4, 100])); // false 23console.log(isDrowable(lines, [4, 5, 100])); // true 24console.log(isDrowable(lines, [1, 2, 120])); // true 25console.log(isDrowable(lines, [2, 3, 120])); // true 26console.log(isDrowable(lines, [3, 4, 120])); // false 27console.log(isDrowable(lines, [4, 5, 120])); // false 28console.log(isDrowable(lines, [5, 6, 120])); // false 29console.log(isDrowable(lines, [6, 7, 120])); // true

動いているようですね。
このように確認してBoolean値を返す関数を作成して置いておくとテストも楽で捗りますね。

なお、この関数はif (it[0] === line[0]) return false;の辺りが重複してダサいので色々と改良しがいがありそうですね。
色んな手段がありますので色々と改良してみてくださいね。

投稿2018/05/07 14:39

miyabi-sun

総合スコア21158

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

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

michael-ilcsy

2018/05/07 15:04

回答ありがとうございます! いろいろと改良して組み込んでみた結果無事動いてほしいように動きました。 [4,5,110]を引くときは[3,4,110]と[5,6,110]があるかどうか調べなきゃいけない! と思い込んでしまっていて、こうやって分解して調べるというのに頭が回っていませんでした。 聞けばなるほどのコロンブスの卵的なものですが、自分でしっかり考えてこういう解決方法を導き出せるように精進したいと思います。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問