研究班番号【 105 】

AI 学習を用いたオセロ AI の作成
情報班：坂田 琢馬

１．はじめに近年、AI 産業が発達しているという中、AI を学習することが将来役立つと考え、手始めに AIを使ったオセロを作成しようと思い、開発に取り組んだ。また、今回はオセロ AI の作成だけでなく自分たちの視覚に合わせた三次元空間の疑似的な描画にも着手した。

２．作成方法
この研究では HTML と JavaScript というプログラミング言語を用いた。
AI の行動について

・各マスの重要度をランダムに学習させた。
方法としてはランダムなマスへの優先度を持った AI 同士で対戦させ、勝利した AI のマス
目優先度を延々と積み重ねるという手法をとり、その学習結果を用いて開放度理論をベースに行動するようにプログラミングした。
プログラムは以下の通りである<!DOCTYPE html><html><head><meta charset="UTF-8"><title>osero</title><style>#canvas {background: #fff;}</style></head><body><canvas id="canvas" width="1500" height="550"></canvas><table id="tbl" border="1" width="220" height="220" bgcolor="green"
bordercolor="black" style=border-collapse:collapse>//オセロの操作場面の設定<tr><td></td><td></td>

<td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>

<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>
<td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>

</tr></table><script>var osero=[[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:1},{iro:2},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:2},{iro:1},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}]];//オセロの盤面の状態を記録した配列の作成
var oseronex=[[],[],[],[],[],[],[],[]];
var oseronex2=[[],[],[],[],[],[],[],[]];//オセロの盤面を保存できる箱を作成
var
oserobefo=[[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}]];var ifosero=[[],[],[],[],[],[],[],[]];
var turn1=1;
var turn2=2;
var change;
var kouho=[];var siro;var kuro;
var learn= [[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],];var prac= [[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0],];//一次元的なオセロの学習結果を保存する箱を作成
var set=0;
var kioku=[];var mixi=[];var imp=0;
var win=0;
var kaiho=0;
var match=0;//後で説明for(s=0;s<8;s++){for(t=0;t<8;t++){oseronex[s][t]= Object.create(osero[s][t]);}}
window.onload=check();function check(){
for(s=0;s<8;s++){for(t=0;t<8;t++){oseronex[s][t]= Object.create(osero[s][t]);}}
var tbl = document.getElementById("tbl");for(s=0;s<8;s++){for(t=0;t<8;t++){const r=s;
const c=t;
tbl.rows[s].cells[t].addEventListener("click",false);}
kuro=0;siro=0;}function(){shudou(r,c)},koma();
battle(osero);}//盤面の駒の数を計測
while(match<1000){te();}var interv=null;interv=window.setInterval(te,500);//後に記載するオセロ学習プログラムを繰り返す
console.log(learn);function shudou(a1,a2){//console.log(osero);huku(prac);//開放度の計算
if(typeof mixi[0]==="undefined"){const change=turn1;
turn1=turn2;
turn2=change;
imp+=1;}else{
if(turn1==2){oku(a1,a2);}
huku(prac);
if(turn1==1){oku(mixi[0].rx,mixi[0].cy);}if(imp==2||kuro+siro==64){}else{
console.log("黒："+kuro,"白："+siro);}}koma();
redraw()}//手動でオセロをする場合のコンピューターの設定

function te(){if(gyoukaku!=-40){
if(match<1){
maxim(learn);if(typeof mixi[0]==="undefined"){const change=turn1;
turn1=turn2;
turn2=change;
imp+=1;}else{
if(turn1==1){
maxim(prac);oku(mixi[0].rx,mixi[0].cy);
const kx=mixi[0];//kioku.push(kx);
imp=0;}else{
maxim(learn);oku(mixi[0].rx,mixi[0].cy);
imp=0;}}
if(imp==2||kuro+siro==64){
match+=1;//console.log(kioku);
if(kuro>siro){
win+=1;}else{
for(g=0;g<8;g++){for(u=0;u<8;u++){prac[g][u]=prac[g][u]+Math.floor(learn[g][u]/10);}}
win=0;}
for(g=0;g<11;g++){kioku[g]=Math.floor(Math.random()*150);}
cpar();
osero=[[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:1},{iro:2},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:2},{iro:1},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}],[{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0},{iro:0}]];koma();
console.log("黒："+kuro,"白："+siro);
console.log(match);}}else{for(g=0;g<8;g++){for(u=0;u<8;u++){prac[g][u]=Math.floor(prac[g][u]/50);}}
console.log(osero,prac,match);clearInterval(interv);}
koma();
redraw();}}//コンピューター同士の対戦による学習
function oku(ox,oy){
judge(osero,ox,oy);if(osero[ox][oy].put){for(s=0;s<8;s++){for(t=0;t<8;t++){//if(osero[s][t].iro!=oseronex[s][t].iro){learn[s][t]-=1;}
osero[s][t]= Object.create(oseronex[s][t]);}}
osero[ox][oy].iro=turn2;
const change=turn1;
turn1=turn2;
turn2=change;
console.log(osero, turn1,turn2,ox,oy);//koma();osero[ox][oy].put=false;
battle(osero);if(typeof kouho[0]==="undefined"){const change=turn1;
turn1=turn2;
turn2=change;}}}//駒を置く、という動作を作成

