アプリ版:「スタンプのみでお礼する」機能のリリースについて

Youtubeにてあきちょんさんの動画、テトリスを作る17回でテトリスを回転させるコードについて分からないことがあったので質問させて頂きます。必要そうなコードのみ抜粋、変数は自分が分かりやすいように多少変えてます。

<!DOCTYPE html>
<html>
<body>
<script>

let tetro = [
[0,0,0,0],
[1,1,0,0],
[0,1,1,0],
[0,0,0,0],
];

function rotate()
{
let kaiten=[]
for( let y = 0; y<4; y++ )
{
kaiten[y] = []
for( let x = 0; x<4; x++ )
{
kaiten[y][x] = tetro[3-x][y];
}
}
return kaiten;
}



let ntetro = rotate(); //一回目回転させる
tetro = ntetro


ntetro = rotate(); //二回目回転させる
tetro = ntetro

</script>
</body>
</html>


のコードですが、前々回第15回でも二次元配列を初期化、代入を説明されていたので、
let kaiten を関数の外で宣言してreturnを受け取らずにしました。

<!DOCTYPE html>
<html>
<body>
<script>


let tetro = [
[0,0,0,0],
[1,1,0,0],
[0,1,1,0],
[0,0,0,0],
];


let kaiten=[] //関数の外で宣言

function rotate()
{
for( let y = 0; y<4; y++ )
{
kaiten[y] = []
for( let x = 0; x<4; x++ )
{
kaiten[y][x] = tetro[3-x][y];
}
}
}    //returnを受け取らない

rotate(); //一回目回転させる
tetro = kaiten

rotate(); //二回目回転させる
tetro = kaiten

</script>
</body>
</html>

このようにしたところ、一回回転させる分には正常なのですが、2回目からバクるんですが、なぜだか分かりません。どうぞご教授ください。プログラミング初めて一か月くらいなので、平たく解説していただけると助かります。

A 回答 (4件)

こんにちは



単変数の場合は、値を代入するとそれぞれが値を保持しますけれど、配列やオブジェクトの場合は参照代入になります。

let a = [1, 2, 3, 4];
let b = a;

b[0] = 5;
console.log(a); // [5, 2, 3, 4]

うまくいかないという方に関しては、最初は配列kaitenとtetroは別々に定義されているので、それぞれ別の値を保持していますが、
>tetro = kaiten
の代入を実行すると、tetroとkaitenは同じ値を参照するようになります。
このため、2度目以降はおかしなことになります。
正しく動作する方のスクリプトは、関数内で毎回新しく配列kaitenを生成しているので、このようなことが起こりません。

後でご提示の方法でも意図通り動作させたければ、
>tetro = kaiten
とせずに、構成する要素を個々に代入するようにすれば、それぞれの変数が個別に値を保持するようになるので、意図通りになると思います。
例えば、
 tetro = kaiten.map(i=>i.map(j=>j));
とか。
    • good
    • 0
この回答へのお礼

ありがとう

ご回答ありがとうございます。
参照代入を勉強させて頂きます。
代替案もありがとうございます。
余裕が出来たらそちらも勉強させて頂きます。

お礼日時:2021/12/17 18:11

No1です



連投失礼。
ちょっと面白い記事をみつけたので・・・
https://qiita.com/kznrluk/items/790f1b154d1b6d4d …

行列の回転を行うワンライナーです。ご参考までに。
// 時計回りに回転
const rotate = a => a[0].map((_, c) => a.map(r => r[c]).reverse());

let tetro = [
[0,0,0,0],
[1,1,0,0],
[0,1,1,0],
[0,0,0,0]
];

tetro = rotate(tetro);
tetro = rotate(tetro);
    • good
    • 0
この回答へのお礼

がんばります

ありがとうございます。

お礼日時:2021/12/17 18:12

tetro = kaiten;


kaiten[0] = 'kaitenに代入';
console.log(tetro);

としたとき、
kaitenにだけ代入したつもりなのに、
tetroも一緒に変化します。

一般的な感覚だと、おかしい気もしますが、
プログラムとしては、これが正しい結果です。

その理屈は、No1さんの解説の通りなのですが、
もし難しければ、
「JavaScript 基本型 参照型」
などでググると、いろいろ解説記事が出てきますので、
それらを読んでみて、自分で一番納得しやすいものを参考にしてください。
    • good
    • 0
この回答へのお礼

助かりました

ご回答ありがとうございます。
なんとなく分かりました。
forループを使って一気に出力すると頭がこんがりますね。
一つ一つ代入しながら検証していきたいと思いました

お礼日時:2021/12/17 18:15

> Youtubeにてあきちょんさんの動画、テトリスを作る17回でテトリスを回転させるコードについて分からないことがあったので質問させて頂きます。



ハッキリ言うけど。
何故に松下電器の商品に対する質問をSONYにするような真似をするの。
そういう「YouTubeでプログラミング講座」を提供してるトコ自体で質問しなさいよ。
他のサイトにそういう質問を持ち込まない。

逆に言うと、誰?そのあきちょんさんだか何だか知らんけど、もし、貴方のような人からYouTubeで質問を受け付けてない、としたら「プログラミング講座」とかやる資格がないんだよ。
分かる?

> プログラミング初めて一か月くらいなので

うん、だったらそれやめて本の一冊でも買って勉強しなさい。
「動画だったら簡単にプログラムを学べる!」とかウソだから。
安直なヤツが騙されるんだよ。
もう一回言うけど、「質問を受け付けてないような」サイトで「学べる」とかあり得ないから。
だったらフツーに本買って読んで勉強した方がマシ。それには結局「勝てない」んだよな。
    • good
    • 1
この回答へのお礼

ご回答ありがとうございます。
お気に障りましたら申し訳ございませんでした。

お礼日時:2021/12/17 18:16

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!