사용자:Bd3076/대규모 실험실/8/plugin: 두 판 사이의 차이
< 사용자:Bd3076 | 대규모 실험실 | 8
백괴게임>Bd3076 편집 요약 없음 |
백괴게임>Bd3076 편집 요약 없음 |
||
(같은 사용자의 중간 판 13개는 보이지 않습니다) | |||
3번째 줄: | 3번째 줄: | ||
* 용도: 2048 MP에 사용될 플러그인 | * 용도: 2048 MP에 사용될 플러그인 | ||
*/ | */ | ||
var api = MediaWikiAPI(); | |||
// 보드판 생성 | // 보드판 생성 | ||
13번째 줄: | 15번째 줄: | ||
// 점수 생성 | // 점수 생성 | ||
var | var myScore = 0; | ||
var maxScore = localStorage.getItem('maxScore'); | |||
if(maxScore === null) maxScore = 0; | |||
// 캔버스 구문 | // 캔버스 구문 | ||
111번째 줄: | 115번째 줄: | ||
// 점수 그리기 | // 점수 그리기 | ||
ctx.fillStyle = "#f2ddaf"; | ctx.fillStyle = "#f2ddaf"; | ||
ctx.font = "bold 30px sans-serif"; | |||
ctx.fillText("YOUR SCORE", 697, 33); | ctx.fillText("YOUR SCORE", 697, 33); | ||
121번째 줄: | 126번째 줄: | ||
ctx.lineTo(774, 150); | ctx.lineTo(774, 150); | ||
ctx.arc(774, 140, 10, 0, Math.PI/2); | ctx.arc(774, 140, 10, 0, Math.PI/2); | ||
ctx.lineTo(784, | ctx.lineTo(784, 140); | ||
ctx.lineTo(784, 76); | ctx.lineTo(784, 76); | ||
ctx.arc(774, 76, 10, Math.PI*3/2, Math.PI*2); | ctx.arc(774, 76, 10, Math.PI*3/2, Math.PI*2); | ||
131번째 줄: | 136번째 줄: | ||
ctx.fillStyle = "#776E65"; | ctx.fillStyle = "#776E65"; | ||
ctx.font = "bold 60px sans-serif"; | ctx.font = "bold 60px sans-serif"; | ||
ctx.fillText( | ctx.fillText(myScore, 697, 108); | ||
// 최고점수 그리기 | |||
ctx.fillStyle = "#f2ddaf"; | |||
ctx.font = "bold 30px sans-serif"; | |||
ctx.fillText("MAX SCORE", 697, 33+180); | |||
ctx.fillStyle = "#EEE4DA"; | |||
ctx.beginPath(); | |||
ctx.moveTo(610, 76+180); | |||
ctx.lineTo(610, 140+180); | |||
ctx.arc(620, 140+180, 10, Math.PI/2, Math.PI); | |||
ctx.lineTo(620, 150+180); | |||
ctx.lineTo(774, 150+180); | |||
ctx.arc(774, 140+180, 10, 0, Math.PI/2); | |||
ctx.lineTo(784, 140+180); | |||
ctx.lineTo(784, 76+180); | |||
ctx.arc(774, 76+180, 10, Math.PI*3/2, Math.PI*2); | |||
ctx.lineTo(774, 66+180); | |||
ctx.lineTo(620, 66+180); | |||
ctx.arc(620, 76+180, 10, Math.PI, Math.PI*3/2); | |||
ctx.closePath(); | |||
ctx.fill(); | |||
ctx.fillStyle = "#776E65"; | |||
ctx.font = "bold 60px sans-serif"; | |||
ctx.fillText(maxScore, 697, 108+180); | |||
}; | }; | ||
153번째 줄: | 183번째 줄: | ||
console.log(ek); | console.log(ek); | ||
// 판 움직이기 | // 판 움직이기 | ||
if(37 <= ek && ek <= 40) e.preventDefault(); | |||
switch(ek){ | switch(ek){ | ||
case 37: | case 37: | ||
168번째 줄: | 199번째 줄: | ||
cnt--; | cnt--; | ||
added[cnt-1][j] = 1; | added[cnt-1][j] = 1; | ||
myScore += board[cnt-1][j]; | |||
} | } | ||
} | } | ||
180번째 줄: | 211번째 줄: | ||
cnt--; | cnt--; | ||
added[cnt-1][j] = 1; | added[cnt-1][j] = 1; | ||
myScore += board[cnt-1][j]; | |||
} | } | ||
} | } | ||
201번째 줄: | 232번째 줄: | ||
cnt--; | cnt--; | ||
added[i][cnt-1] = 1; | added[i][cnt-1] = 1; | ||
myScore += board[i][cnt-1]; | |||
} | } | ||
} | } | ||
213번째 줄: | 244번째 줄: | ||
cnt--; | cnt--; | ||
added[i][cnt-1] = 1; | added[i][cnt-1] = 1; | ||
myScore += board[i][cnt-1]; | |||
} | } | ||
} | } | ||
234번째 줄: | 265번째 줄: | ||
cnt--; | cnt--; | ||
added[3-(cnt-1)][j] = 1; | added[3-(cnt-1)][j] = 1; | ||
myScore += board[3-(cnt-1)][j]; | |||
} | } | ||
} | } | ||
246번째 줄: | 277번째 줄: | ||
cnt--; | cnt--; | ||
added[3-(cnt-1)][j] = 1; | added[3-(cnt-1)][j] = 1; | ||
myScore += board[3-(cnt-1)][j]; | |||
} | } | ||
} | } | ||
267번째 줄: | 298번째 줄: | ||
cnt--; | cnt--; | ||
added[i][3-(cnt-1)] = 1; | added[i][3-(cnt-1)] = 1; | ||
myScore += board[i][3-(cnt-1)]; | |||
} | } | ||
} | } | ||
279번째 줄: | 310번째 줄: | ||
cnt--; | cnt--; | ||
added[i][3-(cnt-1)] = 1; | added[i][3-(cnt-1)] = 1; | ||
myScore += board[i][3-(cnt-1)]; | |||
} | } | ||
} | } | ||
294번째 줄: | 325번째 줄: | ||
board[re[0]][re[1]] = aNum; | board[re[0]][re[1]] = aNum; | ||
// 최고점수 갱신 | |||
if(maxScore < myScore){ | |||
maxScore = myScore; | |||
localStorage.setItem('maxScore', maxScore); | |||
} | |||
drawBoard(); | drawBoard(); | ||
// 게임 오버 감지 | // 게임 오버 감지 | ||
320번째 줄: | 357번째 줄: | ||
function gameOver(){ | function gameOver(){ | ||
ctx.fillStyle = " | ctx.fillStyle = "rgba(187, 171, 160, 0.2)"; | ||
ctx.fillRect(0, 0, | ctx.fillRect(0, 0, 800, 600); | ||
ctx.fillStyle = "black"; | ctx.fillStyle = "black"; | ||
ctx.font = "bold 100px sans-serif"; | ctx.font = "bold 100px sans-serif"; | ||
327번째 줄: | 364번째 줄: | ||
ctx.font = "bold 20px sans-serif"; | ctx.font = "bold 20px sans-serif"; | ||
ctx.fillText("다시 시작하려면 새로고침하세요", 300, 450); | ctx.fillText("다시 시작하려면 새로고침하세요", 300, 450); | ||
var username = mw.config.get('wgUserName'); | |||
if(username === null){ | |||
ctx.fillText("랭킹에 결과를 등록하기 위해서는 로그인이 필요합니다", 300, 500); | |||
} | |||
else{ | |||
updateRanking(); | |||
ctx.fillText("랭킹은 게임 토론 메뉴에서 확인 가능합니다", 300, 500); | |||
} | |||
return; | return; | ||
} | |||
function scoreData(){ | |||
var score; | |||
var name; | |||
var time; | |||
} | |||
var bigger = function(a, b){ | |||
if(a.score != b.score) return a.score > b.score; | |||
return a.time < b.time; | |||
} | |||
function updateRanking(){ | |||
var username = mw.config.get('wgUserName'); | |||
var rankingDoc = api.getDocument("2048 MP/Ranking"); | |||
var json = JSON.parse(rankingDoc); | |||
var myData = new scoreData(); | |||
myData.score = myScore; | |||
myData.name = mw.config.get('wgUserName'); | |||
myData.time = Date.now(); | |||
var rnum = undefined; | |||
// 랭킹 구조 | |||
// json[data]: 구조체 데이터 | |||
// json[rank]: 각 사람별 등수 | |||
for(var i=json['data'].length-1; i>=0; i--){ | |||
if(bigger(myData, json['data'][i])){ | |||
json['data'][i+1] = json['data'][i]; | |||
if(json['rank'][json['data'][i].name] === undefined || json['rank'][json['data'][i].name] == i){ | |||
json['rank'][json['data'][i].name] = i+1; | |||
} | |||
json['data'][i] = null; | |||
} | |||
else{ | |||
json['data'][i+1] = myData; | |||
rnum = i+2; | |||
break; | |||
} | |||
} | |||
if(rnum === undefined){ | |||
json['data'][0] = myData; | |||
rnum = 1; | |||
} | |||
if(!(json['rank'][myData.name] === undefined && json['rank'][myData.name] < rnum)){ | |||
json['rank'][myData.name] = rnum; | |||
} | |||
console.log(json); | |||
api.changeDocument('2048 MP/ranking', '랭킹 갱신', JSON.stringify(json), 1, 1); | |||
} | } | ||
2019년 4월 10일 (수) 18:01 기준 최신판
/** 2048 plugin
* 제작자: Bd3076
* 용도: 2048 MP에 사용될 플러그인
*/
var api = MediaWikiAPI();
// 보드판 생성
var board = new Array(new Array(4), new Array(4), new Array(4), new Array(4));
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
board[i][j] = 0;
}
}
// 점수 생성
var myScore = 0;
var maxScore = localStorage.getItem('maxScore');
if(maxScore === null) maxScore = 0;
// 캔버스 구문
document.getElementById('gameArea').innerHTML = '<canvas id="cvs" width="800" height="600"></canvas>';
var canvas = document.getElementById('cvs');
var ctx = canvas.getContext('2d');
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// 비어있는 칸이 있는지 판별하는 함수
var emptyExist = function(){
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
if(!board[i][j]) return true;
}
}
return false;
};
// 비어있는 칸 중 하나를 랜덤으로 고르는 함수
var randomEmpty = function(){
var emptyArray = new Array(0); // 비어 있는 칸들의 목록
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
if(!board[i][j]) emptyArray.push([i, j]);
}
}
if(emptyArray.length === 0){
console.log("error: no empty slots");
return null;
}
return emptyArray[Math.floor(Math.random() * emptyArray.length)];
};
// 보드판의 상태를 캔버스에 그리는 함수
var drawBoard = function(){
// 숫자에 따른 색
var numberColor = ["#CDC1B4", "#EEE4DA", "#EDE0C8", "#F2B179", "#F59563",
"#F67C5F", "#F6523B", // ~64
"#EDCF72", "#EDCC61", "#EDC850",
"#EDC53F", "#EDC22E", "#EBB914", "#D3A612", // ~8192
"#BC9410", "#BC9410", "#BC9410", "#BC9410"];
// 보드판의 개형 그리기
ctx.fillStyle = "#BBADA0";
ctx.beginPath();
ctx.moveTo(0, 10);
ctx.lineTo(0, 590);
ctx.arc(10, 590, 10, Math.PI/2, Math.PI);
ctx.lineTo(10, 600);
ctx.lineTo(790, 600);
ctx.arc(790, 590, 10, 0, Math.PI/2);
ctx.lineTo(800, 590);
ctx.lineTo(800, 10);
ctx.arc(790, 10, 10, Math.PI*3/2, Math.PI*2);
ctx.lineTo(790, 0);
ctx.lineTo(10, 0);
ctx.arc(10, 10, 10, Math.PI, Math.PI*3/2);
ctx.closePath();
ctx.fill();
// 각 칸 그리기
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
// 외형 그리기
var startX = 16 + 146*i;
var startY = 16 + 146*j;
ctx.fillStyle = numberColor[board[i][j] === 0 ? 0 : Math.round(Math.log2(board[i][j]))];
ctx.beginPath();
ctx.moveTo(startX, startY+4);
ctx.lineTo(startX, startY+126);
ctx.arc(startX+4, startY+126, 4, Math.PI/2, Math.PI);
ctx.lineTo(startX+4, startY+130);
ctx.lineTo(startX+126, startY+130);
ctx.arc(startX+126, startY+126, 4, 0, Math.PI/2);
ctx.lineTo(startX+130, startY+126);
ctx.lineTo(startX+130, startY+4);
ctx.arc(startX+126, startY+4, 4, Math.PI*3/2, Math.PI*2);
ctx.lineTo(startX+126, startY);
ctx.lineTo(startX+4, startY);
ctx.arc(startX+4, startY+4, 4, Math.PI, Math.PI*3/2);
ctx.closePath();
ctx.fill();
// 텍스트 그리기
if(board[i][j] !== 0){
var numberLength = board[i][j].toString().length;
var fontSize = numberLength == 1 ? 80 : 160 / numberLength;
ctx.fillStyle = "#776E65";
ctx.font = "bold " + fontSize + "px sans-serif";
console.log("bold " + fontSize + "px sans-serif");
ctx.fillText(board[i][j], startX+65, startY+65);
}
}
}
// 점수 그리기
ctx.fillStyle = "#f2ddaf";
ctx.font = "bold 30px sans-serif";
ctx.fillText("YOUR SCORE", 697, 33);
ctx.fillStyle = "#EEE4DA";
ctx.beginPath();
ctx.moveTo(610, 76);
ctx.lineTo(610, 140);
ctx.arc(620, 140, 10, Math.PI/2, Math.PI);
ctx.lineTo(620, 150);
ctx.lineTo(774, 150);
ctx.arc(774, 140, 10, 0, Math.PI/2);
ctx.lineTo(784, 140);
ctx.lineTo(784, 76);
ctx.arc(774, 76, 10, Math.PI*3/2, Math.PI*2);
ctx.lineTo(774, 66);
ctx.lineTo(620, 66);
ctx.arc(620, 76, 10, Math.PI, Math.PI*3/2);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "#776E65";
ctx.font = "bold 60px sans-serif";
ctx.fillText(myScore, 697, 108);
// 최고점수 그리기
ctx.fillStyle = "#f2ddaf";
ctx.font = "bold 30px sans-serif";
ctx.fillText("MAX SCORE", 697, 33+180);
ctx.fillStyle = "#EEE4DA";
ctx.beginPath();
ctx.moveTo(610, 76+180);
ctx.lineTo(610, 140+180);
ctx.arc(620, 140+180, 10, Math.PI/2, Math.PI);
ctx.lineTo(620, 150+180);
ctx.lineTo(774, 150+180);
ctx.arc(774, 140+180, 10, 0, Math.PI/2);
ctx.lineTo(784, 140+180);
ctx.lineTo(784, 76+180);
ctx.arc(774, 76+180, 10, Math.PI*3/2, Math.PI*2);
ctx.lineTo(774, 66+180);
ctx.lineTo(620, 66+180);
ctx.arc(620, 76+180, 10, Math.PI, Math.PI*3/2);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "#776E65";
ctx.font = "bold 60px sans-serif";
ctx.fillText(maxScore, 697, 108+180);
};
// 키보드 입력을 받아 판을 이동시키고, 새로운 숫자를 만들거나 게임 오버시키는 함수
$("#left").click(function(){ gameRunner({keyCode: 37})});
$("#up").click(function(){ gameRunner({keyCode: 38})});
$("#right").click(function(){ gameRunner({keyCode: 39})});
$("#down").click(function(){ gameRunner({keyCode: 40})});
var gameRunner = function(e){
var ek = e.keyCode;
var cnt;
var moved = 0;
var added = new Array(new Array(4), new Array(4), new Array(4), new Array(4));
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
added[i][j] = 0;
}
}
console.log(ek);
// 판 움직이기
if(37 <= ek && ek <= 40) e.preventDefault();
switch(ek){
case 37:
for(var j=0; j<4; j++){
cnt = 0;
for(var i=0; i<4; i++){
if(i>0 && board[i][j] !== 0 && board[i-1][j] === 0){
board[cnt++][j] = board[i][j];
board[i][j] = 0;
moved = 1;
if(cnt > 1 && board[cnt-1][j] == board[cnt-2][j] && !added[cnt-2][j]){
board[cnt-2][j] *= 2;
board[cnt-1][j] = 0;
cnt--;
added[cnt-1][j] = 1;
myScore += board[cnt-1][j];
}
}
else if(board[i][j] !== 0){
cnt++;
if(cnt > 1 && board[cnt-1][j] == board[cnt-2][j] && !added[cnt-2][j]){
moved = 1;
board[cnt-2][j] *= 2;
board[cnt-1][j] = 0;
cnt--;
added[cnt-1][j] = 1;
myScore += board[cnt-1][j];
}
}
}
}
if(!moved) return;
break;
case 38:
for(var i=0; i<4; i++){
cnt = 0;
for(var j=0; j<4; j++){
if(j>0 && board[i][j] !== 0 && board[i][j-1] === 0){
board[i][cnt++] = board[i][j];
board[i][j] = 0;
moved = 1;
if(cnt > 1 && board[i][cnt-1] == board[i][cnt-2] && !added[i][cnt-2]){
board[i][cnt-2] *= 2;
board[i][cnt-1] = 0;
cnt--;
added[i][cnt-1] = 1;
myScore += board[i][cnt-1];
}
}
else if(board[i][j] !== 0){
cnt++;
if(cnt > 1 && board[i][cnt-1] == board[i][cnt-2] && !added[i][cnt-2]){
moved = 1;
board[i][cnt-2] *= 2;
board[i][cnt-1] = 0;
cnt--;
added[i][cnt-1] = 1;
myScore += board[i][cnt-1];
}
}
}
}
if(!moved) return;
break;
case 39:
for(var j=0; j<4; j++){
cnt = 0;
for(var i=3; i>=0; i--){
if(i<3 && board[i][j] !== 0 && board[i+1][j] === 0){
board[3-(cnt++)][j] = board[i][j];
board[i][j] = 0;
moved = 1;
if(cnt > 1 && board[3-(cnt-1)][j] == board[3-(cnt-2)][j] && !added[3-(cnt-2)][j]){
board[3-(cnt-2)][j] *= 2;
board[3-(cnt-1)][j] = 0;
cnt--;
added[3-(cnt-1)][j] = 1;
myScore += board[3-(cnt-1)][j];
}
}
else if(board[i][j] !== 0){
cnt++;
if(cnt > 1 && board[3-(cnt-1)][j] == board[3-(cnt-2)][j] && !added[3-(cnt-2)][j]){
moved = 1;
board[3-(cnt-2)][j] *= 2;
board[3-(cnt-1)][j] = 0;
cnt--;
added[3-(cnt-1)][j] = 1;
myScore += board[3-(cnt-1)][j];
}
}
}
}
if(!moved) return;
break;
case 40:
for(var i=0; i<4; i++){
cnt = 0;
for(var j=3; j>=0; j--){
if(j<3 && board[i][j] !== 0 && board[i][j+1] === 0){
board[i][3-(cnt++)] = board[i][j];
board[i][j] = 0;
moved = 1;
if(cnt > 1 && board[i][3-(cnt-1)] == board[i][3-(cnt-2)] && !added[i][3-(cnt-2)]){
board[i][3-(cnt-2)] *= 2;
board[i][3-(cnt-1)] = 0;
cnt--;
added[i][3-(cnt-1)] = 1;
myScore += board[i][3-(cnt-1)];
}
}
else if(board[i][j] !== 0){
cnt++;
if(cnt > 1 && board[i][3-(cnt-1)] == board[i][3-(cnt-2)] && !added[i][3-(cnt-2)]){
moved = 1;
board[i][3-(cnt-2)] *= 2;
board[i][3-(cnt-1)] = 0;
cnt--;
added[i][3-(cnt-1)] = 1;
myScore += board[i][3-(cnt-1)];
}
}
}
}
if(!moved) return;
break;
default:
return;
}
// 숫자 추가
var aNum = (Math.random() < 0.875) ? 2 : 4;
var re = randomEmpty();
board[re[0]][re[1]] = aNum;
// 최고점수 갱신
if(maxScore < myScore){
maxScore = myScore;
localStorage.setItem('maxScore', maxScore);
}
drawBoard();
// 게임 오버 감지
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
if(board[i][j] === 0) return;
}
}
for(var i=0; i<4; i++){
for(var j=0; j<3; j++){
if(board[i][j] == board[i][j+1]) return;
}
}
for(var i=0; i<3; i++){
for(var j=0; j<4; j++){
if(board[i][j] == board[i+1][j]) return;
}
}
window.onkeydown = undefined;
setTimeout(gameOver, 2000);
};
function gameOver(){
ctx.fillStyle = "rgba(187, 171, 160, 0.2)";
ctx.fillRect(0, 0, 800, 600);
ctx.fillStyle = "black";
ctx.font = "bold 100px sans-serif";
ctx.fillText("Game Over", 300, 300);
ctx.font = "bold 20px sans-serif";
ctx.fillText("다시 시작하려면 새로고침하세요", 300, 450);
var username = mw.config.get('wgUserName');
if(username === null){
ctx.fillText("랭킹에 결과를 등록하기 위해서는 로그인이 필요합니다", 300, 500);
}
else{
updateRanking();
ctx.fillText("랭킹은 게임 토론 메뉴에서 확인 가능합니다", 300, 500);
}
return;
}
function scoreData(){
var score;
var name;
var time;
}
var bigger = function(a, b){
if(a.score != b.score) return a.score > b.score;
return a.time < b.time;
}
function updateRanking(){
var username = mw.config.get('wgUserName');
var rankingDoc = api.getDocument("2048 MP/Ranking");
var json = JSON.parse(rankingDoc);
var myData = new scoreData();
myData.score = myScore;
myData.name = mw.config.get('wgUserName');
myData.time = Date.now();
var rnum = undefined;
// 랭킹 구조
// json[data]: 구조체 데이터
// json[rank]: 각 사람별 등수
for(var i=json['data'].length-1; i>=0; i--){
if(bigger(myData, json['data'][i])){
json['data'][i+1] = json['data'][i];
if(json['rank'][json['data'][i].name] === undefined || json['rank'][json['data'][i].name] == i){
json['rank'][json['data'][i].name] = i+1;
}
json['data'][i] = null;
}
else{
json['data'][i+1] = myData;
rnum = i+2;
break;
}
}
if(rnum === undefined){
json['data'][0] = myData;
rnum = 1;
}
if(!(json['rank'][myData.name] === undefined && json['rank'][myData.name] < rnum)){
json['rank'][myData.name] = rnum;
}
console.log(json);
api.changeDocument('2048 MP/ranking', '랭킹 갱신', JSON.stringify(json), 1, 1);
}
// 초기 보드판 상태: 2 또는 4가 총 2개 나오고, 4가 나올 확률은 각각 1/8
var sNum1 = (Math.random() < 0.875) ? 2 : 4;
var sNum2 = (Math.random() < 0.875) ? 2 : 4;
var re1 = randomEmpty();
board[re1[0]][re1[1]] = sNum1;
var re2 = randomEmpty();
board[re2[0]][re2[1]] = sNum2;
// 판 그리기
drawBoard();
window.onkeydown = gameRunner;