Antworten auf deine Fragen:
Neues Thema erstellen

Minesweeper

keul3

3dsMax | 3D-Contest

Hi,

ich habe jetzt endlich mein erstes JS geschrieben. Da ich mich erstmal mit der Sprache vertraut machen wollte, ist etwas kleineres geworden, eine Adaption von meiner FlashVersion

Es ist soweit spielbar, aber Luxusfunktionen wie Schwierigkeitsgrad oder ein HUD fehlen. Auch ist das ganze nicht wirklich fancy

zum Spiel

Da das für mich alles noch neu ist, hätte ich eine Bitte und zwar: könntet ihr bitte den Code einmal überfliegen und mir grundlegende Fehler (Peformancefresser) aufzeigen?:)

Auf anonyme Funktionen habe ich komplett verzichtet. Ich habe jede Variable innerhalb von Funktionen und Schleifen declariert, was afaik nicht unbedingt nötig ist, aber da ich mit einer rekursiven Funktion inkl. nicht deklarierter Variabel ziemlich aufs Maul geflogen bin, bin ich danach auf Nummer sicher gegangen:D
das JS hab ich erstmal als ganzes gelassen, würde es aber normalerweise aufteilen, so das z.B. alle drawFunktionen ausgelagert werden.

Danke schonmal für eure Hilfe;)

Javascript:
// JavaScript Document
//Minesweeper

var xCount = 30;
var yCount = 15;
var cellSize = 30;
var mineRatio = .2;
var canvasRect;
var canvas;
var cells;
var oldCell;
var markerKeyDown;
var gameOver;
var cellsToClear;

function init()
{
    createCanvas();
    window.addEventListener("keydown", keyDownHandler);
    window.addEventListener("keyup", keyUpHandler);
    window.addEventListener("resize", resizeHandler);
    createField()
}


function createField()
{
    markerKeyDown = false;
    gameOver = false;

    cells = createCells(xCount, yCount); //[x][y]

    if (mineRatio > 1) mineRatio = 1;
    if (mineRatio < 0) mineRatio = 0;
    var cellCount = xCount * yCount;
    var mineCount = Math.ceil(cellCount * mineRatio);
    cellsToClear = cellCount - mineCount;
    var mines = getMines(cellCount, mineCount);
    assignMinesToCells(mines, cells);
    countSurroundingMines(cells);

    for (var i = 0; i < cells.length; i++)
    {
        for (var j = 0; j < cells[i].length; j++) drawCover(cells[i][j]);
    }
}

function createCells(xC, yC)
{
    var cells = new Array();

    for (var i = 0; i < xCount; i++)
    {
        var temp = new Array();

        for (j = 0; j < yCount; j++)
        {
            var cell = new Object();
            cell.idX = i;
            cell.idY = j;
            cell.x = i * cellSize;
            cell.y = j * cellSize;
            cell.revealed = false;
            cell.revealedSurroundings = false;
            cell.marked = false;
    
            temp.push(cell);
        }
        cells.push(temp);
    }

    return cells;
}


function getMines(cellCount, mineCount)
{
    var numbers = new Array();
    var mines = new Array();
    for (var i = 0; i < cellCount; i++)
    {
        numbers.push(i);
        mines.push(false);
    }
    
    for (var j = 0; j < mineCount; j++)
    {
        var rn = Math.floor( Math.random() * numbers.length ); //randomNumber
        mines[ numbers[rn] ] = true;
        numbers.splice(rn, 1);
    }
    
    return mines;
}

function assignMinesToCells(m, c)
{
    var a = 0;
    
    for (var i = 0; i < c.length; i++)
    {
        for (var j = 0; j < c[i].length; j++)
        {
            c[i][j].mine = m[a];
            a++;
        }
    }
}

function countSurroundingMines(c)
{
    for (var i = 0; i < c.length; i++)
    {
        for (var j = 0; j < c[i].length; j++)
        {
            var a = 0;
            var sCells =     [
                                [i - 1, j - 1], //top-left
                                [i    , j - 1], //top
                                [i + 1, j - 1], //top-right
                                [i - 1, j    ], //left
                                [i + 1, j    ], //right
                                [i - 1, j + 1], //bottom-left
                                [i    , j + 1], //bottom
                                [i + 1, j + 1]  //bottom-right
                            ];
            
            for (var k = 0; k < sCells.length; k++)
            {
                if ( hasMine(sCells[k][0], sCells[k][1], c) ) a++;
            }
            c[i][j].minesAround = a;
        }
    }
}

function hasMine(x, y, c)
{
    var b = false;
    
    if (x >= 0 && x < xCount && y >= 0 && y < yCount) b = c[x][y].mine;
    
    return b;
}


