14 svar
197 visningar
HiMate123 352
Postad: 26 okt 2021 08:51

Fel på kod. Hjälp

Hej, 

Mitt spel fungerar till 90% bra, men när det blir oavgjort skrivs inte meddelandet ut:

"Ingen vinner den här gången tyvärr."

Någon som vet vad jag kan göra?
Motorn/hjärnan i spelet är spelSpelet-funktionen.

Tic Tac Toe med 5 funktioner:

#include <stdio.h> // printf, scanf
#include <stdbool.h> // bool
#include <ctype.h> // toupper

#define ANTRUTER 9 ///< Antal rutor på spelet
const int STRLEN = 80; ///< Textlengd

void nullstillBrett();
bool sjekkBrett(const int n);
bool sjekkVinner();
void skrivBrett();
int spillSpillet();

char gBrett[ANTRUTER]; ///< spel.

/**
 * Hovudprogram
 */

int main()
{
 char spelar1[STRLEN]; 
 char spelar2[STRLEN];
 char nyttSpel; // Kör programmet / spelet EN gång till.
 int vinner; // Alla spelarnummer som har vunnit.

 do {
 resetSpel(); 
 ritaSpel();  

 printf("\n\nNamn på spelar 1: "); gets(spelar1);
 printf("Namn på spelar 2: "); gets(spelar2); printf("\n");
 vinner = spelSpelet();

 if (vinnar == 1) printf("\Grattis %s!!\n\n", spelar1);
 else if (vinnar == 2) printf("\Grattis%s!!\n\n", spelar2);
 // 'vinner' == 0:

 else printf("\nIngen vinner den här gången tyvärr.\n\n");

 printf("\n\nEn ny omgång (N/J): ");
 scanf(" %c", &nyttSpel); nyttSpel = toupper(nyttSpel);
 getchar();

 } while (nyttSpel == 'J');
 return 0;
}
/* -------------------------------------------------------------------*/
void ritaSpel() {
 printf("\n\t Tic Tac Toe \n");
 printf("\t---1-----2-----3---\n");
 printf("\t| %c | %c | %c |\n",gBrett[0], gBrett[1], gBrett[2]);
 printf("\t---4-----5-----6---\n");
 printf("\t| %c | %c | %c |\n",gBrett[3], gBrett[4], gBrett[5]);
 printf("\t---7-----8-----9---\n");
 printf("\t| %c | %c | %c |\n",gBrett[6], gBrett[7], gBrett[8]);
 printf("\t-------------------\n");
}

/* -------------------------------------------------------------------*/

 void resetSpel(){
 for (int i = 0; i < ANTRUTER; i++)
 gBrett[i] = ' '; // 
}
// Återställer spel så att alla rutor är tomma.
/* -------------------------------------------------------------------*/
bool kontrolleraSpel(const int n){
if(gBrett[n-1]== ' '){
 return 1;
}else return 0;
while(!(n < 1 || n > 9));
}
/* Kontrollerar om en plats är ledig eller upptagen.
  n-1 för att kompensera för arrayen som börjar med noll,
  men att spelet börjar med en */
/* -------------------------------------------------------------------*/
 bool kontrolleraVinnar(){
if (gBrett [0] != ' ' && gBrett[0] == gBrett[1] && gBrett[1] == gBrett[2] )
 return 1;
else if (gBrett [3] != ' ' && gBrett[3] == gBrett[4] && gBrett[4] == gBrett[5])
 return 1;
else if (gBrett [6] != ' ' && gBrett[6] == gBrett[7] && gBrett[7] == gBrett[8])
 return 1;
else if (gBrett [2] != ' ' && gBrett[2] == gBrett[5] && gBrett[5] == gBrett[8])
 return 1;
else if (gBrett [1] != ' ' && gBrett[1] == gBrett[4] && gBrett[4] == gBrett[7])
 return 1;
else if (gBrett [0] != ' ' && gBrett[0] == gBrett[3] && gBrett[3] == gBrett[6])
 return 1;
else if (gBrett [2] != ' ' && gBrett[2] == gBrett[4] && gBrett[4] == gBrett[6])
 return 1;
else if (gBrett [0] != ' ' && gBrett[0] == gBrett[4] && gBrett[4] == gBrett[8])
 return 1;
else if (gBrett[0] != '1' && gBrett[1] != '2' && gBrett[2] != '3' &&
 gBrett[3] != '4' && gBrett[4] != '5' && gBrett[5] != '6' && gBrett[6]
 != '7' && gBrett[7] != '8' && gBrett[8] != '9');
 return 0;
 }
