次へ進む  [目次]  [STEP0]  [STEP1]  [STEP2]  [STEP3]  [STEP4]  [STEP5]  [STEP6]  [STEP7]  [終わりに]

猫でも作れる神経衰弱♪

STEP6:最弱のコンピュータを作りますにゃ   STEP6−結果

 STEP6では、ラッキーカードとくるくるカードの効果が出る処理を作って、最弱のコンピュータの思考ルーチンを作って、形だけでも人間対コンピュータで遊べるようにしますにゃ。できあがるものはこれですにゃ。STEP5で作ったものに、いろいろ書き加えていきますにゃ。
 ちょっと長くなりますから、3回に分けて作っていきますにゃ。まずは、ラッキーカードの処理くるくるカードの処理、それとコンピュータの頭脳になる配列の宣言この3つを作りますにゃ。こういうものができると思いますにゃ。
<html>
<head>
<title>神経衰弱♪</title>
<script language="JavaScript">
<!--
tims=0;times=0;flg=0;
var player=new Array(2);var p=new Array(30);var score=new Array(2);
var cp=new Array(60);var cpp=new Array(10);
var gz=new Array(11);
for (i=0;i<=10;i++) {gz[i]=new Image(48,60);}
for (i=0;i<=10;i++) {gz[i].src="./card-"+i+".gif";}

// カード獲得判定
function hantei()
{
 if (p[cardnum1]==9 || p[cardnum2]==9) {kuru=1;} else {kuru=0;}
 if (p[cardnum1]==p[cardnum2])
 {
  c="あたりにゃ♪";
  score[teban]=score[teban]+1;
  if (p[cardnum1]==luckycard)
  {
   c="ラッキーカードであたりにゃ♪";
   score[teban]=score[teban]+lcrule;
  }
  document.hyoji.sc1.value=score[0]+"点";
※関係にゃい部分はちょっと省略しますにゃ
 }
 else {wait=10;flg=4;}
}

// タイマー処理
function timerX()
{
※関係にゃい部分はちょっと省略しますにゃ
 if (flg==4)
 {
  wait=wait-1;
  if (wait<=0)
  {
   if (p[cardnum1]==0) {a=0;} else {a=10;}
   h=charaput(cardnum1,a);h=charaput(cardnum2,a);
   cardnum1=-1;cardnum2=-1;
   if (a==10)
   {
    if (teban==0) {teban=1;c="【後攻】";}
    else {teban=0;c="【先攻】";}
    document.hyoji.h1.value=c+"の番ですにゃ";
   }
   if (kuru==1) {h=cardmix();}
   h=carddataput();
   wait=0;flg=5;
  }
 }
※関係にゃい部分はちょっと省略しますにゃ
}
 くるくるカードを使うルール(ゲームタイプBまたはC)、ラッキーカード+1または+2を選択して、人間同士で遊んでみてくださいにゃ。くるくるカードをめくった時(より正確に言うとその手番が終わる時)にどうなるか、ラッキーカードが揃った時にどうなるか、わかると思いますにゃ。追加した部分の解説をしますにゃ。読み飛ばしても大丈夫ですにゃ。
・「var cp=new Array(60);var cpp=new Array(10);」
 配列cpと配列cppを使うという宣言をしますにゃ。今はまだ使わにゃいんですけど、配列cpは、コンピュータの頭脳(記憶するための場所)として使いますにゃ。ここに30枚のカードを記憶させるんですけど、このプログラムでは先攻のコンピュータと後攻のコンピュータを別のものとして扱いますにゃ。そうしておくと、人間が先攻でコンピュータが後攻の時、その逆の時、コンピュータ同士の対戦を観戦する時、この3つの状況に対応できるんですにゃ。配列cppは、STEP7で出てくるんですけど、コンピュータが何の数字のカードを何枚知っているかを数える時に使いますにゃ。
