-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sokoban.c
1443 lines (1339 loc) · 67.1 KB
/
Sokoban.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Projeto de Computação I: Sokoban em C. 11/2018
*
* Marcos Paulo Paolino e Marco Cabral Campelo
*
* Referência:
*
* 0 = Vazio
* 1 = Parede
* 2 = Caixa
* 3 = DestinoCaixa
* 4 = Jogador
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/stat.h>
#include <memory.h>
typedef enum { false, true } bool;
/*
* Esse typedef bool, foi feito para que exista um tipo bool.
* Preferimos trabalhar com false e true no lugar de 0 e 1, por questões de organização.
*/
int moves;
/*
* Variável de escopo global.
* Armazena os movimentos realizados pelo jogador.
*/
char nomeFase[13];
/*
* Variável de escopo global.
* Armazena o nome da fase customizada, opcionalmente passada como parâmetro ao iniciar o programa.
*/
struct Jogador{
/*
* Essa struct Jogador é usada para auxiliar no momento da leitura do Ranking.
* Armazena o nome do jogador e seus movimentos.
*/
int moves;
char nome[21];
};
int contaLinhas(char *nome){
/*
* Esta função conta e retorna o número de linhas em um dado arquivo de texto.
* Conta quantos '\n' existem. Cada '\n' seria uma nova linha.
* A cadeia de caracteres nome, é o nome/caminho para determinado arquivo.
*/
int ch;
int linhas = 0;
FILE *arq = fopen(nome,"r");
while(!feof(arq))
{
ch = fgetc(arq);
if(ch == '\n')
linhas++;
}
return linhas;
}
void pause(){
/*
* Esta função foi criada no intuíto de permitir a leitura de informações importantes pelo usuário.
* Ela "limpa" a entrada do programa, stdin, com o comando fflush e espera pela entrada do ENTER pelo usuário.
* Após isso, limpa o terminal (linux).
*/
printf("Digite enter para continuar");
char a = 0;
while(a != '\n')
{
getchar();
fflush(stdin);
a = (char)getchar();
}
system("clear");
}
void ordenar(struct Jogador *jogador, int nLinhas) {
/*
* A função realiza a ordenação "Bubble Sort" dos jogadores lidos no arquivo de recorde de determinada fase.
* Por meio de ponteiros aos struct Jogador *jogador, é possível ordenar o array, levando em conta quem fez menos movimentos.
* Não possui retorno, apenas ordena o vetor.
*/
struct Jogador auxiliar;
for(int i = 0; i < nLinhas-1; i++)
for(int j = 0; j < nLinhas-i-1; j++)
if(jogador[j].moves > jogador[j+1].moves)
{
auxiliar = jogador[j];
jogador[j] = jogador[j+1];
jogador[j+1] = auxiliar;
}
}
bool Mallocar2d(int *** matriz, int lin, int col) {
/*
* Como a mecânica de Sokoban desenvolvida aqui, envolvem inúmeras manipulações de matrizes e vetores, foi criada a função Mallocar2d.
* Basicamente, recebe um ponteiro para uma matriz e 2 inteiros, número de linhas e colunas, respectivamente.
* Após isso, executa a função malloc para alocar "ponteiros int" às linhas.
* Então, em cada linha, é executado malloc novamente, mas alocando os devidos inteiros em cada coluna, não ponteiros.
* Retorna false se algum erro ocorrer e verdadeiro se tudo for devidamente alocado.
*/
*matriz = malloc( sizeof(int *) * lin);
if (*matriz == NULL){
printf("ERROR: Sem memória!\n");
return false;
}
for (int i=0;i<lin;i++){
(*matriz)[i] = malloc( sizeof(int) * col);
if ((*matriz)[i] == NULL){
printf("ERROR: Sem memória!\n");
return false;
}
}
printf("Alocado!\n");
return true;
}
bool geraFases(){
/*
* Esta função gera todos os arquivos necessários para as 9 fases genéricas funcionarem sem problemas.
* Determinados os números de linhas e colunas, a matriz é preenchida. Todo mapa é uma matriz.
*/
printf("Geração de fases iniciadas:\n");
FILE *arq;
int lin, col;
//Geração do binário da fase 1
lin = 11; col = 19;
int fase1[11][19] = {{0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 3, 3, 1},
{1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 1},
{1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 4, 1, 1, 0, 0, 3, 3, 1},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}};
if((arq = fopen("./Mapas/Fase1/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase1, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 1 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase1/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
/*
*A função fopen gera os arquivos "level" e "Recordes" de cada fase.
*level se trata de um binário que é preenchido aqui.
* Seu conteúdo é basicamente 2 ints, lin e col, e a matriz[lin][col], também de inteiros.
*/
//Geração do binário da fase 2
lin = 10; col = 14;
int fase2[10][14] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},
{1, 3, 3, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1},
{1, 3, 3, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 1},
{1, 3, 3, 0, 0, 1, 2, 1, 1, 1, 1, 0, 0, 1},
{1, 3, 3, 0, 0, 0, 0, 4, 0, 1, 1, 0, 0, 1},
{1, 3, 3, 0, 0, 1, 0, 1, 0, 0, 2, 0, 1, 1},
{1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 0, 2, 0, 1},
{0, 0, 1, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 1},
{0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
if((arq = fopen("./Mapas/Fase2/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase2, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 2 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase2/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Geração do binário da fase 3
lin = 10; col = 17;
int fase3[10][17] = {{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1, 2, 0, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 2, 0, 1, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 0, 1, 1, 1},
{1, 3, 3, 3, 3, 0, 0, 1, 1, 0, 2, 0, 0, 2, 0, 0, 1},
{1, 1, 3, 3, 3, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 1},
{1, 3, 3, 3, 3, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
if((arq = fopen("./Mapas/Fase3/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase3, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 3 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase3/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Geração do binário da fase 4
lin = 14; col = 19;
int fase4[14][19] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 3, 3, 3, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 3, 3, 3, 3, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 2, 0, 2, 0, 0, 0, 3, 3, 3, 3, 1},
{1, 0, 2, 2, 2, 1, 2, 0, 0, 2, 0, 1, 0, 0, 3, 3, 3, 3, 1},
{1, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 3, 3, 3, 3, 1},
{1, 0, 2, 2, 0, 1, 2, 0, 2, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 2, 2, 1, 2, 2, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}};
if((arq = fopen("./Mapas/Fase4/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase4, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 4 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase4/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Geração do binário da fase 5
lin = 13; col = 17;
int fase5[13][17] = { {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 2, 1, 1, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1},
{1, 3, 3, 3, 3, 0, 0, 1, 1, 0, 2, 0, 0, 2, 1, 1, 1},
{1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 0, 2, 2, 0, 1, 1, 0},
{1, 3, 3, 3, 3, 0, 0, 1, 1, 2, 0, 0, 2, 0, 4, 1, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 0, 0, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 2, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0}};
if((arq = fopen("./Mapas/Fase5/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase5, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 5 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase5/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Geração do binário da fase 6
lin = 11; col = 12;
int fase6[11][12] = {{1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0},
{1, 3, 3, 0, 0, 1, 0, 1, 1, 4, 1, 1},
{1, 3, 3, 0, 0, 1, 1, 1, 0, 0, 0, 1},
{1, 3, 3, 0, 0, 0, 0, 0, 2, 2, 0, 1},
{1, 3, 3, 0, 0, 1, 0, 1, 0, 2, 0, 1},
{1, 3, 3, 1, 1, 1, 0, 1, 0, 2, 0, 1},
{1, 1, 1, 1, 0, 2, 0, 1, 2, 0, 0, 1},
{0, 0, 0, 1, 0, 0, 2, 1, 0, 2, 0, 1},
{0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 1},
{0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1},
{0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
if((arq = fopen("./Mapas/Fase6/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase6, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 6 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase6/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Geração do binário da fase 7
lin = 12; col = 13;
int fase7[12][13] = {{0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1},
{1, 1, 0, 1, 0, 4, 1, 1, 0, 2, 2, 0, 1},
{1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 2, 0, 0, 1, 1, 1, 0, 0, 0, 1},
{1, 1, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 1},
{1, 0, 2, 0, 0, 1, 1, 1, 0, 3, 3, 1, 0},
{1, 0, 2, 0, 2, 0, 2, 0, 3, 3, 3, 1, 0},
{1, 0, 0, 0, 0, 1, 1, 1, 3, 3, 3, 1, 0},
{1, 0, 2, 2, 0, 1, 0, 1, 3, 3, 3, 1, 0},
{1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0},
{1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
if((arq = fopen("./Mapas/Fase7/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase7, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 7 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase7/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Geração do binário da fase 8
lin = 16; col = 16;
int fase8[16][16] = {{0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 2, 0, 1},
{0, 0, 1, 0, 2, 1, 0, 2, 0, 1, 0, 0, 2, 0, 0, 1},
{0, 0, 1, 0, 0, 2, 0, 2, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 1, 1, 0, 2, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1},
{1, 4, 1, 2, 0, 2, 0, 2, 0, 0, 1, 1, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 2, 0, 1, 2, 1, 0, 0, 0, 1, 0, 1},
{1, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 1},
{1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 3, 3, 3, 3, 3, 3, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 3, 3, 3, 3, 3, 3, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 3, 3, 3, 3, 3, 3, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}};
if((arq = fopen("./Mapas/Fase8/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase8, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 8 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase8/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Geração do binário da fase 9
lin = 14; col = 17;
int fase9[14][17] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 3, 3, 1},
{0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 3, 3, 3, 1},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 3, 1},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 3, 3, 3, 1},
{0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 3, 3, 3, 1},
{0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 0, 1, 1, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 2, 0, 1, 1, 1, 1, 1},
{1, 1, 0, 0, 0, 1, 2, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1},
{1, 4, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 1},
{1, 1, 1, 1, 1, 1, 0, 2, 2, 0, 2, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}};
if((arq = fopen("./Mapas/Fase9/level","w"))!=NULL) {
fwrite(&lin, sizeof(int), 1, arq);
fwrite(&col, sizeof(int), 1, arq);
fwrite(fase9, sizeof(int), lin * col, arq);
fclose(arq);
printf("Fase 9 gerada! \n");
}
else {
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
if((arq = fopen("./Mapas/Fase9/Recordes","w")) == NULL)
{
printf("Não foi possível gerar os níveis genéricos! \n");
return false;
}
fclose(arq);
//Fim da geração.
/*
* Se todas as gerações forem um sucesso, a função retorna true.
* Caso tenha dado errado em algum ponto, retorna false.
*/
printf("*** Todas as fases foram geradas! ***\n");
return true;
}
bool verificaArquivos(){
/*
*Essa função avalia se a função geraFases() deve ser chamada.
*/
printf("Verificando arquivos do jogo:\n");
struct stat st = {0};
if(
(stat("./Mapas", &st) == -1)||
(stat("./Mapas/Fase1/level", &st) == -1)||
(stat("./Mapas/Fase2/level", &st) == -1)||
(stat("./Mapas/Fase3/level", &st) == -1)||
(stat("./Mapas/Fase4/level", &st) == -1)||
(stat("./Mapas/Fase5/level", &st) == -1)||
(stat("./Mapas/Fase6/level", &st) == -1)||
(stat("./Mapas/Fase7/level", &st) == -1)||
(stat("./Mapas/Fase8/level", &st) == -1)||
(stat("./Mapas/Fase9/level", &st) == -1))
/*
* Verifica a falta do arquivo level de cada fase essencial do jogo.
* Nesse caso, verifica o "stat" do arquivo(biblioteca <sys/stat.h>).
* Caso o arquivo esteja ausente, retorna -1, satisfazendo a condição do "if".
*/
{
/*
* Cria todas as pastas necessárias para a execução do jogo.
*/
mkdir("./Mapas", 0777);
mkdir("./Mapas/Fase1", 0777);
mkdir("./Mapas/Fase2", 0777);
mkdir("./Mapas/Fase3", 0777);
mkdir("./Mapas/Fase4", 0777);
mkdir("./Mapas/Fase5", 0777);
mkdir("./Mapas/Fase6", 0777);
mkdir("./Mapas/Fase7", 0777);
mkdir("./Mapas/Fase8", 0777);
mkdir("./Mapas/Fase9", 0777);
/*
* mkdir(*caminho, permissao); é um comando que cria um diretório.
* caminho é o caminho para o diretório a ser criado.
* 0777 é o tipo de permissão da pasta. Nesse caso, a permissão de escrita e leitura é global.
*/
return geraFases();
/*
* Retorna verdadeiro ou falso, indicando se foi possível gerar as fases e o jogo está "jogável".
* Caso não tenha dado nenhum erro na função "geraFases()", retorna true. Caso contrário, false.
*/
}
else return true;
/*
* Caso não tenha problema, a verificação de arquivos retorna true e o jogo executa normalmente.
*/
}
void verRanking(){
/*
* A função verRecordes, exibe um RANKING com todos os dados salvos em uma determinada fase.
* Esses dados são:
* Nome do jogador e número de movimentos.
* A ideia é exibir quais foram os melhores jogadores, quais cumpriram determinada fase com menos movimentos.
*/
int c;
int nLinhas;
char fase[13];
char caminhoFase[31];
int i = 0;
FILE *arq;
system("clear");
printf("\n"
"\033[093m██████\033[036m╗ \033[093m█████\033[036m╗ \033[093m███\033[036m╗ \033[093m██\033[036m╗\033[093m██\033[036m╗ \033[093m██\033[036m╗\033[093m██\033[036m╗\033[093m███\033[036m╗ \033[093m██\033[036m╗ \033[093m██████\033[036m╗ \n"
"\033[093m██\033[036m╔══\033[093m██\033[036m╗\033[093m██\033[036m╔══\033[093m██\033[036m╗\033[093m████\033[036m╗ \033[093m██\033[036m║\033[093m██\033[036m║ \033[093m██\033[036m╔╝\033[093m██\033[036m║\033[093m████\033[036m╗ \033[093m██\033[036m║\033[093m██\033[036m╔════╝ \n"
"\033[093m██████\033[036m╔╝\033[093m███████\033[036m║\033[093m██\033[036m╔\033[093m██\033[036m╗ \033[093m██\033[036m║\033[093m█████\033[036m╔╝ \033[093m██\033[036m║\033[093m██\033[036m╔\033[093m██\033[036m╗ \033[093m██\033[036m║\033[093m██\033[036m║ \033[093m███\033[036m╗\n"
"\033[093m██\033[036m╔══\033[093m██\033[036m╗\033[093m██\033[036m╔══\033[093m██\033[036m║\033[093m██\033[036m║╚\033[093m██\033[036m╗\033[093m██\033[036m║\033[093m██\033[036m╔═\033[093m██\033[036m╗ \033[093m██\033[036m║\033[093m██\033[036m║╚\033[093m██\033[036m╗\033[093m██\033[036m║\033[093m██\033[036m║ \033[093m██\033[036m║\n"
"\033[093m██\033[036m║ \033[093m██\033[036m║\033[093m██\033[036m║ \033[093m██\033[036m║\033[093m██\033[036m║ ╚\033[093m████\033[036m║\033[093m██\033[036m║ \033[093m██\033[036m╗\033[093m██\033[036m║\033[093m██\033[036m║ ╚\033[093m████\033[036m║╚\033[093m██████\033[036m╔╝\n"
"╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ \033[039m\n\n");
printf("Digite o número da fase correspondente para ver os recordes.\n\033[093m1 \033[039ma \033[093m9 \033[097m para as \033[093mfases originais \033[0mou \033[091m0 \033[0mpara os recordes da \033[091mfase carregada\033[0m.\n");
scanf("%d", &c);
if(c == 0) strcpy(fase,nomeFase);
/*
* Como a fase customizada é uma fase carregada na entrada do programa e fica salva na variavel global nomeFase,
* strcpy copia o conteúdo dela para a variável local fase.
*/
else sprintf(fase,"Fase%d",c);
/*
* As fases genéricas tem um nome padronizado, sendo possível acessá-las apenas variando o inteiro após "Fase".
*/
sprintf(caminhoFase,"./Mapas/%s/Recordes",fase);
/*
* Esse comando determina qual vai ser o caminho para a Fase.
*/
if((arq =fopen(caminhoFase,"r"))==NULL)
{
printf("Não foi possível abrir o arquivo\n");
pause();
return;
}
nLinhas = contaLinhas(caminhoFase);
if(nLinhas == 0)
{
/*
* Caso o arquivo de Recordes exista e não possua nenhuma linha, significa que ninguém passou de determinado nível ainda.
*/
printf("Ainda não existem dados para esta fase, seja o primeiro!\n");
pause();
return;
}
struct Jogador jogador[nLinhas];
/*
* Declarando um vetor de Jogadores, baseado diretamente no número de recordes lidos (nLinhas).
*/
while(!feof(arq))
{
fscanf(arq,"%s # %d\n",jogador[i].nome,&jogador[i].moves);
i++;
/*
* Enquanto o ponteiro não chega ao final do arquivo, ele continua lendo informações do arquivo "Recordes".
* As informações lidas são guardadas no array de structs Jogador.
*/
}
fclose(arq);
ordenar(jogador, nLinhas);
printf("\033[094m\nFase => \033[0m%s\n\033[094mMelhores jogadores\033[0m:\n\n",fase);
for(int i = 0; i < nLinhas;i++) {
if (i == 0) {
printf("\033[093m%dº \033[094m-> \033[091m%s \033[094m- \033[97m%d movimentos\n", i + 1, jogador[i].nome, jogador[i].moves);
}
else if(i == 1)
{
printf("\033[096m%dº \033[094m-> \033[091m%s \033[094m- \033[97m%d movimentos\n", i + 1, jogador[i].nome, jogador[i].moves);
}
else if(i == 2)
{
printf("\033[091m%dº \033[094m-> \033[091m%s \033[094m- \033[97m%d movimentos\n", i + 1, jogador[i].nome, jogador[i].moves);
}
else
printf("\033[97m%dº \033[094m-> \033[91m%s \033[094m- \033[97m%d movimentos\n", i + 1, jogador[i].nome, jogador[i].moves);
}
printf("\033[0m\n");
pause();
/*
* Os recordes lidos são ordenados com o chamado da função ordenar.
* Após isso, os recordes são impressoes em ordem crescente de movimentos.
* Após a impressão, o programa espera o usuário ENTER para ter tempo de ler os recordes.
*/
}
void verAjuda(){
/*
* A função verAjuda, exibe informações importantes sobre o jogo.
*/
system("clear");
printf("\033[37m██\033[036m╗\033[37m███\033[036m╗ \033[37m██\033[036m╗\033[37m███████\033[036m╗ \033[37m██████\033[036m╗ \n"
"\033[37m██\033[036m║\033[37m████\033[036m╗ \033[37m██\033[036m║\033[37m██\033[036m╔════╝\033[37m██\033[036m╔═══\033[37m██\033[036m╗\n"
"\033[37m██\033[036m║\033[37m██\033[036m╔\033[37m██\033[036m╗ \033[37m██\033[036m║\033[37m█████\033[036m╗ \033[37m██\033[036m║ \033[37m██\033[036m║\n"
"\033[37m██\033[036m║\033[37m██\033[036m║╚\033[37m██\033[036m╗\033[37m██\033[036m║\033[37m██\033[036m╔══╝ \033[37m██\033[036m║ \033[37m██\033[036m║\n"
"\033[37m██\033[036m║\033[37m██\033[036m║ ╚\033[37m████\033[036m║\033[37m██\033[036m║ ╚\033[37m██████\033[036m╔╝\n"
"╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ \n\n\033[0m "
"\033[092mO que é Sokoban?\n"
" \033[0mSokoban é um jogo de origem japonesa, criado inicialmente por Hiroyuki Imabayashi.\n"
" Seu nome significa, literalmente, Zelador do Armazém.\n"
"\033[092mComo funciona o jogo?\n"
" \033[0mO jogo consiste em empurrar caixas até suas devidas posições, mostradas no mapa do jogo (o armazém).\n"
" Só é importante tomar cuidado para não fazer movimentos em falso.\n"
"\033[092mUma curiosidade?\n"
" \033[0mSokoban é bastante utilizado no ramo de I.A. (Inteligência artifical)\n"
" Por seus quebra-cabeças serem um verdadeiro desafio para as inteligências.\n\n"
"\033[092mComo jogar: \033[92mLegenda:\n"
" \033[96mW \033[94m-> \033[0mMove o personagem para cima \033[0m@ \033[94m-> \033[0mPersonagem\n"
" \033[96mA \033[94m-> \033[0mMove o personagem para a esquerda \033[93m# \033[94m-> \033[0mCaixa\n"
" \033[96mS \033[94m-> \033[0mMove o personagem para baixo \033[91mx \033[94m-> \033[0mDestino da caixa\n"
" \033[96mD \033[94m-> \033[0mMove o personagem para a direita \n"
" \033[31mQ \033[94m-> \033[0mSai da fase\n"
" \033[33mR \033[94m-> \033[0mReinicia a fase\n\n");
pause();
}
int exibirMenu() {
/*
* Essa função exibe o menu principal do jogo.
* Dependendo do seu retorno, é possível ir para diversas fases ou funções.
*/
char fase;
printf("\n \n"
"\033[031m███████\033[036m╗ \033[031m██████\033[036m╗ \033[031m██\033[036m╗ \033[031m██\033[036m╗ \033[031m██████\033[036m╗ \033[031m██████\033[036m╗ \033[031m█████\033[036m╗ \033[031m███\033[036m╗ \033[031m██\033[036m╗\033[039m\n"
"\033[031m██\033[036m╔════╝\033[031m██\033[036m╔═══\033[031m██\033[036m╗\033[031m██\033[036m║ \033[031m██\033[036m╔╝\033[031m██\033[036m╔═══\033[031m██\033[036m╗\033[031m██\033[036m╔══\033[031m██\033[036m╗\033[031m██\033[036m╔══\033[031m██\033[036m╗\033[031m████\033[036m╗ \033[031m██\033[036m║\033[039m\n"
"\033[031m███████\033[036m╗\033[031m██\033[036m║ \033[031m██\033[036m║\033[031m█████\033[036m╔╝ \033[031m██\033[036m║ \033[031m██\033[036m║\033[031m██████\033[036m╔╝\033[031m███████\033[036m║\033[031m██\033[036m╔\033[031m██\033[036m╗ \033[031m██\033[036m║\033[039m\n"
"\033[036m╚════\033[031m██\033[036m║\033[031m██\033[036m║ \033[031m██\033[036m║\033[031m██\033[036m╔═\033[031m██\033[036m╗ \033[031m██\033[036m║ \033[031m██\033[036m║\033[031m██\033[036m╔══\033[031m██\033[036m╗\033[031m██\033[036m╔══\033[031m██\033[036m║\033[031m██\033[036m║╚\033[031m██\033[036m╗\033[031m██\033[036m║\033[039m\n"
"\033[031m███████\033[036m║╚\033[031m██████\033[036m╔╝\033[031m██\033[036m║ \033[031m██\033[036m╗╚\033[031m██████\033[036m╔╝\033[031m██████\033[036m╔╝\033[031m██\033[036m║ \033[031m██\033[036m║\033[031m██\033[036m║ ╚\033[031m████\033[036m║\033[039m\n"
"\033[036m╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝\033[039m\n \n"
"\n Selecione a fase:\n\n"
" 1 -> Fase 1 4 -> Fase 4 7 -> Fase 7 0 -> Fase Customizada\n"
" 2 -> Fase 2 5 -> Fase 5 8 -> Fase 8 C -> Criar Fase\n"
" 3 -> Fase 3 6 -> Fase 6 9 -> Fase 9 R -> Ver Ranking\n\n Q -> Sair H -> Ajuda\n\n");
scanf("%c", &fase);
if(isdigit(fase)) return (fase-'0');
/*
* O programa lê o input do usuário,verifica se determinado input foi, de fato, um dígito.
* Caso seja um dígito, retorna um inteiro que determina a fase que será jogada.
*/
else if (toupper(fase) == 'Q') return -1;
/*
* Se o usuário digitar q ou Q, retorna -1.
* Esse valor faz o jogo ser terminado.
*/
else if(toupper(fase) == 'H') return -2;
/*
* Se o usuário digitar h ou H, retorna -2.
* Esse valor faz o programa exibir informações sobre o jogo.
*/
else if(toupper(fase) == 'R') return -3;
/*
* Se o usuário digitar r ou R, retorna -3.
* Esse valor faz o jogo exibir o menu de Ranking.
*/
else if(toupper(fase) == 'C') return -4;
/*
* Se o usuário digitar c ou C, retorna -4.
* Esse valor faz o jogo exibir o menu de Criação de fases.
*/
else {
system("clear");
return exibirMenu();
/*
* Caso não digite nada esperado,
* retorna a propria função, chamando ela novamente para que receba input correto do usuário.
*/
}
}
int vitoria(char *enderecoFase) {
/*
* Essa função parabeniza o usuário por ter conseguido vencer o quebra-cabeça.
* Além disso, coleta e armazena informações no arquivo "Recordes" de determinada fase.
* Recebe como parâmetro, uma cadeia de caracteres com o endereço da fase.
*/
char nome[21];
system("clear");
printf("\033[092m██████\033[036m╗ \033[092m█████\033[036m╗ \033[092m██████\033[036m╗ \033[092m█████\033[036m╗ \033[092m██████\033[036m╗ \033[092m███████\033[036m╗\033[092m███\033[036m╗ \033[092m██\033[036m╗\033[092m███████\033[036m╗\033[092m██\033[036m╗\n"
"\033[092m██\033[036m╔══\033[092m██\033[036m╗\033[092m██\033[036m╔══\033[092m██\033[036m╗\033[092m██\033[036m╔══\033[092m██\033[036m╗\033[092m██\033[036m╔══\033[092m██\033[036m╗\033[092m██\033[036m╔══\033[092m██\033[036m╗\033[092m██\033[036m╔════╝\033[092m████\033[036m╗ \033[092m██\033[036m║\033[092m██\033[036m╔════╝\033[092m██\033[036m║\n"
"\033[092m██████\033[036m╔╝\033[092m███████\033[036m║\033[092m██████\033[036m╔╝\033[092m███████\033[036m║\033[092m██████\033[036m╔╝\033[092m█████\033[036m╗ \033[092m██\033[036m╔\033[092m██\033[036m╗ \033[092m██\033[036m║\033[092m███████\033[036m╗\033[092m██\033[036m║\n"
"\033[092m██\033[036m╔═══╝ \033[092m██\033[036m╔══\033[092m██\033[036m║\033[092m██\033[036m╔══\033[092m██\033[036m╗\033[092m██\033[036m╔══\033[092m██\033[036m║\033[092m██\033[036m╔══\033[092m██\033[036m╗\033[092m██\033[036m╔══╝ \033[092m██\033[036m║╚\033[092m██\033[036m╗\033[092m██\033[036m║╚════\033[092m██\033[036m║╚═╝\n"
"\033[092m██\033[036m║ \033[092m██\033[036m║ \033[092m██\033[036m║\033[092m██\033[036m║ \033[092m██\033[036m║\033[092m██\033[036m║ \033[092m██\033[036m║\033[092m██████\033[036m╔╝\033[092m███████\033[036m╗\033[092m██\033[036m║ ╚\033[092m████\033[036m║\033[092m███████\033[036m║\033[092m██\033[036m╗\n"
"\033[036m╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═══╝╚══════╝╚═╝"
"\033[039m\n\n Você venceu com um total de \033[092m%d \033[039mmovimentos!\n\n", moves);
printf("\nDigite seu nome para registrá-lo, utilize apenas letras do alfabeto e números:\n");
scanf("%s", nome);
FILE *arq;
if((arq = fopen(strcat(enderecoFase,"Recordes"),"a")) == NULL)
{
printf("Não foi possivel fazer o registro.\n");
pause();
return 0;
}
fprintf(arq,"%s # %d\n",nome,moves);
/*
* Imprime em uma formatação especial para permitir a leitura linha por linhas posteriormente.
*/
fclose(arq);
printf("Sua pontuação foi registrada!\n");
pause();
return 0;
/*
* Lê o nome do usuário e diz à ele se sua pontuação foi ou não registrada no arquivo.
*/
}
bool verificaVitoria(int *movel, int *original, int lin, int col) {
/*
* Como o nome indica, essa função verifica se o jogo foi ganho ou não.
* Para isso, ela deve ser chamada toda vez que um novo movimento é feito.
* Recebe 2 matrizes, o número de linhas e colunas.
* A matriz "móvel", originalmente tem todos os elemetos idênticos à original.
* A diferença é que a original se mantém constante, essa varia conforme os movimentos do jogador.
*/
int nCaixas = 0, nCaixasCorretas = 0;
for(int i = 0; i < col; i++) {
for(int j = 0; j < lin; j++) {
if (original[i * lin + j] == 3) nCaixas++;
}
}
for(int i = 0; i < col; i++) {
for (int j = 0; j < lin; j++) {
if (original[i * lin + j] == 3 && movel[i * lin + j] == 2)
nCaixasCorretas++;
else if(original[i * lin + j] == 3 && movel[i * lin + j] != 2)
return false;
}
}
if(nCaixasCorretas >= nCaixas)
return true;
/*
* O primeiro loop for, conta quantas caixas existem na matriz original.
* O segundo, comparando a matriz móvel com a original, verifica quantas caixas nas posições corretas existem.
* Nesse caso, original[i * lin + j] == 3 && movel[i * lin + j] == 2, onde 3 é a "marcação no chão" e 2 é a "caixa".
* Se o número de caixas corretas for igual ao de caixas, retorna true (Venceu a fase).
* Caso contrário, retorna false.
*/
return false;
}
void exibirPosicao(int *movel, int lin, int col){
/*
* Essa função imprime as coordenadas x e y do jogador na matriz e também imprime o número de movimentos realizados até então.
*/
int contaPlayer = 0;
for(int i = 0; i < lin; i++)
for (int j = 0; j < col; j++) {
if(movel[i * col + j] == 4)
{
if(contaPlayer == 0) {
printf("\nx: %d y: %d \n",j,lin - 1- i);
printf("Movimentos = %d \n", moves);
contaPlayer++;
}
}
}
}
void exibeConstrucao(int*matriz, int lin, int col) {
/*
* Esta função funciona juntamente com a criaFase();
* Funciona para exibir a construção do usuário.
* Lendo a matriz e retornando o devido caractér.
*/
for(int i = 0; i < lin; i++) {
for (int j = 0; j < col; j++) {
switch(matriz[i*col+j])
{
case 0:
printf(" ");
break;
case 1:
printf("\033[36m█\033[0m");
break;
case 2:
printf("\033[93m#\033[0m");
break;
case 3:
printf("\033[91mx\033[0m");
break;
case 4:
printf("\033[0m@\033[0m");
break;
case 5:
printf("\033[95mo\033[0m");
break;
default:
printf("?");
break;
}
}
printf("\n");
}
}
bool verificaMovimento(char direcao, int *movel, int lin, int col) {
switch(direcao)
{
case 'w':
for (int i = 0; i < lin; i++)
for(int j = 0; j < col; j++)
{
if(movel[i*col+j] == 4)
{
if(movel[i * col + j - col] == 0 || movel[i * col + j - col] == 3) return true;
else if(movel[i * col + j - col] == 1) return false;
else if(movel[i * col + j - col] == 2) {
if(movel[i * col + j - (2*col)] != 0 && movel[i * col + j - (2*col)] != 3) return false;
else {
movel[i * col + j - col] = 0;
movel[i * col + j - (2 * col)] = 2;
return true;
}
}
}
}
break;
case 'a':
for (int i = 0; i < lin; i++)
for(int j = 0; j < col; j++)
{
if(movel[i*col+j] == 4)
{
if(movel[i * col + j -1] == 0 || movel[i * col + j -1] == 3) return true;
else if(movel[i * col + j -1] == 1) return false;
else if(movel[i * col + j -1] == 2) {
if(movel[i * col + j - 2] != 0 && movel[i * col + j - 2] != 3) return false;
else {
movel[i * col + j - 2] = 0;
movel[i * col + j - 2] = 2;
return true;
}
}
}
}
break;
case 's':
for (int i = 0; i < lin; i++)
for(int j = 0; j < col; j++)
{
if(movel[i*col+j] == 4)
{
if(movel[i * col + j + col] == 0 || movel[i * col + j + col] == 3) return true;
else if(movel[i * col + j + col] == 1) return false;
else if(movel[i * col + j + col] == 2) {
if (movel[i * col + j + 2*col] != 0 && movel[i * col + j + 2*col] != 3) return false;
else {
movel[i * col + j + col] = 0;
movel[i * col + j + (2 * col)] = 2;
return true;
}
}
}
}
break;
case 'd':
for (int i = 0; i < lin; i++)
for(int j = 0; j < col; j++)
{
if(movel[i*col+j] == 4)
{
if(movel[i * col + j + 1] == 0 || movel[i * col + j + 1] == 3) return true;
else if(movel[i * col + j + 1] == 1) return false;
else if(movel[i * col + j + 1] == 2) {
if(movel[i * col + j + 2] != 0 && movel[i * col + j + 2] != 3) return false;
else {
movel[i * col + j + 1] = 0;
movel[i * col + j + 2] = 2;
return true;
}
}
}
}
break;
}
return false;
}
int movimentarPersonagem(int *movel, int lin, int col) {
/*
* Essa função é a base da movimentação do "@" pela matriz.
* Recebe input do usuário, teclas WASD(4 direções) e Q(sair).
*
* Em cada um dos casos uma coisa é comum:
* Foram utilizados 2 loops for para encontrar o "4"(Personagem) na matriz móvel.
* A partir dessa posição, mudanças são feitas.
*/
switch(getchar()) {
case 'w':
for(int i = 0; i < lin; i++)
for (int j = 0; j < col; j++) {
if(movel[i*col + j] == 4)
{
if(verificaMovimento('w', movel, lin, col) == true) {
movel[i * col + j - col] = 4;
movel[i * col + j] = 0;
moves++;
return true;
/*
* Chama a função verificaMovimento para determinar se o movimento pretendido é possível.
* Caso seja, atualiza a matriz. O 4 agora está "um i" acima, graças à:
* movel[i * col + j - col] = 4;
* Atualiza também o número de movimentos e a posição antiga onde 4 se encontrava passa a ser 0.
*/
}
}
}
break;
case 'a':
for(int i = 0; i < lin; i++)
for (int j = 0; j < col; j++) {
if(movel[i*col + j] == 4)
{
if(verificaMovimento('a', movel, lin, col) == true) {
movel[i * col + j - 1] = 4;
movel[i * col + j] = 0;
moves++;
return true;
/*
* Chama a função verificaMovimento para determinar se o movimento pretendido é possível.
* Caso seja, atualiza a matriz. O 4 agora está "um j" à esquerda, graças à:
* movel[i * col + j - 1] = 4;
* Atualiza também o número de movimentos e a posição antiga onde 4 se encontrava passa a ser 0.
*/
}
}
}
break;
case 's':
for(int i = 0; i < lin; i++)
for (int j = 0; j < col; j++) {
if(movel[i*col + j]== 4)
{
if(verificaMovimento('s', movel, lin, col) == true) {
movel[i * col + j + col] = 4;
movel[i * col + j] = 0;
moves++;
return true;
/*
* Chama a função verificaMovimento para determinar se o movimento pretendido é possível.
* Caso seja, atualiza a matriz. O 4 agora está "um i" abaixo, graças à:
* movel[i * col + j + col] = 4;
* Atualiza também o número de movimentos e a posição antiga onde 4 se encontrava passa a ser 0.
*/
}
}
}