Битвы в C

Цель: создать простую игру с линкором, чтобы проверить, что я узнал до сих пор.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void buff_clr(void)
{
    char junk;
    do{
        junk=getchar();
    }while(junk!='\n');
}
struct coord
{
    int y;
    int x;

}coords;

int randgen(int **ships_ptr,int n)
{
    int i,j,count=0;
    srand((unsigned)time(NULL));
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            ships_ptr[i][j]=rand()%2;
            if(ships_ptr[i][j]==1)
            {
                count++;
            }
        }
    }
    return count;
}
void draw_gui(char **pseudo_gui_ptr,int n)
{
    int i,j;

    pseudo_gui_ptr[0][0]=' ';
    for(i=1;i<(n+1);i++)
    {
        pseudo_gui_ptr[0][i]=i+48;
        pseudo_gui_ptr[i][0]=i+48;
    }

    for(i=1;i<(n+1);i++)
    {
        for(j=1;j<(n+1);j++)
        {
            pseudo_gui_ptr[i][j]='+';
        }
    }
}
void battle(int **ships_ptr, char **pseudo_gui_ptr,int n, struct coord x,int* count,int* miss)
{

    int i,j;

     for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                if(x.x-1 == i && x.y-1 == j)
                {
                    if(ships_ptr[i][j]==1)
                    {
                        if(pseudo_gui_ptr[i+1][j+1]=='O')
                        {
                            printf("\nYou've already uncovered this field!\n");
                            break;
                        }
                        printf("\nHit!\n");
                        pseudo_gui_ptr[i+1][j+1]='O';
                        (*count)--;
                    }
                    else
                    {
                        if(pseudo_gui_ptr[i+1][j+1]=='X')
                        {
                            printf("\nYou've already uncovered this field!\n\n");
                            break;
                        }
                        printf("\nMiss!\n");
                        pseudo_gui_ptr[i+1][j+1]='X';
                        (*miss)++;
                    }

                }
            }
        }


}
void result(char **pseudo_gui_ptr,int n)
{
    int i,j;

    for(i=0;i<(n+1);i++)
    {
        for(j=0;j<(n+1);j++)
        {
            printf("%6c",pseudo_gui_ptr[i][j]);
        }
        printf("\n\n");
    }
}
int main(){

   int **ships;
   char **pseudo_gui;
   int i,j;
   int n;
   char switch_size,switch_difficulty;
   int difficulty=0;
   int shipcount=0;
   int x_count=0;


   printf("\t\t\tSink the ships v0.1b");

   printf("\nChoose size(S,M,L):");
   scanf("%c",&switch_size);
   buff_clr();

      switch(switch_size)
   {
       case 's':
       case 'S':n=3;break;
       case 'm':
       case 'M':n=5;break;
       case 'l':
       case 'L':n=8;break;
       default:printf("\nYou've choosen poorly!");
               getch();
               exit(EXIT_FAILURE);
   }

   printf("\nChoose difficulty(E,H):");
   scanf("%c",&switch_difficulty);
   buff_clr();

   switch(switch_difficulty)
   {
       case 'e':
       case 'E':difficulty=(n*2)-2;break;
       case 'h':
       case 'H':difficulty=(n/2);break;
       default:printf("\nYou've choosen poorly!");
               getch();
               exit(EXIT_FAILURE);
   }

   ships=(int**)malloc(n*sizeof(int*));

   for(i=0;i<n;i++)
   {
       ships[i]=(int*)malloc(n*sizeof(int));
   }

   pseudo_gui=(char**)malloc((n+1)*sizeof(char*));

   for(i=0;i<(n+1);i++)
   {
       pseudo_gui[i]=(char*)malloc((n+1)*sizeof(char));
   }

   shipcount=randgen(ships,n);

   printf("\n\nNumber of ships to be sunk:%d",shipcount);
   printf("\nNumber of misses allowed: %d\n\n",difficulty);

   draw_gui(pseudo_gui,n);
   result(pseudo_gui,n);

   while(shipcount!=0 && x_count!=difficulty)
   {

   printf("\nEnter coordinates (x,y):");
   scanf("%d,%d",&coords.x,&coords.y);
   buff_clr();

   system("cls");

   battle(ships,pseudo_gui,n,coords,&shipcount,&x_count);
   result(pseudo_gui,n);

   printf("Number of ships to be sunk:%d",shipcount);
   printf("\nNumber of misses(out of %d): %d\n\n",difficulty,x_count);

   }
   if(shipcount==0)
   {
       printf("\nWinner!\n\n");
       getch();
   }
   else if(x_count==difficulty)
   {
       printf("\nYou Lose!\n\n");
       getch();
   }


  return 0;
}

Это то, что я сделал до сих пор, но я сомневаюсь, что мой код:

  1. Легко понять
  2. Прямо
  3. Возможно, я сделал что-то другим, более простым или более удобным способом?