function createCanvas()
{
    var w = xCount * cellSize;
    var h = yCount * cellSize;

    canvas = document.createElement("CANVAS");

    var attWidth = document.createAttribute("width");
    attWidth.value = w.toString();
    canvas.setAttributeNode(attWidth);

    var attHeight = document.createAttribute("height");
    attHeight.value = h.toString();
    canvas.setAttributeNode(attHeight);
    document.body.appendChild(canvas);

    canvas.addEventListener("click", clickHandler);
    canvas.addEventListener("mousemove", mouseMoveHandler);

    elementToCenterOfWindow(canvas);
    canvasRect = canvas.getBoundingClientRect();
}

function elementToCenterOfWindow(element)
{
    element.style.position = "absolute"
    element.style.left = (window.innerWidth - element.width)/2 + "px";
    element.style.top = (window.innerHeight - element.height)/2 + "px";
}


function drawCover(cell)
{
    var lineWidth = 2;

    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.rect(cell.x + lineWidth/2, cell.y + lineWidth/2, cellSize - lineWidth, cellSize - lineWidth);
    ctx.fillStyle = "#009900";
    ctx.fill();
    ctx.lineWidth = lineWidth;
    ctx.strokeStyle = "#006600";
    ctx.stroke();
    ctx.closePath();
}

function drawCoverHighlight(cell)
{
    var lineWidth = 2;

    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.rect(cell.x + lineWidth/2, cell.y + lineWidth/2, cellSize - lineWidth, cellSize - lineWidth);
    ctx.fillStyle = "#00bb00";
    ctx.fill();
    ctx.lineWidth = lineWidth;
    ctx.strokeStyle = "#009900";
    ctx.stroke();
    ctx.closePath();
}


function drawCell(cell)
{
    var lineWidth = 2;

    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.rect(cell.x + lineWidth/2, cell.y + lineWidth/2, cellSize - lineWidth, cellSize - lineWidth);
    ctx.fillStyle = "#ffff00";
    ctx.fill();
    ctx.lineWidth = lineWidth;
    ctx.strokeStyle = "#aaaa00";
    ctx.stroke();
    ctx.closePath();

    if (cell.mine)
    {
        var xCenter = cell.x + cellSize/2;
        var yCenter = cell.y + cellSize/2;
        var radius = cellSize/2 * .6;
        ctx.beginPath();
        ctx.arc(xCenter, yCenter, radius, 0, 2 * Math.PI, false);
        ctx.fillStyle = "#000000";
        ctx.fill();
        ctx.closePath();
    }
    else if (cell.minesAround)
    {
        var fontSize = cellSize * .4;
        var text = cell.minesAround.toString();
        ctx.font = fontSize.toString() + "pt Calibri";
        ctx.textAlign = "center";
        ctx.fillStyle = "#000000";
          textWidth = ctx.measureText(text).width;
        var d = (cellSize - fontSize)/2;
        var x = cell.x + cellSize/2;
        var y = cell.y + cellSize - d;
          ctx.fillText(text, x, y);
    }
}


function drawMarker(cell)
{
    var ctx = canvas.getContext("2d");
    var xCenter = cell.x + cellSize/2;
    var yCenter = cell.y + cellSize/2;
    var radius = cellSize/2 * .8;
    ctx.beginPath();
    ctx.arc(xCenter, yCenter, radius, 0, 2 * Math.PI, false);
    ctx.fillStyle = "#ff0000";
    ctx.fill();
    ctx.closePath();
}


function clickHandler(event)
{
    if (!gameOver)
    {
        var cell = getCellByMouse(event);
        if (!cell.revealed)
        {
            if (markerKeyDown) markCell(cell)
            else revealCell(cell);
        }
    }
    else restart();
}

function markCell(cell)
{
    if (cell.marked)
    {
        drawCover(cell);
        cell.marked = false;
    }
    else
    {
        drawCover(cell);
        drawMarker(cell);
        cell.marked = true;
    }
}

function getCellByMouse(e)
{
    var x = e.clientX - canvasRect.left;
    var y = e.clientY - canvasRect.top;

    x = Math.floor(x / cellSize);
    y = Math.floor(y / cellSize);

    var cell = cells[x][y];

    return cell;
}

function revealCell(cell)
{
    if (!cell.marked)
    {
        cell.revealed = true;
        drawCell(cell);
        cellsToClear --;
        if (!cellsToClear) won();
        if (!cell.minesAround) revealZeroSurroundings( cell );
        if (cell.mine) boom();
    }

}

