Permalänk

Hitta svaret i tre i rad.

Hej!
Jag har en uppgift där jag ska göra en funktion som kontrollerar om någon har vunnit i tre i rad. Jag har testat allt från att göra en nästlad loop, skriva, skriva samtliga utslag separat och det senaste jag gjort är något mellanting.

här är det viktiga ur main.

int main() { char spelplan[3][3]; int drag, klart; do { rensa(spelplan); visa(spelplan); /* spela en omgång */ klart = 0; for (drag = 1; drag <= 9 && !klart; drag++) { markera(drag, spelplan); visa(spelplan); /* kontrollera vinnare om 5 markeringar eller fler */ if (drag >= 5) klart = kontrollera(spelplan); } /* skriv omgångens resultat */ gotoxy(30, 20); if (!klart) printf("Remi!"); else if (drag % 2 == 0) printf("x vinner!"); else printf("o vinner!");

Här är min funktion:

int kontrollera(char p[3][3]) { int i, j; for(i = 0; i < 3; i++) if(p[i][0] == p[i][1] && p[i][1] == p[i][2]) return 1; for(j = 0; j < 3; j++) if(p[0][j] == p[1][j] && p[1][j] == p[2][j]) return 1; if(p[0][0] == p[1][1] && p[1][1] == p[2][2]){ return 1; } else if(p[2][0] == p[1][1] && p[1][1] == p[0][2]){ return 1; } else return 0; };

Är inte intresserad av en färdig lösning, men snälla hjälp mig med vart jag tänker fel.

Det här får jag när jag kör spelet och jag ser inte vart jag har sagt att det är vinst.

[_][_][_]
[o][x][_]
[x][o][x]

x vinner!

Kan det vara så att när den efter 5 total drag kör funktionen så får den 1 returnerat?

mvh/M

Permalänk
Hedersmedlem
Skrivet av Swehurricane:

Det här får jag när jag kör spelet och jag ser inte vart jag har sagt att det är vinst.

[_][_][_]
[o][x][_]
[x][o][x]

x vinner!

Kan det vara så att när den efter 5 total drag kör funktionen så får den 1 returnerat?

I den översta raden är ju faktiskt alla lika (om än varken kryss eller ringar)...

Permalänk

Tack! (hur kunde jag inte se det)
Ska genast testa att ändra!

Permalänk
Medlem

Vad händer om du inte sätter något i mitten? fortsätter spelet då?

Permalänk

goliat80: Ja det gjorde det.

Testade en annan variant, men det funkar inte heller. Det syns säkert lång väg att jag är ny på det här
Vad är det som jag tycker verkar logiskt, men inte datorn?

int kontrollera(char p[3][3]) { int i, j; for(i = 0; i < 3; i++) for(j = 0; i < 3; j++){ while(p[i][j] != ' '){ if(p[i][j] == p[i][j+1] && p[i][j+1] == p[i][j+2]) return 1; else if(p[i][j] == p[i+1][j] && p[i+1][j] == p[i+2][j]) return 1; else if(p[i][j] == p[i+1][j] && p[i+1][j] == p[i+2][j]) return 1; else if(p[i][j] == p[i][j-1] && p[i][j] == p[i][j+1]) return 1; else if(p[i][j] == p[i-1][j] && p[i][j] == p[i+1][j]) return 1; else if(p[i][j] == p[i+1][j+1] && p[i+1][j+1] == p[i+2][j+2]) return 1; else if(p[i+2][j] == p[i+1][j+1] && p[i+1][j+1] == p[i][j+2]) return 1; else return 0; };

Permalänk

Använder jag "&&" fel? (fått för mig att det är "och")
Har i alla fall testat att använda "||" (eller?) ingen skillnad...

Permalänk
Hedersmedlem
Skrivet av Swehurricane:

for(i = 0; i < 3; i++) for(j = 0; i < 3; j++){ while(p[i][j] != ' '){ if(p[i][j] == p[i][j+1] && p[i][j+1] == p[i][j+2])

Du vill nog ha j där och sedan måste man vara lite försiktig. Vad händer till exempel när både i och j är 2? Den första if-satsen blir

if(p[2][2] == p[2][3] && p[2][3] == p[2][4])

dvs. utanför de 3x3-rutan.
Edit: Äsch, det var en while där också, men ovanstående gäller i alla fall när p[2][2] != ' '.

Permalänk

Hmm.. knåpar vidare, brb!

tack!

Permalänk
Medlem
Skrivet av Swehurricane:

goliat80: Ja det gjorde det.

Testade en annan variant, men det funkar inte heller. Det syns säkert lång väg att jag är ny på det här
Vad är det som jag tycker verkar logiskt, men inte datorn?

int kontrollera(char p[3][3]) { int i, j; for(i = 0; i < 3; i++) for(j = 0; i < 3; j++){ while(p[i][j] != ' '){ if(p[i][j] == p[i][j+1] && p[i][j+1] == p[i][j+2]) return 1; else if(p[i][j] == p[i+1][j] && p[i+1][j] == p[i+2][j]) return 1; else if(p[i][j] == p[i+1][j] && p[i+1][j] == p[i+2][j]) return 1; else if(p[i][j] == p[i][j-1] && p[i][j] == p[i][j+1]) return 1; else if(p[i][j] == p[i-1][j] && p[i][j] == p[i+1][j]) return 1; else if(p[i][j] == p[i+1][j+1] && p[i+1][j+1] == p[i+2][j+2]) return 1; else if(p[i+2][j] == p[i+1][j+1] && p[i+1][j+1] == p[i][j+2]) return 1; else return 0; };

I min värld så hade den där koden langat ett IndexOutOfRangeException
Vad händer när "i" eller "j" blir 2 och du försöker hämta i+1 eller j+1 från en array som bara har 3 positioner (0,1,2)?

Edit: Elgot hann före

Visa signatur

ηλί, ηλί, λαμά σαβαχθανί!?

Permalänk
Inaktiv
Skrivet av Swehurricane:

Använder jag "&&" fel? (fått för mig att det är "och")
Har i alla fall testat att använda "||" (eller?) ingen skillnad...

Du har rätt, det fungerar såhär:
x y && ||
0 0 0 0
1 0 0 1
0 1 0 1
1 1 1 1

Permalänk
Hedersmedlem
Skrivet av Leedow:

I min värld så hade den där koden langat ett IndexOutOfRangeException

Bara i överbeskyddande språk...

Permalänk
Medlem
Skrivet av Elgot:

Bara i överbeskyddande språk...

Det stämmer bra det. Är det överbeskyddande om funktionen ändå inte fungerar?
Vad händer i detta fall?

Visa signatur

ηλί, ηλί, λαμά σαβαχθανί!?

Permalänk

Finns det någon mening i det här fallet att använda en nästlad loop? :-S

Permalänk
Inaktiv
Skrivet av Swehurricane:

Finns det någon mening i det här fallet att använda en nästlad loop? :-S

Ingen aning, här är ett förslag med rekursion

int kontrollera(char p[3][3]){ //Initiera return kontrollera(p, 0, 0, 0); } int kontrollera(char p[3][3], int x, int y, int count){ //Basfall if (count == 3){ return 1; } //Vad letar vi efter? here = p[x][y]; int sum //Gå ner if(y < 2 && p[x][y+1] == here){ sum += kontrollera(p, x, y+1, count + 1); } else { sum += kontrollera(p, x, y+1, 0 } //Gå snett ner if(x<2 && y<2 && p[x+1][y+1] == type){ sum += kontrollera(p, x+1, y+1, count, type); } else if (x<2 && y<2 && p[x+1][y+1]){ sum += kontrollera(p, x+1, y+1, 0, ' '); } //Gå höger if(x < 2 && p[x+1][y] == here){ sum += kontrollera(p, x+1, y, count + 1); } else { sum += kontrollera(p, x+1, y, 0 } //Gå snett upp if(x<2 && y>1 && p[x+1][y-1] == type){ sum += kontrollera(p, x+1, y-1, count, type); } else if (x<2 && y<2 && p[x+1][y+1]){ sum += kontrollera(p, x+1, y-1, 0, ' '); } return sum; }

Permalänk
Hedersmedlem
Skrivet av Leedow:

Är det överbeskyddande om funktionen ändå inte fungerar?

Kanske inte, men c-filosofin är väl att man inte vill tvinga på folk kostnaden av kontroller i onödan.

Skrivet av Leedow:

Vad händer i detta fall?

Det varierar (beteendet är odefinierat). Man försöker läsa vad som råkar finnas i minnet där till exempel p[2][4] hade funnits om matrisen hade varit lite större (ungefär i alla fall), men om resultatet blir något godtyckligt värde, en krasch eller något annat är svårt att förutsäga.

Permalänk

Killbom: Jag testade att klistra in den, men fortfarande samma problematik =/
Kan det vara så att det är fel på uppgiften/resten av programmet som ja fått?

Permalänk

Jag lägger upp hela programmet för er som har tid/lust att titta på det.

#include <stdio.h> #include <conio.h> #include "MSViscon.h" #define ESC 27 /* Fyller matrisen med blanktecken, som betyder tomma rutor */ void rensa(char p[3][3]) { int rad, kol; for (rad = 0; rad <= 2; rad++) for (kol = 0; kol <= 2; kol++) p[rad][kol] = ' '; } /* Returnerar 1 om en vinnare finns, annars 0 */ int kontrollera(char p[3][3]){ } /* Ritar upp brädet på skärmen */ void visa(char p[3][3]) { int rad, kol; char ram[7][14] = { "ÚÄÄÄÂÄÄÄÂÄÄÄ¿", "³ ³ ³ ³", "ÃÄÄÄÅÄÄÄÅÄÄÄ´", "³ ³ ³ ³", "ÃÄÄÄÅÄÄÄÅÄÄÄ´", "³ ³ ³ ³", "ÀÄÄÄÁÄÄÄÁÄÄÄÙ" }; clrscr(); /* Skriv ledtext */ gotoxy(10, 5); printf("Flytta med piltangenterna och markera med RETURN!"); /* rita ram med övre vänstra hörnet på rad 10 kolumn 30 */ for (rad = 0; rad <= 6; rad++) { gotoxy(30, 10 + rad); for (kol = 0; kol <= 12; kol++) putchar(ram[rad][kol]); } /* rita markeringarna */ for (rad = 0; rad < 3; rad++) { for (kol = 0; kol < 3; kol++) { gotoxy(30 + 4*kol + 2, 10 + 2*rad + 1); if (p[rad][kol] == 'x') printf("%c", 'x'); else if (p[rad][kol] == 'o') printf("%c", 'o'); } } } void markera(int d, char p[3][3]) { static int rad = 0, kol = 0; /* Behåller värdet mellan anropen */ char ch; /* välj utseende och startposition för markör */ setcursor(1, 100); if (d == 1) gotoxy(32 + 4*1, 11 + 2*1); else gotoxy(32 + 4*kol, 11 + 2*rad); /* flytta omkring med piltangenterna */ while (1) { rad = (wherey() - 11) / 2; kol = (wherex() - 32) / 4; if (_kbhit()) { ch = _getch(); if (ch == 0 || ch == -32) { ch = _getch(); if (ch == 77 && wherex() < 40) gotoxy(wherex() + 4, wherey()); else if (ch == 75 && wherex() > 32) gotoxy(wherex() - 4, wherey()); else if (ch == 80 && wherey() < 15) gotoxy(wherex(), wherey() + 2); else if (ch == 72 && wherey() > 11) gotoxy(wherex(), wherey() - 2); } /* markera och avbryt om RETURN och ledig plats */ else if ( ch == 13 && p[rad][kol] == ' ') { if (d % 2 == 0) p[rad][kol] = 'o'; else p[rad][kol] = 'x'; setcursor(0, 100); break; } } } } int main() { char spelplan[3][3]; int drag, klart; do { rensa(spelplan); visa(spelplan); /* spela en omgång */ klart = 0; for (drag = 1; drag <= 9 && !klart; drag++) { markera(drag, spelplan); visa(spelplan); /* kontrollera vinnare om 5 markeringar eller fler */ if (drag >= 5) klart = kontrollera(spelplan); } /* skriv omgångens resultat */ gotoxy(30, 20); if (!klart) printf("Remi!"); else if (drag % 2 == 0) printf("x vinner!"); else printf("o vinner!"); /* ny omgång ? */ gotoxy(15, 23); printf("Programmet konstruerat av Gunnar Joki."); gotoxy(15, 24); printf("Tryck tangent f\224r ny omg\206ng! ESC avslutar!"); } while (_getch() != ESC); return 0; } if(p[i][0] == p[i][1] && p[i][1] == p[i][2]) if(p[i][0] != ' ') return 1; for(j = 0; j < 3; j++) if(p[0][j] == p[1][j] && p[1][j] == p[2][j]) if(p[0][j] != ' ') return 1; if(p[0][0] == p[1][1] && p[1][1] == p[2][2]){ return 1; } else if(p[2][0] == p[1][1] && p[1][1] == p[0][2]){ return 1; }

Permalänk
Medlem
Skrivet av Swehurricane:

Killbom: Jag testade att klistra in den, men fortfarande samma problematik =/

Först en sidnotis; i orginalet av kontrollera så gick du inte bara över index, du gick även under. shit happens to all of us

else if(p[i][j] == p[i+1][j] && p[i+1][j] == p[i+2][j])//här går du över med "+" på en variabel som går till sista index return 1; else if(p[i][j] == p[i][j-1] && p[i][j] == p[i][j+1]) //och här går du under med "-" på en variabel som startat på första index return 1;

Jag tog och skrev detta lite snabbt.
lösningen är lite väl "raktpåsak" för att vara fin, men borde fungera.
inte direkt compilerbar med din kod, men den ändringen borde inte ta tid

//assert: spelplanen är populerad av int's (0 för tom ruta och att en spelare inte har mer än ett nummer) //samt att spelplanen inte är större än 3*3 //retunerar kod för att fortsätta spela eller vem som vann(användarens nummer) int kontrollera(int p[3][3]){ int i=0; int j=0; int fortsattSpela=255; int tomRuta=0; //kollar om raderna är lika med varandra horisontellt for(;i<3;i++){ if(p[i][j]!=tomRuta){ if(p[i][j] == p[i][j+1] && p[i][j] == p[i][j+2]){ return p[i][j]; } j=0; } } i=0; //kollar om raderna är lika med varandra vertikalt for(;j<3;j++){ if(p[i][j]!=tomRuta){ if(p[i][j] == p[i+1][j] && p[i][j] == p[i+2][j]){ return p[i][j]; } i=0; } } //kontrollerar diagonalt vänster upp till höger ner if(p[0][0] == p[1][1] && p[0][0] == p[2][2]) return p[0][0]; //kontrollerar diagonalt vänster ner till höger upp if(p[2][0] == p[1][1] && p[0][2] == p[2][0]) return p[2][0]; //om programmet når hit har ingen vunnit ännu return fortsattSpela; }

Permalänk

Tack!

Ska se vad det blir utav det här