function judge(xxx,i,k){for(s=0;s<8;s++){for(t=0;t<8;t++){oseronex[s][t]= Object.create(xxx[s][t]);oseronex[s][t].put=false;}}if(xxx[i][k].iro==0){
for(n=1;(k-n>0&&xxx[i][k-n].iro==turn1);n++){if(xxx[i][k-n].iro==turn1){
if(xxx[i][k-n-1].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i][k-a].iro=turn2;}}}else{break;}}for(n=1;(k+n<7&&osero[i][k+n].iro==turn1);n++){if(xxx[i][k+n].iro==turn1){
if(xxx[i][k+n+1].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i][k+a].iro=turn2;}}}else{break;}}for(n=1;(i-n>0&&xxx[i-n][k].iro==turn1);n++){if(xxx[i-n][k].iro==turn1){
if(xxx[i-n-1][k].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i-a][k].iro=turn2;}}}else{break;}}for(n=1;(i+n<7&&xxx[i+n][k].iro==turn1);n++){if(xxx[i+n][k].iro==turn1){
if(xxx[i+n+1][k].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i+a][k].iro=turn2;}}}else{break;}}for(n=1;(i-n>0&&k-n>0);n++){if(xxx[i-n][k-n].iro==turn1){
if(xxx[i-n-1][k-n-1].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i-a][k-a].iro=turn2;}}}else{break;}}for(n=1;(i+n<7&&k+n<7);n++){if(xxx[i+n][k+n].iro==turn1){
if(xxx[i+n+1][k+n+1].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i+a][k+a].iro=turn2;}}}else{break;}}for(n=1;(i+n<7&&k-n>0);n++){if(xxx[i+n][k-n].iro==turn1){

if(xxx[i+n+1][k-n-1].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i+a][k-a].iro=turn2;}}}else{break;}}for(n=1;(i-n>0&&k+n<7);n++){if(xxx[i-n][k+n].iro==turn1){
if(xxx[i-n-1][k+n+1].iro==turn2){xxx[i][k].put=true;for(a=1;a<n+1;a++){oseronex[i-a][k+a].iro=turn2;}}}else{break;}}}else{//xxx[i][k].put=false;}}//駒をひっくり返すという処理を作成

function koma(){var tbl = document.getElementById("tbl");for(s=0;s<8;s++){for(t=0;t<8;t++){if(osero[s][t].iro==1){
tbl.rows[s].cells[t].innerHTML="〇"}else{
if(osero[s][t].iro==2){
tbl.rows[s].cells[t].innerHTML="●"}else{tbl.rows[s].cells[t].innerHTML="}}}//駒の色を描画
function search(lll){for(s=0;s<8;s++){for(t=0;t<8;t++){"}}oseronex[s][t]= Object.create(osero[s][t]);}}
kouho=[];
for(p=0;p<8;p++){for(q=0;q<8;q++){const rr=p;
const cc=q;
judge(osero,p,q);
kaiho=0;if(osero[p][q].put==true){console.log(osero)
const cat=bord(p,q);
kouho[kouho.length]={"rx":rr,"cy":cc,"atai":lll[rr][cc],"mu":cat};}}}for(s=0;s<8;s++){for(t=0;t<8;t++){oseronex[s][t]= Object.create(osero[s][t]);}}
console.log(kouho);}//駒が置ける場所を探索

function battle(banmen){kuro=0;siro=0;for(b=0;b<8;b++){for(w=0;w<8;w++){if(banmen[b][w].iro==2){kuro+=1}
if(banmen[b][w].iro==1){siro+=1}}}}
function maxim(ppp){
search(ppp);
mixi=[kouho[0]];for(z=0;z<kouho.length;z++){if(mixi[0].atai<kouho[z].atai){mixi=[kouho[z]];}if(mixi[0].atai==kouho[z].atai&&z!=0){mixi.push(kouho[z])}var ran=Math.floor(Math.random()*mixi.length);mixi=[mixi[ran]];}}//学習結果をソートして学習に基づいて AI の行動を指定

function huku(ppp){
search(ppp);
mixi=[kouho[0]];for(z=0;z<kouho.length;z++){//console.log(kouho[z].mu)
if(mixi[0].mu<kouho[z].mu){mixi=[kouho[z]];}if(mixi[0].mu==kouho[z].mu&&z!=0){mixi.push(kouho[z])}var ran=Math.floor(Math.random()*mixi.length);mixi=[mixi[ran]];}}//開放度の計算
function noukin(){search();mixi=[kouho[0]];for(z=0;z<kouho.length;z++){if(nousi(mixi[0].rx,mixi[0].cy)<nousi(kouho[z].rx,kouho[z].cy)){mixi=[kouho[z]];}
if(nousi(mixi[0].rx,mixi[0].cy)==nousi(kouho[z].rx,kouho[z].cy)&&z!=0){mix
i.push(kouho[z])}var ran=Math.floor(Math.random()*mixi.length);mixi=[mixi[ran]];}}//ただ多くひっくり返せるところに置くコンピューター
function nousi(ox,oy){judge(ox,oy);battle(oseronex);
var jk=siro;
battle(osero);
return jk-siro;}//ひっくり返す駒の数を測定

function bord(fx,fy){
judge(osero,fx,fy);for(s=0;s<8;s++){for(t=0;t<8;t++){if(oseronex[s][t].iro!=osero[s][t].iro){if(s==fx&&t==fy){}else{
kaiho=vacant(s,t,kaiho,osero);}}}}var dog=100;
const change=turn1;
turn1=turn2;
turn2=change;for(s=0;s<8;s++){for(t=0;t<8;t++){ifosero[s][t]= Object.create(oseronex[s][t]);//ifosero[s][t].put=false;}}for(p=0;p<8;p++){for(q=0;q<8;q++){judge(ifosero,p,q);
var kaiho2=0;
if(ifosero[p][q].put==true){for(s=0;s<8;s++){for(t=0;t<8;t++){if(ifosero[s][t].iro!=oseronex[s][t].iro){if(p==s&&q==t){}else{
kaiho2+=vacant(s,t,kaiho2,ifosero);}}}}
if(dog>kaiho2){dog=kaiho2;}}}}
const change2=turn1;
turn1=turn2;

turn2=change2;
console.log(dog,kaiho);
kaiho=dog-kaiho;
return(kaiho);}//開放度の測定

function vacant(kx,ky,kl,kh){
if(-1<(kx-1)&&8>(kx-1)&&-1<(ky-1)&&8>(ky-1)){if(kh[kx-1][ky-1].iro==0){kl+=1;}}
if(-1<(kx-1)&&8>(kx-1)&&-1<ky&&8>ky){if(kh[kx-1][ky].iro==0){kl+=1;}}
if(-1<(kx-1)&&8>(kx-1)&&-1<(ky+1)&&8>(ky+1)){if(kh[kx-1][ky+1].iro==0){kl+=1;}}
if(-1<kx&&8>kx&&-1<(ky-1)&&8>(ky-1)){if(kh[kx][ky-1].iro==0){kl+=1;}}
if(-1<kx&&8>kx&&-1<(ky+1)&&8>(ky+1)){if(kh[kx][ky+1].iro==0){kl+=1;}}
if(-1<(kx+1)&&8>(kx+1)&&-1<(ky-1)&&8>(ky-1)){if(kh[kx+1][ky-1].iro==0){kl+=1;}}
if(-1<(kx+1)&&8>(kx+1)&&-1<ky&&8>ky){if(kh[kx+1][ky].iro==0){kl+=1;}}
if(-1<(kx+1)&&8>(kx+1)&&-1<(ky+1)&&8>(ky+1)){if(kh[kx+1][ky+1].iro==0){kl+=1;}}
return kl;}//開放度の測定//ここから３D 化
let canvas = document.getElementById("canvas");let ctx = canvas.getContext('2d');
let zahyou=[];let gyoukaku=-40;
let muki=0;
var siten={"x":0,"y":0,"z":0};
let sc=[];let eye = {}let d2y={}let d2x={}
var path=0
for(k=0;k<49;k++){creface(10+10*k,10,-10,10,0,40,"black")}
for(k=0;k<49;k++){creface(10,10+10*k,-10,0,10,40,"black")}
for(k=0;k<49;k++){creface(10,10+10*k,-10,0,10,40,"black")}

for(k=0;k<49;k++){creface(500-10*k,500,30,-10,0,-40,"black")}
for(k=0;k<49;k++){creface(500,500-10*k,30,0,-10,-40,"black")}
for(k=0;k<9;k++){for(i=0;i<7;i++){creface(10+70*i,10+60*k,30,70,10,0,"black")}}
for(k=0;k<9;k++){for(i=0;i<7;i++){creface(10+60*k,10+70*i,30,10,70,0,"black")}}
for(i=0;i<8;i++){for(k=0;k<8;k++){creface(20+60*i,20+60*k,30,50,50,0,"green")}}

//オセロ盤の作成
function nagasa(arr){
let len=Math.sqrt(arr.x*arr.x+arr.y*arr.y+arr.z*arr.z)
return len}//ベクトルの大きさを計算
function vec(arr1,arr2){
let ve={}ve.x=arr2.x-arr1.x
ve.y=arr2.y-arr1.yve.z=arr2.z-arr1.z
return ve}//ベクトルを作成
function cosv(arr1,arr2){
let naiseki=arr1.x*arr2.x+arr1.y*arr2.y+arr1.z*arr2.z
let len=nagasa(arr1)*nagasa(arr2)
return naiseki/len}//ベクトルの内積によって cos を計算
function reye(){eye = {
"x":Math.cos(gyoukaku * (Math.PI / 180))*Math.sin(muki * (Math.PI / 180)),"y":Math.cos(gyoukaku * (Math.PI / 180))*Math.cos(muki* (Math.PI / 180)),"z":Math.sin(gyoukaku * (Math.PI / 180))}d2x.x=Math.cos(muki * (Math.PI / 180))d2x.y=-1*Math.sin(muki * (Math.PI / 180))d2x.z=0d2y.x=-1*Math.sin(gyoukaku * (Math.PI / 180))*Math.sin(muki * (Math.PI / 180))
d2y.y=-1*Math.sin(gyoukaku * (Math.PI / 180))*Math.cos(muki* (Math.PI / 180))d2y.z=Math.cos(gyoukaku * (Math.PI / 180))}//視線の方向を反映
function bai(arr,n){let kakeru={}kakeru.x=arr.x*n+siten.x
kakeru.y=arr.y*n+siten.ykakeru.z=arr.z*n+siten.zreturn kakeru}//ベクトルをｎ倍する

function view(){reye()
zahyou=[]let eyeob={}for(n=0;n<sc.length;n++){for(m=0;m<sc[n].edge.length;m++){eyeob=vec(siten,sc[n].edge[m])let cos1=cosv(eye,eyeob)
let center=bai(eye,nagasa(eyeob)*cos1)
let d2vec=vec(center,sc[n].edge[m])let menx=cosv(d2vec,d2x)
let meny=cosv(d2vec,d2y)
let shousitu=bai(eye,2000)
const
fx=0.5*canvas.width-((nagasa(d2vec)*menx))*(nagasa(vec(shousitu,sc[n].edge[m]))/2000)
const
fy=0.5*canvas.height-((nagasa(d2vec)*meny))*(nagasa(vec(shousitu,sc[n].edge[m]))/2000)

sc[n].edge[m].drawx=fx
sc[n].edge[m].drawy=fy}

}}//物体の視点などによる位置の測定
function redraw(){koma2()
view()
for(p=0;p<sc.length;p++){const d=nagasa(vec(siten,sc[p].ave))sc[p].dis=d}sc.sort(compareFunc)
console.log(sc)ctx.clearRect(0, 0, canvas.width, canvas.height);
for(q=0;q<sc.length;q++){sc[q].dfunc(sc[q])}}//実際の描画

document.onkeydown = function(e){let keyCode = false;
if (e) event = e;if (event) {if (event.keyCode) {keyCode = event.keyCode;} else if (event.which) {keyCode = event.which;}}if(keyCode==37){muki+=1}
if(keyCode==39){muki-=1}
if(keyCode==38){gyoukaku+=1}
if(keyCode==40){gyoukaku-=1}
console.log("仰角",gyoukaku,"向き",muki,"siten",siten)siten={"x":150-250*Math.cos(gyoukaku * (Math.PI / 180))*Math.sin(muki *(Math.PI / 180)),"y":150-250*Math.cos(gyoukaku * (Math.PI / 180))*Math.cos(muki* (Math.PI /180)),"z":150-250*Math.sin(gyoukaku * (Math.PI / 180))}view()
redraw()}//仰角と方位角を操作
function compareFunc(a, b) {return b.dis - a.dis;}function creface(sx,sy,sz,lx,ly,lz,color){
let pt=path
sc[pt]={"path":pt,"clr":color,"ave":{"x":sx+(lx/2),"y":sy+(ly/2),"z":sz+(lz/2)},"edge":[{"x":sx,"y":sy,"z":sz},{"x":sx+lx,"y":sy,"z":sz},{"x":sx+lx,"y":sy+ly,"z":sz},{"x":sx,"y":sy+ly,"z":sz},{"x":sx,"y":sy+ly,"z":sz+lz},{"x":sx,"y":sy,"z":sz+lz},{"x":sx+lx,"y":sy,"z":sz+lz},{"x":sx+lx,"y":sy,"z":sz},{"x":sx,"y":sy,"z":sz}],"dfunc":function(x){drawR(x)}}path+=1}function koma2(){for(s=0;s<8;s++){for(t=0;t<8;t++){if(osero[s][t].iro==1&&oserobefo[s][t].iro!=osero[s][t].iro){
crecir(465-t*60,465-s*60,40,10,"white")}else{
if(osero[s][t].iro==2&&oserobefo[s][t].iro!=osero[s][t].iro){
crecir(465-t*60,465-s*60,40,10,"black")}else{}}}}
for(s=0;s<8;s++){for(t=0;t<8;t++){oserobefo[s][t]= Object.create(osero[s][t]);}}}//直方体を作成

function drawR(obje){
ctx.beginPath();ctx.moveTo(obje.edge[0].drawx,obje.edge[0].drawy)
for(k=0;k<obje.edge.length;k++){ctx.lineTo(obje.edge[k].drawx,obje.edge[k].drawy)}
ctx.closePath();ctx.fillStyle =obje.clr;
ctx.fill();
ctx.stroke();console.log(obje)}
function crecir(sx,sy,sz,r,color){
let pt=path
sc[pt]={"path":pt,"diam":r,"clr":color,"ave":{"x":sx,"y":sy,"z":sz},"edge":[{"x":sx,"y":sy,"z":sz},{"x":sx,"y":sy+r,"z":sz},{"x":sx+r,"y":sy,"z":sz},{"x":sx,"y":sy-r,"z":sz},

{"x":sx-r,"y":sy,"z":sz},{"x":sx,"y":sy+r,"z":sz}],"dfunc":function(x){drawC(x)}}path+=1}function drawC(obje){
let Dia=obje.diam//obje.dis
ctx.beginPath();var
cx=(obje.edge[1].drawx+obje.edge[2].drawx+obje.edge[3].drawx+obje.edge[4].
drawx)/4var
cy=(obje.edge[1].drawy+obje.edge[2].drawy+obje.edge[3].drawy+obje.edge[4].
drawy)/4
console.log(obje.dis)
ctx.ellipse(cx, cy,Math.abs(Dia),Math.abs(Dia*Math.sin(gyoukaku * (Math.PI /180))),0, 0, 2 * Math.PI);
ctx.stroke()ctx.fillStyle =obje.clr;
ctx.fill();｝//円を作成</script></body></html>３．成果
オセロ自体は完成したが。しかしながら、終始一貫して同じ論理を用いているせいか
弱い、オセロ AI としてあまり満足のいかない結果となった。３D の描画に関しては今回はｚソート法のみを用いていたためある一定の角度にすると表示にバグが起きること以外は満足のいく結果となった。

４．今後の展望
オセロのアルゴリズムがまだ単純なもので、状況による判断ができないため、その点をどう学習させるかが AI 学習のカギとなると感じた。

５．参考文献ならびに参考 Web ページ
https://developer.mozilla.org/ja/>>>MDN

web docs という JavaScript などの文法がまとめられたウェブサイト。