function revealZeroSurroundings(c)
{
    var sCells =     [
                            [c.idX - 1, c.idY - 1], //top-left
                            [c.idX    , c.idY - 1], //top
                            [c.idX + 1, c.idY - 1], //top-right
                            [c.idX - 1, c.idY    ], //left
                            [c.idX + 1, c.idY    ], //right
                            [c.idX - 1, c.idY + 1], //bottom-left
                            [c.idX    , c.idY + 1], //bottom
                            [c.idX + 1, c.idY + 1]  //bottom-right
                        ];


    for (var i = 0; i < sCells.length; i++)
    {
        var x = sCells[i][0];
        var y = sCells[i][1];
        
        if (x >= 0 && x < xCount && y >= 0 && y < yCount)
        {
            if (!cells[x][y].revealed) revealCell(cells[x][y])
            
            if (!cells[x][y].minesAround && !cells[x][y].revealedSurroundings)
            {
                cells[x][y].revealedSurroundings = true;//um einen Stapelüberlauf zu verhindern
                revealZeroSurroundings( cells[x][y] )
            }
        }
    }
}

function mouseMoveHandler(event)
{
    if (!gameOver)
    {
        var cell = getCellByMouse(event);
        if (cell)
        {
            if (!cell.revealed)
            {
                if (cell != oldCell)
                {
                    if (oldCell)//am Anfang ist oldCell null
                    {
                        if (!oldCell.revealed && !oldCell.marked) drawCover(oldCell);
                    }
                    if (!cell.marked) drawCoverHighlight(cell);
                    oldCell = cell;
                }
            }
        }
    }
}

function boom()
{
    gameOver = true;
    drawBanner("BOOOOOOOM");
}

function won()
{
    gameOver = true;
    drawBanner("TOTAL CLEARANCE");
}


function drawBanner(txt)
{
    var ctx = canvas.getContext("2d");

    var bannerWidth = .9;
    var bannerHeight = .6;
    var w = canvas.width * bannerWidth;
    var h = canvas.height * bannerHeight;

    ctx.beginPath();
    ctx.rect( (canvas.width - w)/2, (canvas.height - h)/2, w, h );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "#550000";
    ctx.stroke();
    ctx.closePath();

    var fontSize = h * .2;

    var text = txt;
    ctx.font = fontSize.toString() + "pt Calibri";
    ctx.textAlign = "center";
    var textWidth = ctx.measureText(text).width;
    if (textWidth > w) //textwidth reduzieren auf bannerwidth
    {
        var ratio = w/textWidth;
        fontSize *= ratio;
        ctx.font = fontSize.toString() + "pt Calibri";
    }
    var textHeight = fontSize;
    ctx.fillStyle = "#550000";
    var d = (cellSize - fontSize)/2;
    var x = canvas.width/2;
    var y = canvas.height/2 + fontSize/2;
    ctx.fillText(text, x, y);

    fontSize *= .5;
    text = "click on canvas to restart";
    ctx.font = fontSize.toString() + "pt Calibri";
    ctx.textAlign = "center";
    ctx.fillStyle = "#550000";
    x = canvas.width/2;
    y = canvas.height/2 + fontSize/2 + textHeight;
    ctx.fillText(text, x, y);
}

function restart()
{
    canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
    createField();
}

function keyDownHandler(event) { if (event.ctrlKey) markerKeyDown = true; }
function keyUpHandler(event) { if (!event.ctrlKey && markerKeyDown) markerKeyDown = false; }
function resizeHandler(event) { elementToCenterOfWindow(canvas); canvasRect = canvas.getBoundingClientRect();}
 
Zuletzt bearbeitet:

cebito

undefined

Ich habe jede Variable innerhalb von Funktionen und Schleifen declariert
Haste nicht :p (Zeile 4-14)

...aber da ich mit einer rekursiven Funktion inkl. nicht deklarierter Variabel ziemlich aufs Maul geflogen bin, bin ich danach auf Nummer sicher gegangen
Was hattest denn da gemacht?

ctx in jeder Function wieder neu zu setzen find ich übertrieben, das gehört in createCanvas. Um die dann öffentlich zu machen, lässt das "var" vor dem Variablennamen weg oder declarierst sie schon oben und weist ihr nur noch den Wert zu.

Kannst ja noch mal bei mir reinschauen, wie ich das anno dazumal gemacht hab...

btw. würd ich die Bomben erst nach dem ersten Klick platzieren, ein "Boooooom" schon beim ersten Anlauf sollte nicht sein ;)
 

keul3

3dsMax | 3D-Contest

Haste nicht :p (Zeile 4-14)
k, ich hätte schrieben sollen, ich hab JEDE Variable auch als solche deklariert:D