・「if (p[cardnum1]==9 || p[cardnum2]==9) {kuru=1;}」
 配列pのcardnum1番目の要素の値が9である、または、配列pのcardnum2番目の値が9であるなら、変数kuruの値を1にしますにゃ。「||」は「または」という意味で、前後の条件の少なくともどちらか一方に関してそれにあてはまる時、全体として条件にあてはまることになりますにゃ。「少なくとも」ですから両方とも条件にあてはまる時も含まれますにゃ。「&&」との違いをよく理解しておくと、この先いろいろ役に立つと思いますにゃ。「|」をキーボードから入力する時は、「Shift」を押しにゃがら右上角の「¥」を押すと出ますにゃ。ここでは、めくったカードのどちらか一方(または両方)がくるくるカードだったということを変数kuruを使って覚えておくということをしていますにゃ。
・「else {kuru=0;}」
 そうではにゃい場合、つまり、2枚ともくるくるカード以外のカードだった時は、変数kuruの値を0にしておきますにゃ。この変数kuruは、あとで使うことになりますにゃ。
・「(p[cardnum1]==luckycard)」「{」「}」
 配列pのcardnum番目の要素の値が変数luckycardの値とおなじなら、わかりやすく言うとめくったカードの1枚目がラッキーカードなら{ }の中の命令を実行しますにゃ。この命令は2枚のカードがおなじならという条件にあてはまる時に実行される命令の中に書かれていますから、2枚目のカード(もちろん1枚目のカードとおなじ)は条件に含みませんにゃ。
・「c="ラッキーカードであたりにゃ♪";」
 この直前に変数cの値だった「あたりにゃ♪」という文字列は、画面に表示される前に書き換えられることになりますにゃ。
・「score[teban]=score[teban]+lcrule;」
 配列scoreのteban番目の要素の値、わかりやすく言うとその時の順番のプレイヤーの得点に、変数lcruleの値を足しますにゃ。変数lcruleは「ラッキーカードのセレクトを選択した結果」によってゲームが始まる時に決まる値で、「なし=0」「1点=1」「2点=2」ですにゃ。ちょうどいいですから、その値をそのまま使いますにゃ。2枚のカードが揃った時点で1点が加算されていて、ここではさらに追加得点が加算されることになりますにゃ。
・「if (kuru==1) {h=cardmix();}」
 さっきの変数kuruが、ここで役に立ちますにゃ。変数kuruの値が1なら、言い換えると、めくったカードのどちらか一方(または両方)がくるくるカードだったら、関数cardmixを呼び出して実行しますにゃ。関数cardmixでは、場のカード(すでに取られてなくなったものも含む)をシャッフルして、カードがある場所にはカードの裏の画像を、カードがにゃい場所には「何もにゃい」の画像を表示しますにゃ。

 次は、コンピュータの思考ルーチンと行動の部分を作りますにゃ。ここでは、コンピュータが見たカードを覚えるということはするんですけど、その後はにゃにも考えにゃいで、ただ2枚のカードをめくるだけの最弱のコンピュータを作りますにゃ。作り方はいろいろあるんですけど、この講座では、コンピュータが1枚目のカードを選ぶ処理と2枚目のカードを選ぶ処理を別々に作りますにゃ。こういうものができると思いますにゃ。
※参考 ここで作るコンピュータの思考は、厳密に言うと最弱ではありませんにゃ。コンピュータがでたらめに選んだ2枚のカードがたまたま揃ってしまう可能性があって、それを避けるために、おなじ数字ではにゃい2枚のカードを覚えて、その2枚を選んでめくるということも、やろうと思えばできますにゃ。ここでは、そういうことも含めて「本当に何も考えてにゃい」っていう意味で「最弱」という表現を使っていますにゃ。
// メイン
function main()
{
※関係にゃい部分はちょっと省略しますにゃ
 tims=0;times=0;flg=1;
 if (player[0]>0) {h=complay1();}
}

// 画像表示
function charaput(n1,n2)
{
 name="img"+n1;
 document.images[name].src=gz[n2].src;
}