/*Kontrollerar alla möjliga kombinationer, dvs horisontell, horisontell och tvär.
Totalt 8 möjligheter.
Om någon av dem är lika, exklusive blank, indikeras true för alla
och en spelare vinnar*/
/* -------------------------------------------------------------------*/
 int spelSpelet(){ //namnpå funktion.
 int spelarVal = 1; //Indikerar om det är spelare 1 eller spelare 2:s val.
 int antalVal = 0; // börjar med 0.
 char val; //Tallet bruker taser inn lagres her som valg.
 char merk; //Markera med X eller O.
 
while (antalVal < 9){
 ritaSpel();
 antalVal++;

/* Indikerar att användarinmatning (antal val) kan vara maximalt 9.
Vid varje användarinmatning läggs en till tills vi når 9.
Efter varje användarinmatning läggs en tur till. */

 if(kontrolleraVinnar())return spelerVal;
/* Kontrollerar först om urvalet resulterar i en vinnare.
Om inte, återgår den till nästa spelares val*/

 if(spelerVal == 1) spelerVal = 2;
 else spelerVal = 1;
// Växlar mellan spelare 1 och spelare 2

 do {
 printf("Spelar %d, ditt Val: ", spelarVal);
 scanf("%i", &val);
 merk = (spelerVal == 1) ? 'X' : 'O';

 } while (!kontrolleraSpel(val));
 gBrett[val-1] = merk;
 } return 0;
 }

// looper tills 9 val görs, oavgjort eller en spelare vinner
Lindehaven 820 – Lärare
Postad: 26 okt 2021 09:10

Programmet kompilerar inte.

HiMate123 352
Postad: 26 okt 2021 09:20 Redigerad: 26 okt 2021 09:22

Nu ska det vara Ok :)

#include <stdio.h> // printf, scanf
#include <stdbool.h> // bool
#include <ctype.h> // toupper

#define ANTRUTER 9 ///< Antal rutor på spelet
const int STRLEN = 80; ///< Textlengd

void resetSpel();
bool kontrolleraSpel(const int n);
bool kontrolleraVinnar();
void ritaSpel();
int spelSpelet();

char gBrett[ANTRUTER]; ///< spel.

/**
 * Hovudprogram
 */

int main()
{
 char spelar1[STRLEN];
 char spelar2[STRLEN];
 char nyttSpel; // Kör programmet / spelet EN gång till.
 int vinnar; // Alla spelarnummer som har vunnit.

 do {
 resetSpel();
 ritaSpel();

 printf("\n\nNamn på spelar 1: "); gets(spelar1);
 printf("Namn på spelar 2: "); gets(spelar2); printf("\n");
 vinnar = spelSpelet();

 if (vinnar == 1) printf("\Grattis %s!!\n\n", spelar1);
 else if (vinnar == 2) printf("\Grattis%s!!\n\n", spelar2);
 // 'vinner' == 0:

 else printf("\nIngen vinner den här gången tyvärr.\n\n");

 printf("\n\nEn ny omgång (N/J): ");
 scanf(" %c", &nyttSpel); nyttSpel = toupper(nyttSpel);
 getchar();

 } while (nyttSpel == 'J');
 return 0;
}
/* -------------------------------------------------------------------*/
void ritaSpel() {
 printf("\n\t  Tic Tac Toe \n");
 printf("\t---1-----2-----3---\n");
 printf("\t| %c |  %c  | %c    |\n",gBrett[0], gBrett[1], gBrett[2]);
 printf("\t---4-----5-----6---\n");
 printf("\t| %c |  %c |  %c    |\n",gBrett[3], gBrett[4], gBrett[5]);
 printf("\t---7-----8-----9---\n");
 printf("\t| %c |  %c  |  %c   |\n",gBrett[6], gBrett[7], gBrett[8]);
 printf("\t-------------------\n");
}

/* -------------------------------------------------------------------*/

 void resetSpel(){
 for (int i = 0; i < ANTRUTER; i++)
 gBrett[i] = ' '; //
}
// Återställer spel så att alla rutor är tomma.
/* -------------------------------------------------------------------*/
bool kontrolleraSpel(const int n){
if(gBrett[n-1]== ' '){
 return 1;
}else return 0;
while(!(n < 1 || n > 9));
}
/* Kontrollerar om en plats är ledig eller upptagen.
  n-1 för att kompensera för arrayen som börjar med noll,
  men att spelet börjar med en */