Кроме того, что было бы самым оптимальным способом решения неправильного ввода, когда дело касается размера и сложности? Я сначала сделал значение по умолчанию в запросе на ввод запроса снова, но проблема в том, что он запрашивает только два раза (один раз для первоначального запроса и второй раз по умолчанию). Я попытался добавить функцию do-while для scanf s, но, похоже, у меня не может быть более одного условия (I попробовал добавить несколько проверок, если ввод равен! = букве).

Кроме того, не могли бы вы помочь мне рассказать некоторые идеи о том, как я могу добавить более длинные корабли, которые будут охватывать более 2-х плиток, поскольку я использую случайный генератор? Я знаю, что могу проверить 1, а затем добавить код, чтобы поставить 1 в (i + n), который сделает вертикальный корабль, охватывающий 2 плитки, и для горизонтального (i + 1, i-1), но мне понадобятся некоторые проверки ( Я думаю о добавлении нескольких if s, чтобы проверить, не находится ли я на n плитке), чтобы увидеть, край. Однако, будет ли это работать и является ли это наиболее эффективным методом? Если нет, дайте мне представление.

11 голосов | спросил MrPlow 26 Jam1000000amThu, 26 Jan 2012 02:49:33 +040012 2012, 02:49:33

1 ответ


10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void buff_clr(void)
{
    char junk;
    do{
        junk=getchar();
    }while(junk!='\n');
}

struct coord
{
    int y;
    int x;

}coords;

int randgen(int **ships_ptr,int n)

randgen говорит мне, что я делаю какое-то случайное поколение. Я бы включил что-то о карте в заголовок.

{
    int i,j,count=0;
    srand((unsigned)time(NULL));

Я бы не поставил это здесь. Вы должны вызывать это один раз для каждой программы, и вы можете создавать несколько карт для каждой программы.

    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            ships_ptr[i][j]=rand()%2;
            if(ships_ptr[i][j]==1)
            {
                count++;
            }
        }
    }
    return count;
}
void draw_gui(char **pseudo_gui_ptr,int n)
{
    int i,j;

    pseudo_gui_ptr[0][0]=' ';
    for(i=1;i<(n+1);i++)
    {
        pseudo_gui_ptr[0][i]=i+48;
        pseudo_gui_ptr[i][0]=i+48;

Используйте '0' вместо 48, чтобы сделать более понятным, что вы делаете

    }

    for(i=1;i<(n+1);i++)

Вам не нужны парады вокруг (n+1)

    {
        for(j=1;j<(n+1);j++)
        {
            pseudo_gui_ptr[i][j]='+';
        }
    }
}
void battle(int **ships_ptr, char **pseudo_gui_ptr,int n, struct coord x,int* count,int* miss)

Это будет довольно много параметров. Я бы поместил все в структуру Game или Map. Таким образом, вы просто передаете один указатель, и все остальное приходит как часть этого.

{

    int i,j;

     for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                if(x.x-1 == i && x.y-1 == j)
                {

Чем вы занимаетесь? Вы не хотите делать что-либо несколько раз, поэтому вы не должны использовать цикл. Вы точно знаете, что именно i и j будут просто вычислять эти значения.

                    if(ships_ptr[i][j]==1)
                    {
                        if(pseudo_gui_ptr[i+1][j+1]=='O')

Чтение GUI обычно не помогает. Что делать, если графический интерфейс изменяется? Вместо этого у меня была бы структура Tile для хранения карты. Внутри был бы корабль и открытые булевы. Это сделало бы вещи немного проще

                        {
                            printf("\nYou've already uncovered this field!\n");
                            break;
                        }
                        printf("\nHit!\n");
                        pseudo_gui_ptr[i+1][j+1]='O';
                        (*count)--;
                    }
                    else
                    {
                        if(pseudo_gui_ptr[i+1][j+1]=='X')
                        {
                            printf("\nYou've already uncovered this field!\n\n");
                            break;
                        }
                        printf("\nMiss!\n");
                        pseudo_gui_ptr[i+1][j+1]='X';
                        (*miss)++;
                    }

                }
            }
        }


}
void result(char **pseudo_gui_ptr,int n)
{
    int i,j;

    for(i=0;i<(n+1);i++)
    {
        for(j=0;j<(n+1);j++)
        {
            printf("%6c",pseudo_gui_ptr[i][j]);
        }
        printf("\n\n");
    }

Я бы избавился от pseudo_gui_ptr и каждый раз регенерировал вывод на основе данных Tile.

}
int main(){

   int **ships;
   char **pseudo_gui;
   int i,j;
   int n;
   char switch_size,switch_difficulty;
   int difficulty=0;
   int shipcount=0;
   int x_count=0;


   printf("\t\t\tSink the ships v0.1b");

   printf("\nChoose size(S,M,L):");
   scanf("%c",&switch_size);

switch_size? Назовите его после того, что это значит, а не структуру управления, которую вы собираетесь передать.

   buff_clr();

      switch(switch_size)
   {
       case 's':
       case 'S':n=3;break;
       case 'm':
       case 'M':n=5;break;
       case 'l':
       case 'L':n=8;break;
       default:printf("\nYou've choosen poorly!");

: р

               getch();
               exit(EXIT_FAILURE);
   }

   printf("\nChoose difficulty(E,H):");
   scanf("%c",&switch_difficulty);
   buff_clr();

   switch(switch_difficulty)
   {
       case 'e':
       case 'E':difficulty=(n*2)-2;break;
       case 'h':
       case 'H':difficulty=(n/2);break;
       default:printf("\nYou've choosen poorly!");
               getch();
               exit(EXIT_FAILURE);
   }

   ships=(int**)malloc(n*sizeof(int*));

   for(i=0;i<n;i++)
   {
       ships[i]=(int*)malloc(n*sizeof(int));
   }

   pseudo_gui=(char**)malloc((n+1)*sizeof(char*));

   for(i=0;i<(n+1);i++)
   {
       pseudo_gui[i]=(char*)malloc((n+1)*sizeof(char));
   }

   shipcount=randgen(ships,n);

   printf("\n\nNumber of ships to be sunk:%d",shipcount);
   printf("\nNumber of misses allowed: %d\n\n",difficulty);

   draw_gui(pseudo_gui,n);
   result(pseudo_gui,n);

   while(shipcount!=0 && x_count!=difficulty)
   {

   printf("\nEnter coordinates (x,y):");
   scanf("%d,%d",&coords.x,&coords.y);
   buff_clr();

Сделайте отступы последовательно!

   system("cls");

   battle(ships,pseudo_gui,n,coords,&shipcount,&x_count);
   result(pseudo_gui,n);

   printf("Number of ships to be sunk:%d",shipcount);
   printf("\nNumber of misses(out of %d): %d\n\n",difficulty,x_count);

   }
   if(shipcount==0)
   {
       printf("\nWinner!\n\n");
       getch();
   }
   else if(x_count==difficulty)
   {
       printf("\nYou Lose!\n\n");
       getch();
   }


  return 0;
}