// コンピュータ思考(1枚目)
function complay1()
{
 cardnum1=-1;
 if (cardnum1<0)
 {
  for (i=0;i<=2;i++)
  {
   r=Math.floor(Math.random()*30);
   if (p[r]==0) {i=0;}
   else {cardnum1=r;break;}
  }
 }
 h=charaput(cardnum1,p[cardnum1]);
 flg=2;wait=10;
}

// コンピュータ思考(2枚目)
function complay2()
{
 cardnum2=-1;
 if (cardnum2<0)
 {
  for (i=0;i<=2;i++)
  {
   r=Math.floor(Math.random()*30);
   if (p[r]==0 || r==cardnum1) {i=0;}
   else {cardnum2=r;break;}
  }
 }
 h=charaput(cardnum2,p[cardnum2]);
 h=hantei();
}

// タイマー処理
function timerX()
{
※関係にゃい部分はちょっと省略しますにゃ
 if (flg==2)
 {
  wait=wait-1;
  if (wait<=0)
  {
   if (player[teban]==0) {c="2枚目のカードをクリックしてくださいにゃ";} else {c="";}
   document.hyoji.h2.value=c;
   flg=3;
   if (player[teban]>0) {h=complay2();}
  }
 }
 if (flg==4)
 {
  wait=wait-1;
  if (wait<=0)
  {
※関係にゃい部分はちょっと省略しますにゃ
   h=carddataput();
   wait=0;flg=5;
   if (player[teban]>0) {wait=11;} else {wait=0;}
   flg=5;
  }
 }
 if (flg==5)
 {
  wait=wait-1;
  if (wait<=0)
  {
   if (player[teban]==0) {c="1枚目のカードをクリックしてくださいにゃ";} else {c="";}
   document.hyoji.h2.value=c;
   flg=1;
   if (player[teban]>0) {h=complay1();}
  }
 }
}
 先攻または後攻を「COM Lv1」〜「COM Lv5」にして「開始」をクリックすると、人間対コンピュータで遊べますにゃ。今のところ、レベルによる違いはありませんにゃ。両方とも「COM Lv1」〜にすると、コンピュータ同士の対戦を観戦できますにゃ。追加した部分を解説しますにゃ。読み飛ばしても大丈夫ですにゃ。
・「if (player[0]>0) {h=complay1();}」
 ゲームが始まった時に、配列playerの0番目の要素の値が0より大きい時、わかりやすく言うと先攻のプレイヤーがコンピュータの時に関数complay1を呼び出して実行しますにゃ。関数complay1では、コンピュータが1枚目のカードを選んでめくる処理をしますにゃ。この時点ではウエイトはありませんから、コンピュータが先攻の時、ゲームが始まった次の瞬間には1枚目のカードがめくられることになりますにゃ。1枚目は何も考えにゃくていいはずですから、これは許容範囲ってことにしますにゃ。
・「function complay1()}」「{」「}」
 この関数の中で、コンピュータが1枚目のカードを選んでめくる処理をしますにゃ。今はまだ短いんですけど、STEP7ではもうちょっと長くなりますにゃ。
・「cardnum1=-1;」
 コンピュータが1枚目にめくるカードは、まだ決まっていにゃい(これから決める)ってことで、変数cardnum1の値を-1(カードの番号としてありえにゃい値)にしておきますにゃ。
・「if (cardnum1<0)}」「{」「}」
 変数cardnum1の値が0未満、つまり、1枚目のカードがまだ決まっていにゃい時、{ }の中の命令を実行しますにゃ。この時点で変数cardnumの値は-1になっていますから、この条件にはかならずあてはまることになりますにゃ。だから今は必要にゃいんですけど、STEP7でこういう書き方をすることになりますから、今のうちにそうしておきますにゃ。
・「for (i=0;i<=2;i++)}」「{」「}」
 STEP4でも出てきた繰り返し処理の特別な使い方で、繰り返し回数は3回ではありませんにゃ。これとは別のある条件にあてはまるまで、{ }の中の命令を繰り返しますにゃ。どんな条件にゃのかは、このあと説明しますにゃ。
