function setup(){
canvasWidth = 600;
canvasHeight = 600;
cvs= createCanvas(canvasWidth,canvasHeight);
background('#1b5e20');
row = 8;
rowWidth = canvasWidth / row;
radius = rowWidth-20;
count = 1; // 돌을 놓는 차례. 1을 검정색으로 설정
blackScore = whiteScore = 2;
blackAvailable = whiteAvailable = 2;
pass = 0;
checkDirection = [[1, -1], [1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1],];
board = new Array();
buffer = new Array();
boardHistory = new Array();
tik = new Audio("tik.mp3");
beep = new Audio("beep.wav");
ending = new Audio("ending.wav");
plz = new Audio("plz.m4a");
oneMore = new Audio("oneMore.m4a");
winScreen = document.querySelector('.winShow');
turnPass = document.querySelector(".turnPass");
// 보드 격자를 그리고, 모든 칸에 -1을 입력
boardInit();
// 시작 돌 4개
board[3][3] = board[4][4] = 1;
board[4][3] = board[3][4] = 0;
checkAvailable();
drawBoard();
document.querySelector("#black").innerHTML = "검정색 점수 : " + blackScore;
document.querySelector("#white").innerHTML = "하얀색 점수 : " + whiteScore;
button1 = document.querySelector("#withdraw");
button2 = document.querySelector("#reload");
troImg = document.querySelector("#trophyImg");
// 무르기 버튼 동작
button1.addEventListener('mouseup', ()=>{
plz.currentTime = 0.5;
plz.play();
withdraw();
})
button2.addEventListener('mouseup', ()=>{
oneMore.currentTime = 0.5;
oneMore.play();
setTimeout(() => {
location.reload();
}, 2000);
})
canvasPosition = cvs.position(0,30);
}
function boardInit(){
// 보드 격자를 그리고, 모든 칸에 -1을 입력
stroke("black");
strokeWeight(2);
fill('#1b5e20');
for (i = 0; i < 8; i++) {
board[i] = new Array(8);
for (j = 0; j < 8; j++) {
rect(i * rowWidth, j * rowWidth, rowWidth, rowWidth);
board[i][j] = -1;
}
}
console.log('-1 초기화')
fill("black");
circle(rowWidth * 2, rowWidth * 2, 10);
circle(rowWidth * 2, rowWidth * 6, 10);
circle(rowWidth * 6, rowWidth * 2, 10);
circle(rowWidth * 6, rowWidth * 6, 10);
}
// 마우스 클릭하면 그 칸의 위치 파악
document.addEventListener("mouseup", (e) => {
// console.log('offset' , e.offsetX, e.offsetY);
// console.log('page' , e.pageX, e.pageY);
if(e.offsetX > 0 && e.offsetX < canvasWidth && e.pageY > canvasPosition.y && e.offsetY > 0 && e.offsetY < canvasHeight){
let rowX = floor(e.offsetX / rowWidth);
let rowY = floor(e.offsetY / rowWidth);
main(rowX, rowY);
}
});
// 객체 복사하는데, 이전 값을 계속 참조하는 것을 막는 함수
function cloneObj(obj){
const result = [];
// console.log(obj)
for( i = 0 ; i< 8 ;i++ ){
result[i] = JSON.parse(JSON.stringify(obj[i]));
}
return result;
}
// 메인 함수. 클릭된 칸에 흰색(0), 검은색(1) 입력하고,
// 뒤집어야 하는 함수 호출, 보드 전체 그리는 함수 호출
function main(x, y) {
// 돌을 놓을 수 있는 곳일때만 주요 함수들 실행
if (board[y][x] == 2 || board[y][x] == 3) {
tik.currentTime = 0.5;
tik.play();
board[y][x] = count % 2;
// 돌을 놓을 수 있는 위치에 3(검정)이나 2(흰색)로 보드에 입력하는 함수 호출
checkReversible(x, y);
count++;
// 돌을 뒤집어야 하는 경우에, 바뀐 색으로 보드에 입력
checkAvailable();
let boardTemp = board;
// board배열상태로 보드를 그려줌
drawBoard();
// 검정,하얀 돌 개수 계산
scoreCalc();
// 무르기를 위해서 매 차례의 보드 배열을 통째로 boardHistory배열에 입력
boardHistory.push(cloneObj(board));
// console.log('boardHistory', boardHistory);
} else {
beep.play();
console.log('Not Here')
}
}
// 무르기 함수
function withdraw(){
boardInit();
boardHistory.pop();
board = cloneObj(boardHistory.slice(-1)[0]);
// board = boardHistory.slice(-1)[0];
console.log(boardHistory);
count--;
drawBoard();
scoreCalc();
}
// 점수 계산 함수
// 점수 계산 및 돌을 둘 수 있는 곳이 몇 개 있는지도 확인
// 만약 돌을 둘 수 있는 곳이 없으면, 나중에 패스하도록
function scoreCalc(){
blackScore = whiteScore = 0;
blackAvailable = whiteAvailable = 0;
for(i=0;i<8;i++){
blackScore += board[i].filter((e) => e === 1).length;
whiteScore += board[i].filter((e) => e === 0).length;
blackAvailable += board[i].filter((e) => e === 3).length;
whiteAvailable += board[i].filter((e) => e === 2).length;
}
document.querySelector("#black").innerHTML = "검정색 점수 : " + blackScore;
document.querySelector("#white").innerHTML = "하얀색 점수 : " + whiteScore;
if (count % 2 == 0 && whiteAvailable == 0 && pass != 2) {
console.log("no white move");
pass++;
}
if (count % 2 == 1 && blackAvailable == 0 && pass != 2) {
console.log("no black move");
pass++;
}
// 놓을 곳이 없으면 상대방에게 차례 넘김
if(pass == 1){
console.log("다음 차례로 넘어갑니다.");
turnPass.style.zIndex = 3;
turnPass.style.visibility = "visible";
turnPass.style.animationName = "moveDown";
console.log(turnPass);
setTimeout(() => {
turnPass.style.zIndex = -1;
}, 2500);
count++;
}
// 혹시 둘 곳이 없어서 다음 차례로 넘어간 경우 때문에
// 가능한 곳을 다시 찾고, 다시 그려주는 함수 호출
pass++;
checkAvailable();
drawBoard();
}
// 배열 상태대로 보드 전체에 돌 및 놓을 수 있는 위치를 그려줌
function drawBoard(){
noStroke();
// board배열에 따라 흰색,검정색,작은 사각형 그려주고
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
switch (board[i][j]) {
case 0:
fill("white");
circle((j+1)*rowWidth - floor(rowWidth/2), (i+1)*rowWidth - floor(rowWidth/2), radius);
break;
case 1:
fill("black");
circle((j+1)*rowWidth - floor(rowWidth/2), (i+1)*rowWidth - floor(rowWidth/2), radius);
break;
case 2:
fill("rgba(255,255,255,1)");
rect((j+1)*rowWidth - floor(rowWidth/2)-4, (i+1)*rowWidth - floor(rowWidth/2)-4, 10, 10 );
break;
case 3:
fill("rgba(0,0,0,1)");
rect((j+1)*rowWidth - floor(rowWidth/2)-4, (i+1)*rowWidth - floor(rowWidth/2)-4, 10, 10 );
break;
default :
fill("#1b5e20");
rect((j+1)*rowWidth - floor(rowWidth/2)-8, (i+1)*rowWidth - floor(rowWidth/2)-8, 16, 16 );
break;
}
}
}
}
// 원을 뒤집어야 하는지 여부 확인해서 0(하얀색),1(검정색)을 좌표에 입력
function checkReversible(x,y){
// 8방향으로 체크하는 루프
for (j = 0; j < checkDirection.length; j++) {
cX = x;
cY = y;
while (cX >= 0 && cY >= 0 && cX < 8 && cY < 8) {
cX = cX + checkDirection[j][0];
cY = cY + checkDirection[j][1];
if (cX < 0 || cY < 0 || cX >= 8 || cY >= 8) {
break;
} else {
if (board[cY][cX] == count%2 || board[cY][cX] == -1 || board[cY][cX] == 2 || board[cY][cX] == 3) {
buffer.push([cX, cY]);
break;
} else {
buffer.push([cX, cY]);
}
}
}
// console.log(buffer)
if (buffer.length >= 1) {
if (
count%2 == board[buffer[buffer.length - 1][1]][buffer[buffer.length - 1][0]]
) {
// console.log('here', count % 2);
for (i = 0; i < buffer.length; i++) {
board[buffer[i][1]][buffer[i][0]] = count%2;
}
}
}
buffer = [];
}
}
// 돌을 놓을 수 있는 위치 파악해서, 검정색 가능위치(3), 하얀색 가능위치(2)로 board에 기록
function checkAvailable(){
// 둘 곳 없어서 패스된게 두 번이 되면 게임 종료
if(pass>1){
console.log('game over')
turnPass.style.visibility="hidden";
gameOver();
}
// 이전 차례에서 2,3이었던 값을 -1로 초기화하는 함수 호출
resetAvailable();
boardCopy = board;
// console.log(boardCopy)
for (i=0;i<checkDirection.length;i++){
for(k=0;k<checkDirection.length;k++){
tX = i;
tY = k;
for (j = 0; j < checkDirection.length; j++) {
// 검사할 좌표들을 aX,aY로 설정
aX = tX;
aY = tY;
// 8방향으로 검사하는 루프
while (aX >= 0 && aY >= 0 && aX < 8 && aY < 8) {
aX += checkDirection[j][0];
aY += checkDirection[j][1];
// 검사 영역이 8x8 판 밖으로 나가면 멈추고,
if (aX < 0 || aY < 0 || aX >= 8 || aY >= 8) {
break;
}
// 판 안에서 검사하는 칸들을 배열에 넣는다.
else {
buffer.push([aX, aY, boardCopy[aY][aX]]);
// 검사한 칸의 색이 이번 차례의 색과 같거나, 빈 칸이면 배열에 넣기를 멈춘다.
// 아니라면 검사한 칸의 값을 계속 배열에 넣는 루프를 반복한다.
if (
boardCopy[aY][aX] === count % 2 ||
boardCopy[aY][aX] === -1 ||
boardCopy[aY][aX] === 2 ||
boardCopy[aY][aX] === 3 ||
boardCopy[tY][tX] !== -1
) {
break;
}
}
}
// 만약 돌들의 배열이 돌을 놓을 수 있는 조건이면 3(검은색)이나 2(흰색)을 입력한다
if (
buffer.length > 1 &&
boardCopy[buffer[0][1]][buffer[0][0]] != count % 2 &&
boardCopy[buffer[buffer.length - 1][1]][buffer[buffer.length - 1][0]] === count%2
) {
// console.log(count);
switch (count % 2 ) {
case 0:
board[tY][tX] = 2;
break;
case 1:
board[tY][tX] = 3;
break;
}
pass = 0;
}
buffer = [];
}
}
}
}
function resetAvailable(){
for (i=0;i<row;i++){
for(k=0;k<row;k++){
if(board[i][k]==2 || board[i][k]== 3){
board[i][k]= -1;
}
}
}
};
// 승리 화면 표시
function gameOver(x) {
ending.play();
// 음악이 재생되도록 약간의 시차를 두고 화면 표시
setTimeout(() => {
winScreen.style.visibility = 'visible';
winScreen.style.zIndex = 2;
if(blackScore > whiteScore){
document.querySelector(".comment").innerHTML = "<br>" + "검정색 승리";
}
if(blackScore < whiteScore){
document.querySelector(".comment").innerHTML = "<br>" + "하얀색 승리";
}
if(blackScore == whiteScore){
document.querySelector(".comment").innerHTML = "<br>" + "무승부";
}
console.log(winScreen)
troImg.style.animationName = "trophy";
}, 300);
}