/* -------------------------------------------------------------------*/
 bool kontrolleraVinnar(){
if (gBrett [0] != ' ' && gBrett[0] == gBrett[1] && gBrett[1] == gBrett[2] )
 return 1;
else if (gBrett [3] != ' ' && gBrett[3] == gBrett[4] && gBrett[4] == gBrett[5])
 return 1;
else if (gBrett [6] != ' ' && gBrett[6] == gBrett[7] && gBrett[7] == gBrett[8])
 return 1;
else if (gBrett [2] != ' ' && gBrett[2] == gBrett[5] && gBrett[5] == gBrett[8])
 return 1;
else if (gBrett [1] != ' ' && gBrett[1] == gBrett[4] && gBrett[4] == gBrett[7])
 return 1;
else if (gBrett [0] != ' ' && gBrett[0] == gBrett[3] && gBrett[3] == gBrett[6])
 return 1;
else if (gBrett [2] != ' ' && gBrett[2] == gBrett[4] && gBrett[4] == gBrett[6])
 return 1;
else if (gBrett [0] != ' ' && gBrett[0] == gBrett[4] && gBrett[4] == gBrett[8])
 return 1;
else if (gBrett[0] != '1' && gBrett[1] != '2' && gBrett[2] != '3' &&
 gBrett[3] != '4' && gBrett[4] != '5' && gBrett[5] != '6' && gBrett[6]
 != '7' && gBrett[7] != '8' && gBrett[8] != '9');
 return 0;
 }
/*Kontrollerar alla möjliga kombinationer, dvs horisontell, horisontell och tvär.
Totalt 8 möjligheter.
Om någon av dem är lika, exklusive blank, indikeras true för alla
och en spelare vinnar*/
/* -------------------------------------------------------------------*/
 int spelSpelet(){ //namnpå funktion.
 int spelarVal = 1; //Indikerar om det är spelare 1 eller spelare 2:s val.
 int antalVal = 0; // börjar med 0.
 char val; //Tallet bruker taser inn lagres her som valg.
 char merk; //Markera med X eller O.

while (antalVal < 9){
 ritaSpel();
 antalVal++;

/* Indikerar att användarinmatning (antal val) kan vara maximalt 9.
Vid varje användarinmatning läggs en till tills vi når 9.
Efter varje användarinmatning läggs en tur till. */

 if(kontrolleraVinnar())return spelarVal;
/* Kontrollerar först om urvalet resulterar i en vinnare.
Om inte, återgår den till nästa spelares val*/

 if(spelarVal == 1) spelarVal = 2;
 else spelarVal = 1;
// Växlar mellan spelare 1 och spelare 2

 do {
 printf("Spelar %d, ditt Val: ", spelarVal);
 scanf("%i", &val);
 merk = (spelarVal == 1) ? 'X' : 'O';

 } while (!kontrolleraSpel(val));
 gBrett[val-1] = merk;
 } return 0;
 }
beerger 962
Postad: 26 okt 2021 12:31 Redigerad: 26 okt 2021 12:41

Koden kompilerar inte.

Varför har du en vinner och en vinnar variabel?

spelerVal? Inte initialiserat.

Lindehaven 820 – Lärare
Postad: 26 okt 2021 12:32

Du kan behöva sätta brytpunkter och/eller göra spårutskrifter för att se vad som händer.

Det jag kan se är att denna kod troligen inte gör vad du förväntar dig att den ska göra:

else if (gBrett[0] != '1' && gBrett[1] != '2' && gBrett[2] != '3' &&
 gBrett[3] != '4' && gBrett[4] != '5' && gBrett[5] != '6' && gBrett[6]
 != '7' && gBrett[7] != '8' && gBrett[8] != '9');  /* <-- detta semikolon ska troligen inte finnas här */
 return 0;
 /* här behöver du troligen en else-sats med en return */
beerger 962
Postad: 26 okt 2021 12:51 Redigerad: 26 okt 2021 14:23

Lös detta

Tänk på att main använder bland annat resetSpel() innan resetSpel är initialiserad. Så fungerar inte kompilatorn i C. Lägg main längst ner isf.

Lindehaven 820 – Lärare
Postad: 26 okt 2021 14:09

Det ser ut som om @beerger inte kompilerat det senaste programmet som därför verkar ha för många fel och varningar. Kompilerar man det senast programmet finns inga syntaxfel men dock varningar om logiska fel. Ta för vana att skriva lite kod, kompilera, åtgärda alla fel, åtgärda alla varningar, skriv testkod, testa och repetera detta tills dess du har ett fungerande program.

Några fler tips:

Denna kodrad (72?) kommer aldrig att exekveras och bör tas bort:   while(!(n < 1 || n > 9));

Funktionen kontrolleraSpel() har returtypen bool och då bör den returnera true eller false (inte numeriska värden).