・「r=Math.floor(Math.random()*30);」
 変数rに0〜29までのでたらめな整数を代入しますにゃ。これは、「何番目のカードをめくるか」をでたらめに決めてるってことですにゃ。
・「if (p[r]==0) {i=0;}」
 配列pのr番目の要素の値が0、わかりやすく言うとさっき選んだ番号のカードは、取られたからもう場ににゃい時に、変数iの値を0にすることで繰り返し処理を続けさせますにゃ。これがにゃいと、たまたま3回続けて「もうにゃいカード」を選んでしまった時、そのまま進んでしまいますにゃ。
・「else {cardnum1=r;break;}」
 そうではにゃい時、つまり、選んだカードがまだ場にある時、変数cardnum1の値を変数rの値にする、言い換えるとでたらめに選んだカードを1枚目のカードに決定するってことですにゃ。そのあと「break;」でこの繰り返し処理を強制終了しますにゃ。
・「h=charaput(cardnum1,p[cardnum1]);」
 関数charaputを呼び出して実行しますにゃ。その時に、第1引数として変数cardnum1の値を、第2引数として配列pのcardnum1番目の要素の値を渡しますにゃ。ようするに、今決まったカードの画像(カードの裏)をそのカードの表の画像に差し替えるってことですにゃ。
・「flg=2;wait=10;」
 フラグ=2(1枚目のカードがめくられた後のウエイト状態)に移行しますにゃ。今はコンピュータの手番ですから、コンピュータが考えているように見せかけるために10(約1秒)のウエイトを設定しますにゃ。これがにゃいと、見かけ上(プログラム内では実際にそうにゃんですけど)コンピュータが瞬間的に2枚目のカードを決めてめくるように見えてしまいますにゃ。
・「function complay2()}」「{」「}」
 この関数の中で、コンピュータが2枚目のカードを選んでめくる処理をしますにゃ。今のところ、中身は1枚目の時とほとんどおなじで、2行だけ違うところがありますから、そこだけ説明して、他の部分の説明は省略しますにゃ。
・「if (p[r]==0 || r==cardnum1) {i=0;}」
 配列pのr番目の要素の値が0である、または、変数rの値と変数cardnum1の値がおなじである時、変数iの値を0にして繰り返し処理を続けさせますにゃ。「または」ですから、どちらか一方または両方の条件にあてはまる時にゃんですけど、この場合は両方の条件にあてはまることはありえませんにゃ。最初の条件は、さっきとおなじで「そのカードが取られたからもうにゃい時」ですにゃ。2番目の条件は、わかりやすく言うと2枚目候補としてでたらめに選んだカードが1枚目のカードとおなじだった時ですにゃ。ここで言う「おなじ」っていうのは、カードの中身の話じゃにゃくて「何番目のカードか」ってことですにゃ。これがにゃいと、たまたま1枚目と2枚目でおなじカードを選んでしまって、結果的に1枚しかめくらにゃいっていうことが発生する恐れが出てきますにゃ。
・「h=hantei();」
 関数hanteiを呼び出して実行しますにゃ。人間の時とおなじで、2枚のカードが揃ったかどうかの判定とその後の処理をして、まだゲームが続く場合は関数hanteiの最後にフラグ=4(ウエイト状態)に移行しますにゃ。
・「if (player[teban]>0) {h=complay2();}」
 この命令は、フラグ=2のウエイト状態が終わった時(変数waitの値が0以下になった時)に実行されますにゃ。配列playerのteban番目の要素の値が0より大きい、言い換えるとその時の手番のプレイヤーがコンピュータの時に関数complay2を呼び出して実行しますにゃ。
・「wait=0;flg=5;」
 この命令とその後に続く命令は、フラグ=4のウエイト状態が終わった時に実行されますにゃ。今までは人間同士でプレイしていましたから、ウエイトは0に決めていたんですけど、その部分を消して、代わりに別の命令を実行させることにしますにゃ。