Was hattest denn da gemacht?
bei der revealZeroSurroundings()-Funktion hatte ich die Schleifenvariable nicht deklariert und so wurde bei einer Rekursion nicht der Ausgangszustand i = 0 hergestellt, sondern einfach weitergezählt. Wobei ich gar nicht weiß wieso das ging, weil dann ja die Bedingung false ist ...


ctx in jeder Function wieder neu zu setzen find ich übertrieben
ist nicht in jeder Funktion, nur in denen gezeichnet wird:p
aber trotzdem ein berechtigter Einwand;)

Um die dann öffentlich zu machen, lässt das "var" vor dem Variablennamen weg oder declarierst sie schon oben und weist ihr nur noch den Wert zu.
ach so wie ich das in Zeile 4-14 gemacht hab ... :D

btw. würd ich die Bomben erst nach dem ersten Klick platzieren, ein "Boooooom" schon beim ersten Anlauf sollte nicht sein
Aber das ist doch unrealistisch, wo belibt denn da der Thrill?:D
Aber ein guter Tipp, weiß gar nicht wie das bei der MS-Version ist...

Och. Menno. Hättest da nicht was Schönes produzieren können? Dieses Spiel ist soooo doof …
warum denn?:(
 

virra

lazy lizzard

Weil es nicht mit Nachdenken zu knacken ist und ich nach ein paar Klicks regelmäßig explodiere. Ist in meinen Augen hat eher so ein Zufallsding.
 

virra

lazy lizzard

Menno! Dann verrate mir doch mal, wie man nicht nach ca. 3-5 Klicks explodiert. Also die Spielregeln hab ich auch gelesen, aber mir erschließt sich das nicht. Oft explodiere ich schon nach dem 2. oder 3. Klick, wahrscheinlich bin ich ein verkapptes Mienenräumgerät …
 

keul3

3dsMax | 3D-Contest

Habs jetzt so umgeschrieben, dass beim Start garantiert keine Mine erwischt wird, ist bei der MS-Version tatsächlich auch so. Und noch so ein wenig am Code rumgedoktort, was aber keine weiteren Auswirkungen aufs Spiel selbst hat



Code poste ich jetzt nicht, den kann sich ja jeder in Ruhe im Browser anschauen wenn er möchte;)
 

cebito

undefined

Nein, ist es nicht (wie auch im Original nicht)! Jedenfalls nicht immer.
Kommt aber eher selten vor, dann muss man halt mal den einen Zufallsklick wagen um weiterzukommen, die Chancen stehn auf jeden Fall besser als 50/50 :)

Code poste ich jetzt nicht, den kann sich ja jeder in Ruhe im Browser anschauen wenn er möchte;)
Am WE, falls ich Zeit hab :) btw. wäre ein klein wenig Dokumentation in Form von Kommentaren hilfreich, so muss man sich nicht alles selbst zusammenreimen ;)
 

keul3

3dsMax | 3D-Contest

btw. wäre ein klein wenig Dokumentation in Form von Kommentaren hilfreich, so muss man sich nicht alles selbst zusammenreimen
ich geb zu, da bin ich etwas faul:D ich schreib eigentlich nur für mich was hin, wenn ich der Meinung bin, dass ich bei einer späteren Sichtung meinerseits, Probleme haben könnte zu verstehen, warum ich dieses oder jenes so gemacht hab.
Ich denke die Funktionsnamen sind schon recht aussagekräftig. Das blöde, zumindest für mich, dass ich, dank fehlender Typisierung, nicht auf dem ersten sehen kann, ob und was mir diese Funktion rausschmeißt.
 
Bilder bitte hier hochladen und danach über das Bild-Icon (Direktlink vorher kopieren) platzieren.
Antworten auf deine Fragen:
Neues Thema erstellen

Willkommen auf PSD-Tutorials.de

In unseren Foren vernetzt du dich mit anderen Personen, um dich rund um die Themen Fotografie, Grafik, Gestaltung, Bildbearbeitung und 3D auszutauschen. Außerdem schalten wir für dich regelmäßig kostenlose Inhalte frei. Liebe Grüße senden dir die PSD-Gründer Stefan und Matthias Petri aus Waren an der Müritz. Hier erfährst du mehr über uns.

Stefan und Matthias Petri von PSD-Tutorials.de

Nächster neuer Gratisinhalt

03
Stunden
:
:
25
Minuten
:
:
19
Sekunden

Flatrate für Tutorials, Assets, Vorlagen

Zurzeit aktive Besucher

Statistik des Forums

Themen
118.611
Beiträge
1.538.342
Mitglieder
67.524
Neuestes Mitglied
BSKGA
Oben