Tässä on miinaharavan alku jonka löysin alunperin C kielenä. Käänsin sitä C# kieleen harjoitusmielessä. Ohjelma toimii tähän asti jos antaa oikeita lukuja, mutta yksi asia on minulle mysteeri. Kun annan "process" metodille parametrit ja tämä merkkaa taulukkoon lasketun luvun niin miten ohjelma muistaa mitkä luvut taulukkoon on lisätty aiemmin? Joka kerta kun uusi taulukko tulostetaan siellä on siis ne vanhatkin kohdat merkittynä.
Käsittääkseni kaikki metodeille annetut parametrit ovat nimenomaan kopioita ja ne ei pitäisi siirtyä seuraavaan kierrokseen joten mielestäni taulukon tulostuksessa pitäisi näkyä vain viimeisin kohta, mutta näin ei ole. Onko tässä nyt joku jippo jota en vain hoksaa? Osaisitteko auttaa ja kertoa. Auttaisi tosi paljon taulukoiden ymmärtämisessä
Tässä koodi kokonaisuudessaan.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MineSweeper { public class Program { static void Main(string[] args) { // alueen koko char[,] msweep = new char[12,12]; // alueen koko joka näytetään käyttäjälle char[,] user_chart = new char[12, 12]; // muuttujia int i,r,c; // kutsutaan metodia randomize_mines joka luo satunnaiset miinat ja annetaan parametriksi msweep taulukko randomize_mines(msweep); // kysytään koordinaatit joita kaivetaan Console.Write("Anna X-koordinaatti väliltä 1-10: "); r = int.Parse(Console.ReadLine()); Console.Write("Anna Y-koordinaatti väliltä 1-11: "); c = int.Parse(Console.ReadLine()); // tulostetaan miinakenttä annetuilla parametreillä printmatrix(user_chart); // prosessoidaan käyttäjän tekemä valinta i = process(msweep, r, c, user_chart); // mennään looppiin jossa prosessoidaan valintoja looppina while (i == 1) { Console.Write("Miinoja lähettyvillä {0}\n\n", msweep[r,c]); // Tulostetaan tämänhetkinen taulukko! printmatrix(user_chart); Console.Write("Anna X-koordinaatti väliltä 1-10: "); r = int.Parse(Console.ReadLine()); Console.Write("Anna Y-koordinaatti väliltä 1-10: "); c = int.Parse(Console.ReadLine()); i = 0; i = process(msweep, r, c, user_chart); } // jos astuttiin miinaan peli on ohi. if (i == 0) { Console.Write("Astuit miinaan\n"); printmatrix(user_chart); Console.ReadLine(); } } // Luodaan miinat, parametrina taulukko joka luotiin mainissa static void randomize_mines(char [,] msweep) { int r, c, m; // satunnainen muuttuja Random rnd = new Random(); for (m = 0; m < 20; m++) // oletuksena 20 miinaa. { // miinat taulukoihin, reunojen ulkopuolelle. r = rnd.Next(1, 11); c = rnd.Next(1, 11); // 9 tarkoittaa, että siinä on miina johon verrataan myöhemmin msweep[r,c] = '9'; //listataan paikat joissa on miina kokeilua varten (onko esim. reunoilla) Console.WriteLine("{0} {1} ", r, c); } } // tulostetaan matriksi static void printmatrix(char [,] user_chart) { int i,j; Console.WriteLine(".-.-.-.-.-.-.-."); for(i=1;i<11;i++) { Console.Write("./."); for(j=1;j<11;j++) // luvut 1-11 on miinoja varten { Console.Write(user_chart[i,j]); // näytetään nykyiset paikat joista miinoja on jo haravoitu } Console.Write(".\\."); Console.Write("\n"); } Console.Write(".-.-.-.-.-.-.-.\n\n"); } // tämä suoritetaan aina kun käyttäjä antaa kordinaatin. static int process(char[,] msweep, int r, int c, char[,] user_chart) { int i=r,j=c,b=0; char C; if(msweep[r,c] == '9') { user_chart[r, c] = '*'; return 0; // jos osutaan miinaan niin palautetaan 0 } // lasketaan ympäröivät alueet ja jos siinä on miina niin lisätään miinalukuun aina 1. else { if(msweep[i-1,j-1] == '9') b++; if(msweep[i-1,j] == '9') b++; if(msweep[i-1,j+1] == '9') b++; if(msweep[i,j-1] == '9') b++; if(msweep[i,j+1] == '9') b++; if(msweep[i+1,j-1] == '9') b++; if(msweep[i+1,j] == '9') b++; if(msweep[i+1,j+1] == '9') b++; // miinojen yhteystulos muuttujaan C C = (char)(((int)'0')+b); // to covert int to char; // muokataan käyttäjälle näkyvään taulukkoon sama tulos user_chart[r,c] = C; } // palautetaan 1 joka kertoo, että ohjelma voi jatkua return 1; } } }
Miksi et debuggaa itse? En näe koodissa riviäkään debug-koodia. Ongelmista oppisi parhaiten, jos edes vaivautuisi kokeilemaan niiden ratkaisua itse.
kamppis kirjoitti:
Käsittääkseni kaikki metodeille annetut parametrit ovat nimenomaan kopioita
Käytännössä objekteista (luokat, taulukot yms) välitetään viittauksen kopio. Viittauksen kopio viittaa kuitenkin alkuperäiseen objektiin.
void Demo(int luku, List<int> lista) { //Muutos ei näy kutsujalle luku = 38; //Muutos näkyy kutsujalle lista.Add(38); //Muutos ei näy kutsujalle lista = new List<int>(); //Tämäkään ei näy kutsujalle koska lista ei viittaa enää alkuperäiseen lista.Add(38); }
The Alchemist kirjoitti:
Miksi et debuggaa itse? En näe koodissa riviäkään debug-koodia. Ongelmista oppisi parhaiten, jos edes vaivautuisi kokeilemaan niiden ratkaisua itse.
Tarvitseeko debuggaamista varten laittaa jotain koodia jonnekin? :o
C# tosiaan välittää taulukoista viittaukset eikä kopioi niitä, kuten C/C++ tekisi ilman referenssimerkintää. Täten kaikki muutokset mitä kutsuttu funktio tekee tietysti palaavat takaisin. Sinun pitää itse tehdä kopio taulukosta, jos et halua muutosten säilyvän. Tähän käy esimerkiksi Clone()-metodi.
Jos taas taulukossa olisi olioita, pitää huomata, että Clone() kopioi vain osoittimet, ei luo uusia olioita, eli kaikki muutokset näihin olioihin näkyvät sekä alkuperäisessä että kopioidussa taulukossa.
Lisäys:
The Alchemist kirjoitti:
Miksi et debuggaa itse? En näe koodissa riviäkään debug-koodia. Ongelmista oppisi parhaiten, jos edes vaivautuisi kokeilemaan niiden ratkaisua itse.
a) kaikki debuggaus ei vaadi mitään lisäkoodia
b) jos minulla olisi ongelma, en sotkisi koodia debuggitulosteilla tai muilla, vaan säästäisin muiden vaivaa ja laittaisin mahdollisimman kompaktin esimerkin ongelmasta
c) tässä tilanteessa oli selvästi kyse niin perustavan tason erosta totuttuun, että ei debuggaus olisi selittänyt miksi näin tapahtuu, ainoastaan näkee, että näin tapahtuu.
Aihe on jo aika vanha, joten et voi enää vastata siihen.