・「if (player[teban]>0) {wait=11;}」
 その時の手番(カードが揃わにゃかった場合は交代した後の手番)のプレイヤーがコンピュータなら、変数waitの値を11にしますにゃ。これで、見かけ上、コンピュータが1枚目のカードをめくる前に考えているように見えますにゃ。10じゃにゃくて11にするのは、細かいことにゃんですけど、このあと続けて「フラグ=5」の状態の処理をする時に、最初に変数waitの値が10から1減らされて、実質ウエイト9(=約0.9秒)になってしまうのを避けるためですにゃ。
・「else {wait=0;}」
 そうではにゃい時、つまり、次のプレイヤーが人間の時は、ウエイトは必要ありませんにゃ。
・「flg=5;」
 フラグ=5(手番が終わった後のウエイト状態)に移行しますにゃ。その時の手番のプレイヤーが人間でもコンピュータでもおなじことにゃんですけど、ウエイトの数値が違いますにゃ。
・「if (player[teban]>0) {h=complay1();}」
 この命令は、フラグ=5のウエイト状態が終わった時に実行されますにゃ。配列player…の説明はもう書かにゃくてもわかりますにゃ? 次のプレイヤーがコンピュータの時、関数complay1を呼び出して実行しますにゃ。

 STEP6のテーマとしては、これで完成にゃんですけど、次のSTEP7が長くなりすぎると困りますから、分量を調整する都合でコンピュータの記憶の部分を今のうちに作ってしまいますにゃ。ただし、今のところ、見たカードを覚えるんですけどその記憶を元ににゃにか考えるということはしませんにゃ。こういうものができると思いますにゃ。
// カードシャッフル
function cardmix()
{
 for (i=0;i<=999;i++)
 {
  r1=Math.floor(Math.random()*30);
  r2=Math.floor(Math.random()*30);
  a=p[r1];p[r1]=p[r2];p[r2]=a;
 }
 for (i=0;i<=29;i++)
 {
  if (p[i]==0) {a=0;} else {a=10;}
  h=charaput(i,a);
 }
 for (i=0;i<=59;i++) {cp[i]=0;}
}

// カード獲得判定
function hantei()
{
 if (p[cardnum1]==9 || p[cardnum2]==9) {kuru=1;} else {kuru=0;}
 if (p[cardnum1]==p[cardnum2])
 {
  c="あたりにゃ♪";
  score[teban]=score[teban]+1;
  if (p[cardnum1]==luckycard)
  {
   c="ラッキーカードであたりにゃ♪";
   score[teban]=score[teban]+lcrule;
  }
  document.hyoji.sc1.value=score[0]+"点";
  document.hyoji.sc2.value=score[1]+"点";
  cardkazu=cardkazu-2;
  p[cardnum1]=0;p[cardnum2]=0;
  cp[cardnum1]=0;cp[cardnum1+30]=0;
  cp[cardnum2]=0;cp[cardnum2+30]=0;
 }
 else
 {
  c="はずれにゃ…";
  h=commemory();
 }
 document.hyoji.h2.value=c;
 if (cardkazu<=0)
 {
  document.hyoji.h1.value="ゲーム終了にゃ♪";
  document.hyoji.h2.value="[開始]をクリックするともう1回遊べるのにゃ";
  flg=0;
 }
 else
 {
  h=comforget();
  wait=10;flg=4;
 }
}

// カードの内容表示
function carddataput()
{
 c="";
 for (i=0;i<=4;i++)
 {
  c1="";c2="";c3="";
  for (j=0;j<=5;j++)
  {
   a=i*6+j;
   c1=c1+"["+p[a]+"]";
   c2=c2+"["+cp[a]+"]";c3=c3+"["+cp[a+30]+"]";
  }
  c=c+c1+"    "+c2+"    "+c3+"\n";
 }
 document.hyoji.text1.value=c;
}