В целом неплохо. Единственная сумасшедшая вещь - для-для-если.

  

И что будет самым оптимальным способом решения неправильного ввода, когда дело касается размера и сложности? Сначала я сделал дефолт в   переключите запрос на ввод снова, но проблема в том, что он только   запросы дважды (один раз для первоначального запроса и второй раз в   default), поэтому попытался добавить функцию do-while для scanfs, но кажется, что я   не может иметь более одного условия (я попытался добавить несколько проверок, если   вход будет = = к букве).

Какой-то цикл while - это путь. Я точно не знаю, где у вас проблемы. Возможно, вы захотите рассмотреть вопрос о том, что это вопрос о Stackoverflow.

  

Также вы могли бы помочь мне изложить некоторые идеи о том, как я могу добавить более длинные корабли, которые будут охватывать более 2-х плиток, так как я использую случайные   генератор. Я знаю, что могу проверить 1, а затем добавить код, чтобы поставить 1   в (i + n), что сделало бы вертикальный корабль, охватывающий 2 плитки, и для   горизонтальный (i + 1, i-1), но мне понадобятся некоторые проверки (я думаю о   добавив несколько, если нужно проверить, есть ли я на n плитке), чтобы увидеть, есть ли 1   «Край». Однако будет ли это работать и является ли он наиболее эффективным методом?   Если не дать мне идею.

Я бы предложил вам добавить такую ​​функцию, как:

int is_occupied(Map * map, int i, int j)
{
    if(i < 0 || j < 0 || i > map->n || j > map->n)
        return true;
    return map.tiles[i][j].ship;
}

Затем установите только места, где is_occupied () возвращает false. Он вернет true, если там уже есть корабль, или если плитка уходит с края карты.

ИЗМЕНИТЬ

Вот что я думаю, что вы могли бы сделать с плиткой:

struct tile
{
    int ship;
    int uncovered;
};

struct game
{
    struct tile **tiles;
    char **pseudo_gui;
    int shipcount;
    int x_count;
};

void map_gen(struct game *data,int n)
{
    int i,j;
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            data->tiles[i][j].ship =rand()%2;
            data->tiles[i][j].uncovered = 0;
            if(data->ships[i][j]==1)
            {
                data->shipcount++;
            }
        }
    }
}
void battle(struct game *data, struct coord x)
{

    int i,j;

    Tile * tile = &tiles[x.x-1][x.y-1];
    if(tile->uncovered)
    {
        printf("\nYou've already uncovered this field!\n");
    }
    else
    {
        if(tile->ship)
        {
            printf("\nHit!\n");
            data->pseudo_gui[x.x][x.y]='O';
            data->shipcount--;
        }
        else
        {
            printf("\nMiss!\n");
            data->pseudo_gui[x.x][x.y]='X';
            data->x_count++;
        }
    }
}

Другие комментарии к обновлению:

  1. Я бы сделал функцию create_game для настройки полей в игре, а затем выполнил ее main
ответил Winston Ewert 26 Jam1000000amThu, 26 Jan 2012 04:54:40 +040012 2012, 04:54:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132