Funktionen kontrolleraVinnar() har returtypen bool och då bör den returnera true eller false (inte numeriska värden). Den kan skrivas kortare som jag tidigare visat i denna tråd.

beerger 962
Postad: 26 okt 2021 14:24
Lindehaven skrev:

Det ser ut som om @beerger inte kompilerat det senaste programmet som därför verkar ha för många fel och varningar. Kompilerar man det senast programmet finns inga syntaxfel men dock varningar om logiska fel. Ta för vana att skriva lite kod, kompilera, åtgärda alla fel, åtgärda alla varningar, skriv testkod, testa och repetera detta tills dess du har ett fungerande program.

Några fler tips:

Denna kodrad (72?) kommer aldrig att exekveras och bör tas bort:   while(!(n < 1 || n > 9));

Funktionen kontrolleraSpel() har returtypen bool och då bör den returnera true eller false (inte numeriska värden).

Funktionen kontrolleraVinnar() har returtypen bool och då bör den returnera true eller false (inte numeriska värden). Den kan skrivas kortare som jag tidigare visat i denna tråd.

Oj, måste ha råkat kopierat in ursprungskoden på något vänster. Här är de varningar man får nu iaf.

HiMate123 352
Postad: 26 okt 2021 15:21

Tack, gjorde alt ni sa och nu fungerar den :) 
Med tydligen, så var det att på sluttet så var val en "char" och inte "int". Jag ändrade til int och da fungerade det.

Men en fråga, varför fungerade inte som "char val"? det läste ju in när jag tastade et tal? 

HiMate123 352
Postad: 26 okt 2021 15:23
Lindehaven skrev:

Det ser ut som om @beerger inte kompilerat det senaste programmet som därför verkar ha för många fel och varningar. Kompilerar man det senast programmet finns inga syntaxfel men dock varningar om logiska fel. Ta för vana att skriva lite kod, kompilera, åtgärda alla fel, åtgärda alla varningar, skriv testkod, testa och repetera detta tills dess du har ett fungerande program.

Några fler tips:

Denna kodrad (72?) kommer aldrig att exekveras och bör tas bort:   while(!(n < 1 || n > 9));

Funktionen kontrolleraSpel() har returtypen bool och då bör den returnera true eller false (inte numeriska värden).

Funktionen kontrolleraVinnar() har returtypen bool och då bör den returnera true eller false (inte numeriska värden). Den kan skrivas kortare som jag tidigare visat i denna tråd.

while(!(n < 1 || n > 9)); 
om jag inte har det, så kan ju spelar skriva in tex 10. alltså ogiltiga tal. Hur annars ska jag göra så at spelar inte kan göra det? 

Lindehaven 820 – Lärare
Postad: 26 okt 2021 16:12 Redigerad: 26 okt 2021 16:18

Kanske blir tydligare med denna indentering och kommentarer:

bool kontrolleraSpel(const int n)
{
  if(gBrett[n-1]== ' ')
    return 1;  /* Borde vara return true; eftersom funktionen är bool */
  else
    return 0;  /* Borde vara return false; eftersom funktionen är bool */

  /* En av ovanstående return kommer alltid att exekveras vilket innebär att nästa kodrad aldrig kommer att exekvera */
  while(!(n < 1 || n > 9));
}

EDIT: Jag skulle ha skrivit funktionen lite kortare, så här:

bool kontrolleraSpel(const int n)
{
    return (gBrett[n-1] == ' ');
}
beerger 962
Postad: 26 okt 2021 16:14

Har du provat att ange en bokstav istället för siffra? Då händer något, prova o försök se varför det blir som det blir

HiMate123 352
Postad: 27 okt 2021 11:39 Redigerad: 27 okt 2021 11:41

ah men det gick nu. en annan problem är att spelar 2 börjar först. Men spelar 1 borde börja spelet. 
jag testade med

spelarVal = (spelarVal == 1) ? 1 : 2;

och

spelarVal = (spelarVal % 1) ? 1 : 2;

Men båda blir också fel...

Lindehaven 820 – Lärare
Postad: 27 okt 2021 16:30
int spelarVal = 0;
/* ...annan kod...*/
while (antalVal < 9)
{
  /* ...annan kod...*/
  spelarVal = (1 + spelarVal % 2);
Laguna 28421
Postad: 27 okt 2021 17:02

Att skriva %1 är ett fel jag också gör ibland. Det är i stort sett alltid fel.

Men dina försök (om man rättar det andra) sätter spelarVal till 1 om det är 1, och 2 om det är 2, dvs. ändrar aldrig.

Svara Avbryt
Close