// コンピュータ思考(2枚目)
function complay2()
{
※関係にゃい部分はちょっと省略しますにゃ
}

// コンピュータ記憶
function commemory()
{
 for (i=0;i<=1;i++)
 {
  if (player[i]>0)
  {
   a=100;
   r=Math.floor(Math.random()*100);
   if (r<a) {cp[cardnum1+i*30]=p[cardnum1];}
   r=Math.floor(Math.random()*100);
   if (r<a) {cp[cardnum2+i*30]=p[cardnum2];}
  }
 }
}

// コンピュータ忘却
function comforget()
{
 for (i=0;i<=1;i++)
 {
  if (player[i]>0)
  {
   a=0;
   for (j=0;j<a;j++)
   {
    r=Math.floor(Math.random()*30);
    cp[r+i*30]=0;
   }
  }
 }
}

// タイマー処理
※この後はおなじですから省略しますにゃ
 人間対コンピュータ、または、コンピュータ同士を選択して、ゲームを始めてみてくださいにゃ。ゲームの内容はさっきとまったくおなじものにゃんですけど、灰色のところの表示が変わっていますにゃ。全体を3ブロックに分けて、左のブロックは今までとおなじでカードの中身、真ん中のブロックは先攻のコンピュータの記憶、右のブロックは後攻のコンピュータの記憶を表示していますにゃ。また解説していきますにゃ。読み飛ばしても大丈夫ですにゃ。
・「for (i=0;i<=59;i++) {cp[i]=0;}」
 繰り返し処理を60回実行して、配列cpのi番目(=0〜59番目)の要素の値を0にしますにゃ。0〜29番目の要素は先攻のコンピュータの記憶で、30〜59番目の要素は後攻のコンピュータの記憶ですにゃ。場のカードは(取られてなくなったものも含めて)30枚ありますから、配列の要素の数は30枚×コンピュータ2人分で60(0から始まって59まで)になりますにゃ。簡単に言うとカードがシャッフルされたからコンピュータの記憶を全部消すってことですにゃ。関数mainの中じゃにゃくて関数cardmixの中に書く理由は、ゲームが始まった時だけじゃにゃくてくるくるカードの効果が出た時にも実行することになるからですにゃ。プレイヤーのどちらか1人または両方が人間の時には、コンピュータの記憶を消す必要はにゃいんですけど、このままで何の問題もありませんから細かいことは無視しますにゃ。
・「cp[cardnum1]=0;」
 配列cpのcardnum1番目の値を0にしますにゃ。わかりやすく言うと、今めくった1枚目のカードに関する先攻のコン―ピュータの記憶を消すってことですにゃ。この命令を含むいくつかの命令はカードが揃って取られる時に実行されますにゃ。つまり、カードそのものがなくなってしまうから、そのカードに関するコンピュータの記憶も消すってことですにゃ。この場合、「コンピュータが最初からそのカードを記憶していにゃい」「先攻のプレイヤーが人間である」っていう可能性もあるんですけど、このままで何の問題もありませんから細かいことは無視しますにゃ。
・「cp[cardnum1+30]=0;」
 配列cpの「cardnum+30」番目の値を0にしますにゃ。わかりやすく言うと、今めくった1枚目のカードに関する後攻のコン―ピュータの記憶を消すってことですにゃ。あとはおなじですから説明は省略しますにゃ。
・「cp[cardnum2]=0;cp[cardnum2+30]=0;」
 今めくった2枚目のカードについても、おなじようにしますにゃ。あとはおなじですから説明は省略しますにゃ。
・「h=commemory();」
 関数commemoryを呼び出して実行しますにゃ。あとで説明することになるんですけど、関数commemoryの中では、最大2人のコンピュータに今めくった2枚のカードを記憶させますにゃ。この命令は2枚のカードが揃わにゃかった時に実行されますにゃ。2枚のカードが揃った時に記憶させても、その2枚は取られてなくなってしまうから意味がにゃいんですにゃ。
・「h=comforget();」
 コンピュータは、1回覚えたことは忘れにゃいんですけど、ちょっとでも人間っぽく見せるために覚えたカードを忘れることがあるってことにしますにゃ。そのために、ゲームがまだ続いている時に、関数comforgetを呼び出して実行しますにゃ。else{ }の中に書くのは、その前の条件にあてはまる時(=取れるカードがなくなってゲームが終了した時)にカードを忘れさせても意味がにゃいからですにゃ。
・「c1="";c2="";c3="";」
 これは、ゲームには関係にゃい表示部分ですから、大雑把に説明しますにゃ。ここでは、あとで使うことになる3つの文字列を初期化していますにゃ。
・「c1=c1+"["+p[a]+"]";」「c2=c2+"["+cp[a]+"]";c3=c3+"["+cp[a+30]+"]";」
 「カードの中身」「先攻のコンピュータの記憶」「後攻のコンピュータの記憶」をそれぞれ別の文字列にくっつけていますにゃ。
・「c=c+c1+" "+c2+" "+c3+"\n";」
 3つの文字列をくっつけて、1行分の文字列を作っていますにゃ。この命令は5回繰り返し実行されますから、5行分の文字列ができることになりますにゃ。最終的にできあがる文字列が画面の灰色のところに表示されますにゃ。
・「function commemory()」「{」「}」
 関数commemoryの始まりと終わりですにゃ。この中で、コンピュータにカードを記憶させますにゃ。
・「for (i=0;i<=1;i++)」「{」「}」
 コンピュータは先攻と後攻で最大2人いることになりますから、この処理は2回繰り返して実行しますにゃ。
・「if (player[i]>0)」「{」「}」
 配列player…の説明は今までとおなじですから省略しますにゃ。i番目(先攻は0番目、後攻は1番目)のプレイヤーがコンピュータの時、{ }の中の命令を実行しますにゃ。
・「a=100;」
 ここでは変数aの値を仮に100としておきますにゃ。この部分は、STEP7で変わることになりますにゃ。
・「r=Math.floor(Math.random()*100);」
 変数rの値を0〜99までのでたらめな整数にしますにゃ。にゃんで100通りの乱数にゃのかってことは、STEP7でわかりますから、今は気にしにゃいでくださいにゃ。
・「if (r<a)」「{」「}」
 「<=」じゃにゃくて「<」ですから、この場合は未満ってことで、2つの値がおなじ場合は含まれませんにゃ。変数rの値が変数aの値より小さい時、{ }の中の命令を実行するんですけど、変数rの値は最大99で、変数aの値は仮に100としていますから、この場合かならず条件にあてはまることになりますにゃ。
・「cp[cardnum1+i*30]=p[cardnum1];」
 配列cpの「変数cardnum1の値に変数iの値の30倍を加えた数値」番目の値を配列pのcardnum1番目の値にしますにゃ。これだと、にゃにを言ってるのかさっぱりわかりませんから、ちょっとずつ説明しますにゃ。
・配列cpは、コンピュータの記憶ですにゃ。2人分のコンピュータの記憶をまとめて60の要素を持つ配列にしていますにゃ。
・cardnum1は、1枚目としてめくったカードが何番目のカードにゃのかを表していますにゃ。コンピュータが先攻(変数iの値=0)の時は、このままでにゃにも問題ありませんにゃ。
・コンピュータが後攻の時、記憶のための配列cpの配列番号は30から始まる数値になりますにゃ。そのために、1枚目のカードの番号に変数iの30倍の数値を加えていますにゃ。
・例えば、1枚目のカードとして5番目のカードをめくった時、それを覚えるための配列番号は「先攻なら5」「後攻なら35」になりますにゃ。
・そして、その配列番号の要素の値として、1枚目としてめくったカードの数字の値を代入して、コンピュータに記憶させるってことですにゃ。ちょっと難しいかもしれにゃいんですけど、おわかりいただけましたかにゃ?
・「r=Math.floor(Math.random()*100);」
 さっきとおなじですにゃ。同じ命令を2回実行するのには、ちゃんと理由がありますにゃ。STEP7で出てくるんですけど、コンピュータが「決められた確率でカードを覚えたり覚えにゃかったりする」時に、例えば「1枚目のカードは覚えたけど2枚目は覚えられにゃかった」とかいう場合もあるはずですにゃ。その時に、変数r(でたらめな数)を1回だけ決めて2枚のカードに対して使ってしまうと、その結果は「2枚とも覚える」「2枚とも覚えられにゃい」のどちらかになってしまいますにゃ。変数rを2回決めて別々に使うようにすると、その結果は「最大4通り」になりますにゃ。
・「if (r<a)」「{」「}」
 さっきとおなじで、今のところ、この{ }の中の命令はかならず実行されますにゃ。
・「cp[cardnum2+i*30]=p[cardnum2];」
 1枚目が2枚目に代わるだけで、さっきとおなじですにゃ。簡単におさらいしてみますにゃ。配列cpの要素番号は、先攻の時は0、後攻の時は30から始まりますにゃ。2枚目としてめくったカードの番号にその数値を加えたものが、今から使う配列番号になりますにゃ。そこに、2枚目のカードの数字の値を入れることで、コンピュータに2枚目のカードを記憶させるってことですにゃ。
・「function comforget()」「{」「}」
 関数comforgetの始まりと終わりですにゃ。この中で、コンピュータにカードを忘れさせますにゃ。
・「for (i=0;i<=1;i++)」「{」「}」「if (player[i]>0)」「{」「}」
 さっきとおなじで、最大2人のコンピュータがいるから繰り返しは2回、それぞれのプレイヤーがコンピュータなら{ }の中の命令を実行しますにゃ。
・「a=0;」
 ここでは変数aの値を仮に0としておきますにゃ。この部分は、STEP7で変わることになりますにゃ。
・「for (j=0;j<a;j++)」「{」「}」
 2重ループの内側ですから、変数名はjを使いますにゃ。そして、ここがちょっとややこしいんですけど、変数jの初期値は0で、繰り返しの条件は変数jの値は変数aの値未満である時(おなじ場合は含まにゃい)で、さっき仮に変数aの値を0にしましたから、最初からこの条件にはあてはまらにゃいことになって、{ }の中の命令は1回も実行されませんにゃ。それならにゃんでこんなものを作るのにゃ…? STEP7で使うことになるから今のうちに作っておくんですにゃ。ここから先は、その時のための予習みたいなものですにゃ。ここでは「仮に」変数aの値を0にしたんですけど、STEP7では1以上の値にすることになりますにゃ。その時に、この繰り返しの中の命令を「a回」実行することになるんですにゃ。
・「r=Math.floor(Math.random()*30);」
 変数rの値を0〜29までのでたらめな整数にしますにゃ。これは、何番目のカードかってことにゃんですけど、もうわかりますかにゃ?
・「cp[r+i*30]=0;」
 配列cp…の説明はさっきとおなじですから省略しますにゃ。先攻ならr番目の要素、後攻ならr+30番目の要素(=コンピュータの記憶)の値を0にして、そのカードの記憶を忘れさせますにゃ。その時に「コンピュータが最初からそのカードの数字を知らにゃい」「そのカードはもう取られて場ににゃい」この2つの可能性があるんですけど、このままでにゃにも問題ありませんから細かいことは無視しますにゃ。この命令をa回繰り返し実行することでa枚のカードの数字を確実に忘れるんじゃにゃくて、「カードの数字を忘れる機会が最大a回ある」っていう感じですにゃ。ようするに、忘れる時もあれば忘れにゃい時もあるってことですにゃ。

次へ進む  [目次]  [STEP0]  [STEP1]  [STEP2]  [STEP3]  [STEP4]  [STEP5]  [STEP6]  [STEP7]  [終わりに]