├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── libraries
│ └── com_hynnet_jxl_2_6_12_1.xml
├── misc.xml
├── modules.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── Read me.txt
├── Thumbs.db
├── WRCI Results.xls
├── WRCI_Assignment_3.5_Group_9.docx
├── WRCI_ass5.iml
├── apple.png
├── apple.psd
├── body.png
├── body.psd
├── head.png
├── head.psd
├── lib
├── jxl-2.6.12.1.jar
└── log4j-1.2.14.jar
├── out
└── production
│ └── WRCI_ass5
│ ├── Chromosone.class
│ ├── Console$1.class
│ ├── Console.class
│ ├── GeneticTraining$1.class
│ ├── GeneticTraining.class
│ ├── Main.class
│ ├── SnakeGame$1.class
│ ├── SnakeGame$TAdapter.class
│ ├── SnakeGame.class
│ ├── XYPair.class
│ ├── neuralNetWork.class
│ └── storedNetClass.class
└── src
├── Chromosone.java
├── Console.java
├── GeneticTraining.java
├── Main.java
├── SnakeGame.java
├── XYPair.java
├── neuralNetWork.java
└── storedNetClass.java
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/libraries/com_hynnet_jxl_2_6_12_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
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 |
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 | 1474364074112
472 |
473 |
474 | 1474364074112
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 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
1018 | No facets are configured
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 |
1027 |
1028 |
1029 |
1030 |
1031 |
1032 |
1033 |
1034 |
1035 |
1036 |
1037 |
1038 |
1039 |
1040 |
1041 | 1.8
1042 |
1043 |
1044 |
1045 |
1046 |
1047 |
1048 |
1049 |
1050 |
1051 |
1052 |
1053 | WRCI_ass5
1054 |
1055 |
1056 |
1057 |
1058 |
1059 |
1060 |
1061 |
1062 |
1063 |
1064 |
1065 | 1.8
1066 |
1067 |
1068 |
1069 |
1070 |
1071 |
1072 |
1073 |
1074 |
1075 |
1076 |
1077 |
1078 |
1079 |
1080 |
1081 |
1082 |
1083 |
1084 |
1085 |
1086 |
1087 |
1088 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SnakeGame
2 | A classic game of snake that is controlled by a neural network (NN) and trained using a genetic algorithm (GA)
3 |
4 | Written in Java, the objective of the game is to maximize the snake's length without running into it's own body or the boundry wall.
5 | The game is run using a neural network made up 15 input neurons, 7 hidden layer neurons and 4 output neurons.
6 |
7 | --------------------------------------------
8 | Input neurons consist of (note, all values are taken as x and y PIXEL coordinates):
9 |
10 | 0: position of head x
11 |
12 | 1: position of head y
13 |
14 | 2: position of midpoint of body x
15 |
16 | 3: position of midpoint of body y
17 |
18 | 4: position of tail x
19 |
20 | 5: position of tail y
21 |
22 | 6: position of food x
23 |
24 | 7: position of food y
25 |
26 | 8: distance to food x
27 |
28 | 9: distance to food y
29 |
30 | 10: is the block on the left of the head free? (1 or 0)
31 |
32 | 11: is the block on the right of the head free? (1 or 0)
33 |
34 | 12: is the block on the up of the head free? (1 or 0)
35 |
36 | 13: is the block on the down of the head free? (1 or 0)
37 |
38 | 14: bias (-1)
39 |
40 | (note the bias is -1, as the formula in the activation function is given as a negative
41 |
42 | Output neruons are:
43 |
44 | 0: move left
45 |
46 | 1: move right
47 |
48 | 2: move down
49 |
50 | 3: move up
51 |
52 | --------------------------------------------
53 |
54 | Training of the neural network happens through a genetic algorithm through the updating of weights that are optimized around a fitness function.
55 | Random weights are initially generated for the population size of the genetic alorithm (GA) and then a game of snake is played by the NN for every chromozone in the population
56 | At the end of each playing cycle, the GA performs cross overs and mutations around a fitness function in order to try and better each chromozone's score.
57 | The fitness function is:
58 | if (stalled)
59 | out = (stepsTaken/4) + (snakeLength * 100000.0);
60 | else
61 | out = (stepsTaken/2) + (snakeLength * 100000.0);
62 |
63 | It should be noted, that the stalled value is 1, when a game ends because the snake has not found food with a set number of moves.
64 |
--------------------------------------------------------------------------------
/Read me.txt:
--------------------------------------------------------------------------------
1 | wrci project created by:
2 | Adriaan,
3 | Ashley,
4 | Dillon,
5 | Gareth, and
6 | Ridwaan
--------------------------------------------------------------------------------
/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/Thumbs.db
--------------------------------------------------------------------------------
/WRCI Results.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/WRCI Results.xls
--------------------------------------------------------------------------------
/WRCI_Assignment_3.5_Group_9.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/WRCI_Assignment_3.5_Group_9.docx
--------------------------------------------------------------------------------
/WRCI_ass5.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/apple.png
--------------------------------------------------------------------------------
/apple.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/apple.psd
--------------------------------------------------------------------------------
/body.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/body.png
--------------------------------------------------------------------------------
/body.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/body.psd
--------------------------------------------------------------------------------
/head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/head.png
--------------------------------------------------------------------------------
/head.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/head.psd
--------------------------------------------------------------------------------
/lib/jxl-2.6.12.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/lib/jxl-2.6.12.1.jar
--------------------------------------------------------------------------------
/lib/log4j-1.2.14.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/lib/log4j-1.2.14.jar
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/Chromosone.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/Chromosone.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/Console$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/Console$1.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/Console.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/Console.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/GeneticTraining$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/GeneticTraining$1.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/GeneticTraining.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/GeneticTraining.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/Main.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/Main.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/SnakeGame$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/SnakeGame$1.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/SnakeGame$TAdapter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/SnakeGame$TAdapter.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/SnakeGame.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/SnakeGame.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/XYPair.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/XYPair.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/neuralNetWork.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/neuralNetWork.class
--------------------------------------------------------------------------------
/out/production/WRCI_ass5/storedNetClass.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mraythree/SnakeGame/86c25e06083f06c901687e8e30bab76227bc29da/out/production/WRCI_ass5/storedNetClass.class
--------------------------------------------------------------------------------
/src/Chromosone.java:
--------------------------------------------------------------------------------
1 | import java.util.Random;
2 |
3 | /**
4 | * Created by Adriaan on 2016/11/12.
5 | */
6 | public class Chromosone
7 | {
8 | double[][] vWeights, wWeights;
9 | double fitness;
10 | double minSearchSpace, maxSearchSpace;
11 | long timeTaken;
12 | double snakeLength;
13 | int stepsTaken;
14 | boolean stalled;
15 |
16 | public Chromosone()
17 | {
18 | this.minSearchSpace = SnakeGame.minSearchSpace;
19 | this.maxSearchSpace = SnakeGame.maxSearchSpace;
20 | stalled = false;
21 | //initializeWeights();
22 | }
23 |
24 | public Chromosone(boolean firstRun)
25 | {
26 | this.minSearchSpace = SnakeGame.minSearchSpace;
27 | this.maxSearchSpace = SnakeGame.maxSearchSpace;
28 | if (firstRun)
29 | initializeWeights();
30 | stalled = false;
31 | }
32 |
33 | public void initializeWeights()
34 | {
35 | //give initial weights
36 | vWeights = new double[SnakeGame.noHiddenNeurons][SnakeGame.noInputsNeurons]; //2D array for weights going from every input node, to every hidden node.
37 | wWeights = new double[SnakeGame.noOutputNeurons][SnakeGame.noHiddenNeurons]; //2D array for weights going from every hidden node to every output node
38 | for (int i = 0; i<= SnakeGame.noInputsNeurons -1; i++) //set the last one to be the bias
39 | for (int j = 0; j <= SnakeGame.noHiddenNeurons-1; j++)
40 | vWeights[j][i] = randomDouble();
41 |
42 | for (int j = 0; j <= SnakeGame.noHiddenNeurons-1; j++)
43 | {
44 | for (int k = 0; k<= SnakeGame.noOutputNeurons -1; k++)
45 | wWeights[k][j] = randomDouble();
46 | }
47 | }
48 |
49 | //so we are using the time taken and the snake's length as the FF.
50 | //this means that we are encouraging the snake to stay alive, but are rewarding it more for finding the food.
51 | public void setFitness(long timeTaken, double snakeLength)
52 | {
53 | //this.timeTaken = timeTaken;
54 | this.snakeLength = snakeLength;
55 | this.stepsTaken = SnakeGame.stepsTaken;
56 | double out;
57 | if (stalled)
58 | out = (stepsTaken/4) + (snakeLength * 100000.0);
59 | else
60 | out = (stepsTaken/2) + (snakeLength * 100000.0);
61 |
62 | //double out = timeTaken + (snakeLength * 10000000);
63 | //double out = snakeLength * 1.0;
64 | stalled = false;
65 | fitness = out;
66 | }
67 |
68 | public Chromosone clone()
69 | {
70 | Chromosone out = new Chromosone();
71 | double[][] newVWeights = new double[SnakeGame.noHiddenNeurons][SnakeGame.noInputsNeurons];
72 | double[][] newWWeights = new double[SnakeGame.noOutputNeurons][SnakeGame.noHiddenNeurons];
73 |
74 | for (int i = 0; i < SnakeGame.noHiddenNeurons; i++)
75 | newVWeights[i] = getvWeights()[i].clone();
76 | out.setvWeights(newVWeights);
77 |
78 | for (int i = 0; i < SnakeGame.noOutputNeurons; i++)
79 | newWWeights[i] = getwWeights()[i].clone();
80 | out.setwWeights(newWWeights);
81 | out.setFitness(timeTaken, fitness);
82 | return out;
83 | }
84 |
85 | public double getFitness()
86 | {
87 | return fitness;
88 | }
89 |
90 | public double randomDouble()
91 | {
92 | Random r = new Random();
93 | double min = -1 / Math.sqrt(SnakeGame.noInputsNeurons);
94 | double max = 1/ Math.sqrt(SnakeGame.noInputsNeurons);
95 | double randomVal = (r.nextDouble() * (max - min)) + min;
96 | return randomVal;
97 | }
98 |
99 | public double randomDoubleInSearchSpace()
100 | {
101 | Random r = new Random();
102 | double min = minSearchSpace;
103 | double max = maxSearchSpace;
104 | double randomVal = r.nextDouble()*(max - min) + min;
105 | return randomVal;
106 | }
107 |
108 | public long getTimeTaken() {
109 | return timeTaken;
110 | }
111 |
112 | public void setTimeTaken(long timeTaken) {
113 | this.timeTaken = timeTaken;
114 | }
115 |
116 | public double[][] getvWeights() {
117 | return vWeights;
118 | }
119 |
120 | public void setvWeights(double[][] vWeights) {
121 | this.vWeights = vWeights;
122 | }
123 |
124 | public double[][] getwWeights() {
125 | return wWeights;
126 | }
127 |
128 | public void setwWeights(double[][] wWeights) {
129 | this.wWeights = wWeights;
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/Console.java:
--------------------------------------------------------------------------------
1 | import jxl.write.WriteException;
2 |
3 | import javax.swing.*;
4 | import java.awt.*;
5 | import java.awt.event.ActionEvent;
6 | import java.awt.event.ActionListener;
7 | import java.io.IOException;
8 |
9 | /**
10 | * Created by Adriaan on 2016/11/11.
11 | */
12 | public class Console extends JFrame
13 | {
14 | DefaultListModel model;
15 | JList list;
16 | JButton btnStop;
17 | JScrollPane listScroller;
18 | public Console()
19 | {
20 | JPanel pnl = new JPanel(new BorderLayout());
21 | list = new JList();
22 | list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
23 | list.setVisibleRowCount(-1);
24 | model = new DefaultListModel();
25 | model.addElement("Snake Trainer");
26 | list = new JList(model);
27 | listScroller = new JScrollPane(list);
28 | listScroller.setPreferredSize(new Dimension(250, 80));
29 | btnStop = new JButton("Stop");
30 | pnl.add("North", btnStop);
31 | pnl.add("Center", listScroller);
32 | this.add(pnl);
33 | setResizable(true); //we don't want to let the user resize the window
34 | pack(); //take the dimensions of the frame we are loading
35 | setTitle("console"); //we should be the generation number in the title.
36 | this.setBounds(200, 200, 500, 700);
37 | this.setVisible(true);
38 |
39 | btnStop.addActionListener(new ActionListener() {
40 | @Override
41 | public void actionPerformed(ActionEvent e)
42 | {
43 | SnakeGame.btnStoppedPushed = true;
44 | addToConsole("Game Stopping...");
45 | }
46 | });
47 | }
48 |
49 | public void addToConsole(String message)
50 | {
51 | model.addElement(message);
52 | list = new JList(model);
53 | //listScroller.scrollRectToVisible(new Rectangle(250, 80));
54 | JScrollBar vertical = listScroller.getVerticalScrollBar();
55 | vertical.setValue(vertical.getMaximum());
56 | }
57 |
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/GeneticTraining.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Collections;
3 | import java.util.Comparator;
4 | import java.util.Random;
5 |
6 | /**
7 | * Created by Adriaan on 2016/11/11.
8 | */
9 | public class GeneticTraining
10 | {
11 | public int populationSize, hallOfFameSize, tournamentSize;
12 | ArrayList chromosones;
13 | public int curChromosone;
14 | public double mutationRate;
15 |
16 | //this gets called once. this is tricky.
17 | //in order to evaluate the fitness function, we need to play a game of snake.
18 | //this means, that for every chromosone in the population we have to play a game of snake before we do anything with the population.
19 | public GeneticTraining(int populationSize)
20 | {
21 | this.populationSize = populationSize;
22 | chromosones = new ArrayList<>();
23 | Chromosone c;
24 | for (int i = 0; i <= populationSize -1; i++)
25 | {
26 | c = new Chromosone(true);
27 | chromosones.add(c);
28 | }
29 | curChromosone = 0;
30 | hallOfFameSize = 2;
31 | tournamentSize = 3;
32 | mutationRate = 10;
33 | }
34 |
35 | //once a population of chomozones have been evaluated, do the GA.
36 | public void Train()
37 | {
38 | //comparator is what we use to sort the list. we want to sort them in order of highest to lowest fitness.
39 | Comparator comp = new Comparator()
40 | {
41 | @Override
42 | public int compare(Chromosone o1, Chromosone o2)
43 | {
44 | if (o1.getFitness() < o2.getFitness())
45 | return 1;
46 | if (o1.getFitness() > o2.getFitness())
47 | return -1;
48 | return 0;
49 | }
50 | };
51 |
52 | Collections.sort(chromosones, comp);
53 | ArrayList nextGen = new ArrayList<>(); //this will eventually be the new population of chromozones.
54 | for (int i = 0; i< hallOfFameSize; i++) //let the first fittest individuals take the first slots to the halloffamesize counter.
55 | {
56 | nextGen.add(chromosones.get(i).clone());
57 | }
58 |
59 | //cross and mutate a child from the best 2 (this assumes that the halloffamesize is 2.
60 | Chromosone c1 = nextGen.get(0);
61 | Chromosone c2 = nextGen.get(1);
62 | Chromosone cross = crossover(c1, c2);
63 | cross = mutate(cross);
64 | //cross = mutatePositive(cross);
65 | nextGen.add(cross);
66 |
67 | //do tournament selection for the rest of the population.
68 | for (int i = 0; i< populationSize-(hallOfFameSize+1); i++)
69 | {
70 | c1 = doTournamentSelection(chromosones, comp);
71 | c2 = doTournamentSelection(chromosones, comp);
72 | cross = crossover(c1, c2);
73 | cross = mutate(cross);
74 | //cross = mutatePositive(cross);
75 | nextGen.add(cross);
76 | }
77 | chromosones = nextGen;
78 | }
79 |
80 | private Chromosone doTournamentSelection(ArrayList chromosones, Comparator comp)
81 | {
82 | Chromosone out = null;
83 | double lowestFitness = -9999999;
84 | ArrayList tournamentChromosones = new ArrayList<>();
85 | for (int i = 0; i < tournamentSize; i++)
86 | {
87 | int randI = randomInt1andPopSize();
88 | Chromosone temp = chromosones.get(randI);
89 | tournamentChromosones.add(temp);
90 | }
91 |
92 | Collections.sort(tournamentChromosones, comp);
93 | out = tournamentChromosones.get(0);
94 | return out;
95 | }
96 |
97 | private Chromosone mutate(Chromosone c)
98 | {
99 | double diff;
100 | Random R = new Random();
101 | //v
102 | for (int i = 0; i < SnakeGame.noHiddenNeurons; i++)
103 | {
104 | for (int j = 0; j < SnakeGame.noInputsNeurons; j++)
105 | {
106 | if (randomInt1andPopSize() > populationSize - mutationRate)
107 | {
108 | if (randomInt1andPopSize() > populationSize/2) //50% chance
109 | {
110 | if (j > 7)
111 | diff = randomGauss();
112 | else
113 | //diff = R.nextDouble() * minSearchSpace;
114 | diff = c.getvWeights()[i][j] + R.nextDouble() * SnakeGame.minSearchSpace/50;
115 | }
116 | else
117 | {
118 | if (j > 7)
119 | diff = randomGauss();
120 | else
121 | //diff = R.nextDouble() * maxSearchSpace;
122 | diff = c.getvWeights()[i][j] + R.nextDouble() * SnakeGame.maxSearchSpace/50;
123 | }
124 | c.vWeights[i][j] = diff;
125 | }
126 | }
127 | }
128 |
129 | //w
130 | for (int i = 0; i < SnakeGame.noOutputNeurons; i++)
131 | {
132 | for (int j = 0; j < SnakeGame.noHiddenNeurons; j++)
133 | {
134 | if (randomInt1andPopSize() > populationSize - mutationRate)
135 | {
136 | if (randomInt1andPopSize() > populationSize/2)
137 | {
138 | if (i > 2)
139 | diff = randomGauss();
140 | else
141 | //diff = R.nextDouble() * minSearchSpace;
142 | diff = c.getwWeights()[i][j] + R.nextDouble() * SnakeGame.minSearchSpace/50;
143 | }
144 | else
145 | {
146 | if (i > 2)
147 | diff = randomGauss();
148 | else
149 | //diff = R.nextDouble() * maxSearchSpace;
150 | diff = c.getwWeights()[i][j] + R.nextDouble() * SnakeGame.maxSearchSpace/50;
151 | }
152 | c.wWeights[i][j] = diff;
153 | }
154 | }
155 | }
156 |
157 | return c;
158 | }
159 |
160 | //get a value around 1 to move in.
161 | public double randomGauss()
162 | {
163 | Random r = new Random();
164 | double desiredStandardDeviation = 0.05;
165 | double desiredMean = 1;
166 | return r.nextGaussian()*desiredStandardDeviation+desiredMean;
167 | }
168 |
169 | public Chromosone crossover(Chromosone c1, Chromosone c2)
170 | {
171 | Chromosone out = new Chromosone();
172 | double[][] newVWeights = new double[SnakeGame.noHiddenNeurons][SnakeGame.noInputsNeurons];
173 | double[][] newWWeights = new double[SnakeGame.noOutputNeurons][SnakeGame.noHiddenNeurons];
174 | //v
175 | for (int i = 0; i < SnakeGame.noHiddenNeurons; i++)
176 | {
177 | for (int j = 0; j < SnakeGame.noInputsNeurons; j++)
178 | {
179 | int r = randomInt1andPopSize();
180 | if (r % 2 == 0)
181 | newVWeights[i][j] = c1.getvWeights()[i][j];
182 | else
183 | newVWeights[i][j] = c2.getvWeights()[i][j];
184 | }
185 | }
186 | //w
187 | for (int i = 0; i < SnakeGame.noOutputNeurons; i++)
188 | {
189 | for (int j = 0; j < SnakeGame.noHiddenNeurons; j++)
190 | {
191 | int r = randomInt1andPopSize();
192 | if (r % 2 == 0)
193 | newWWeights[i][j] = c1.getwWeights()[i][j];
194 | else
195 | newWWeights[i][j] = c2.getwWeights()[i][j];
196 | }
197 | }
198 | out.setvWeights(newVWeights);
199 | out.setwWeights(newWWeights);
200 | return out;
201 | }
202 |
203 | public int randomInt1andPopSize()
204 | {
205 | Random r = new Random();
206 | int min = 0;
207 | int max = populationSize;
208 | int randomVal = r.nextInt((max - min)) + min;
209 | return randomVal;
210 | }
211 |
212 | public Chromosone getCurChromosone()
213 | {
214 | return chromosones.get(curChromosone);
215 | }
216 |
217 | public void incCurChromosone()
218 | {
219 | if (curChromosone < populationSize-1)
220 | curChromosone++;
221 | else
222 | curChromosone = 0;
223 | }
224 |
225 |
226 |
227 |
228 | }
229 |
--------------------------------------------------------------------------------
/src/Main.java:
--------------------------------------------------------------------------------
1 | import javax.swing.*;
2 |
3 | /**
4 | * Created by Adriaan on 2016/09/20.
5 | */
6 | public class Main extends JFrame
7 | {
8 | public static SnakeGame snakeGame;
9 | public Main()
10 | {
11 | snakeGame = SnakeGame.getClassInstance();
12 | add(snakeGame);
13 | setResizable(false); //we don't want to let the user resize the window
14 | pack(); //take the dimensions of the frame we are loading
15 | setTitle("Snake Being Trained"); //we should be the generation number in the title.
16 | setLocationRelativeTo(null);
17 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
18 | }
19 |
20 | public static void main(String[] args)
21 | {
22 | JFrame ex = new Main();
23 | ex.setVisible(true);
24 | try
25 | {
26 | snakeGame.runGame();
27 | }
28 | catch (InterruptedException e)
29 | {
30 | e.printStackTrace();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/SnakeGame.java:
--------------------------------------------------------------------------------
1 | import jxl.Workbook;
2 | import jxl.write.*;
3 |
4 | import javax.swing.*;
5 | import java.awt.*;
6 | import java.awt.Label;
7 | import java.awt.event.KeyAdapter;
8 | import java.awt.event.KeyEvent;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.util.ArrayList;
12 | import java.util.Date;
13 | import java.util.Random;
14 | import java.util.concurrent.TimeUnit;
15 |
16 | /**
17 | * Created by Adriaan on 2016/09/20
18 | */
19 | public class SnakeGame extends JPanel
20 | {
21 | //constant variables
22 | private static final int DOT_SIZE = 15;
23 | private static final int populationSize = 50;
24 | private static final int boarderHeight = 425;
25 | private static final int boarderWidth = 425;
26 | private static final int ALL_DOTS = 600;
27 | private static final int randomPos = 27; //seed value for randoms
28 | private static final int noStepsTakenTillStallAllowed = 100;
29 |
30 | //pulic static vars
31 | public static int noInputsNeurons = 15;
32 | public static int noHiddenNeurons = 7;
33 | public static int noOutputNeurons = 4;
34 | public static int minSearchSpace = -10000;
35 | public static int maxSearchSpace = 10000;
36 |
37 | //size of board
38 | private static final int x[] = new int[ALL_DOTS];
39 | private static final int y[] = new int[ALL_DOTS];
40 |
41 | //global variables
42 | private static boolean leftDirection;
43 | private static boolean rightDirection;
44 | private static boolean upDirection;
45 | private static boolean downDirection;
46 | private static boolean inGame;
47 |
48 |
49 | private static int dots;
50 | private static int foodX;
51 | private static int foodY;
52 | private static int snakeLength;
53 | private static int maxSnakeLength;
54 | private static int iterationCounter;
55 | private static int applesEaten;
56 | public static int stepsTaken;
57 | public static int stepsTakenSinceLastFood;
58 |
59 | //mins and maxes for normalization
60 | private static double maxX;
61 | private static double maxY;
62 | private static double minY;
63 | private static double minX;
64 |
65 |
66 | //images to use
67 | private static Image imgBody;
68 | private static Image imgApple;
69 | private static Image imgHead;
70 |
71 | //positions of things
72 | private static XYPair headBody;
73 | private static XYPair midBody;
74 | private static XYPair tailBody;
75 | private static XYPair foodXY;
76 | private static boolean leftDirFree;
77 | private static boolean rightDirFree;
78 | private static boolean upDirFree;
79 | private static boolean downDirFree;
80 |
81 | //timer
82 | private static long timeSinceLastFood;
83 | private static long elapsedTimeSinceLastFood;
84 | private static long gameTime;
85 | private static long elapsedGameTime;
86 | private static boolean invalidMove;
87 |
88 | public static SnakeGame snakeGame;
89 | public static boolean btnStoppedPushed;
90 |
91 | private static WritableSheet writableSheet;
92 | private static WritableWorkbook writableWorkbook;
93 | private static Console console;
94 | //constructor
95 | public SnakeGame() throws IOException, WriteException {
96 | //initialze Excel
97 | btnStoppedPushed = false;
98 | String path = "C:\\Users\\Adriaan\\Desktop\\WRCI Results.xls";
99 | File exlFile = new File(path);
100 | writableWorkbook = Workbook.createWorkbook(exlFile);
101 | writableSheet = writableWorkbook.createSheet("Sheet1", 0);
102 | jxl.write.Label label = new jxl.write.Label(0, 0, "WRCI Results");
103 | writableSheet.addCell(label);
104 | //initialize variables
105 | inGame = true;
106 | snakeLength = 3;
107 | headBody = new XYPair(0,0);
108 | midBody = new XYPair(0,0);
109 | tailBody = new XYPair(0,0);
110 | foodXY = new XYPair(0,0);
111 |
112 | //put the key listener in
113 | addKeyListener(new TAdapter());
114 |
115 | setBackground(Color.black);
116 | setFocusable(true);
117 | setPreferredSize(new Dimension(boarderWidth, boarderHeight));
118 | iterationCounter = 0;
119 | applesEaten = 0;
120 | stepsTaken = 0;
121 | stepsTakenSinceLastFood = 0;
122 | invalidMove = false;
123 | initializeImages();
124 | initializeGame();
125 | }
126 |
127 | //used by the Main class.
128 | public static SnakeGame getClassInstance()
129 | {
130 | if (snakeGame == null)
131 | {
132 | try {
133 | //console lets us see the result from each iteration
134 | snakeGame = new SnakeGame();
135 | console = new Console();
136 | } catch (IOException e) {
137 | e.printStackTrace();
138 | } catch (WriteException e) {
139 | e.printStackTrace();
140 | }
141 | return snakeGame;
142 | }
143 | return snakeGame;
144 | }
145 |
146 | public void runGame() throws InterruptedException
147 | {
148 | //iteration of each game. at the end of each iteration info is passed back and fourth to the GA.
149 | GeneticTraining ga = new GeneticTraining(populationSize); //takes in the population size
150 | //set up the NN with the info from the GA
151 | neuralNetWork NN = new neuralNetWork();
152 | Chromosone c; //this will be used to keep track of the current chromozone we are on.
153 | iterationCounter = 0;
154 | maxSnakeLength = 3; //always starts with length 3.
155 | while (iterationCounter < 200001 && !btnStoppedPushed)
156 | {
157 | c = ga.getCurChromosone();
158 | NN.setWeightsOfNN(c.getvWeights(), c.getwWeights());
159 |
160 | //restart stall counter. --> these have been depricated. working with number of steps is better.
161 | restartFoodTimer();
162 | restartGameTimer();
163 | snakeLength = 3;
164 | applesEaten = 0;
165 | //gives us updates in console.
166 | if (iterationCounter % 20000 == 0)
167 | System.out.println("Max length achieved so far: " + maxSnakeLength);
168 |
169 | //this while loop runs the actual game within each iteration.
170 | while (inGame)
171 | {
172 | //every 20 thousand iterations you can see how the snake is doing.
173 | //if the snake reachers a length greater than 25, we will also see what it is doing.
174 | //reduce the sleep time, to make the snake move faster.
175 | if (iterationCounter % 20000 == 0 || snakeLength > 29)
176 | TimeUnit.MILLISECONDS.sleep(100);
177 |
178 | //this is also deprecated, as invalid moves should not be made. leave just in case.
179 | if (invalidMove)
180 | inGame = false;
181 |
182 | //we want to know which direction we are going in, so that if the NN tries to go that way, we say "NO BITCH", and take the next best move. the game stalls if the NN tries to go in the opposite direction as this is not allowed, but the inputs don't change, so the NN will continuing trying.
183 | int currentOppositeDir = 0;
184 | if (leftDirection)
185 | currentOppositeDir = 1;
186 | else if (rightDirection)
187 | currentOppositeDir = 0;
188 | else if (upDirection)
189 | currentOppositeDir = 3;
190 | else if (downDirection)
191 | currentOppositeDir = 2;
192 | double[] inputs = getInputs(); //get new inputs for the NN for the next move.
193 | int Move = NN.getNextMove(currentOppositeDir, inputs); //calculate the next move.
194 |
195 | managemove(Move); //find out in which way the NN wants us to go.
196 |
197 | handleMovement(); //actually move the snake.
198 | checkEatenApple(); //did the snake find food? if so increase its length and reset the stall counter.
199 |
200 | //did the snake just learn how to survive without the need to find food? kill it dead. game stalled.
201 | //this value might need to be changed to something dynamic, as when the size increases, it might need more steps.
202 | if (stepsTakenSinceLastFood > noStepsTakenTillStallAllowed)
203 | {
204 | inGame = false;
205 | c.stalled = true;
206 | }
207 | checkForCollision(); //did the snake collide with anything? wall or body? if so, kill it.
208 | if (iterationCounter % 20000 == 0 || snakeLength > 29) //we don't show what is going on the screen in "simulation mode", takes too long.
209 | repaint(); //refresh screen.
210 | }
211 | //set the chromosone's fitness. //use of time has been depricated.
212 | c.setFitness(getElapsedGameTime(), snakeLength);
213 | //use the console to update what happened in the current iteration.
214 | //console.addToConsole("Iteation: " + iterationCounter + " Length: " + snakeLength);
215 | System.out.println("Iteation: " + iterationCounter + " Length: " + snakeLength);
216 | if (snakeLength > maxSnakeLength)
217 | {
218 | maxSnakeLength = snakeLength;
219 | console.addToConsole("New Highscoore of: " + maxSnakeLength + ", in iteration: " + iterationCounter);
220 | }
221 |
222 |
223 |
224 | iterationCounter++;
225 | //if we have been through a population of chromosone's its time to do crossovers and mutations, etc.
226 | if (iterationCounter % ga.populationSize == 0)
227 | ga.Train();
228 | //move onto the next chromosone. this wraps around to the beginning once the population size is reached.
229 | ga.incCurChromosone();
230 | //initialize the next iteration
231 | initializeGame();
232 | }
233 | console.addToConsole("Game Stopped!");
234 |
235 | //write to excel
236 | writeExcelResults(ga);
237 | try {
238 | writableWorkbook.write();
239 | writableWorkbook.close();
240 | } catch (IOException e) {
241 | e.printStackTrace();
242 | } catch (WriteException e) {
243 | e.printStackTrace();
244 | }
245 | }
246 |
247 | private void writeExcelResults(GeneticTraining ga)
248 | {
249 | jxl.write.Label label;
250 | try {
251 | // LABEL: (COLOUMN, ROW, STRING);
252 | //NN Details
253 | label = new jxl.write.Label(0, 2, "NN Details");
254 | writableSheet.addCell(label);
255 | label = new jxl.write.Label(0, 3, "Input Neurons");
256 | writableSheet.addCell(label);
257 | label = new jxl.write.Label(0, 4, "Hidden Neurons");
258 | writableSheet.addCell(label);
259 | label = new jxl.write.Label(0, 5, "Output Neurons");
260 | writableSheet.addCell(label);
261 | label = new jxl.write.Label(1, 3, String.valueOf(noInputsNeurons));
262 | writableSheet.addCell(label);
263 | label = new jxl.write.Label(1, 4, String.valueOf(noHiddenNeurons));
264 | writableSheet.addCell(label);
265 | label = new jxl.write.Label(1, 5, String.valueOf(noOutputNeurons));
266 | writableSheet.addCell(label);
267 |
268 | //Game Details
269 | label = new jxl.write.Label(3, 2, "Game Details");
270 | writableSheet.addCell(label);
271 | label = new jxl.write.Label(3, 3, "No Steps taken until stall");
272 | writableSheet.addCell(label);
273 | label = new jxl.write.Label(3, 2, "No Iterations over all chromosomes");
274 | writableSheet.addCell(label);
275 | label = new jxl.write.Label(3, 2, "Max Snake Length Achieved");
276 | writableSheet.addCell(label);
277 | label = new jxl.write.Label(4, 3, String.valueOf(noStepsTakenTillStallAllowed));
278 | writableSheet.addCell(label);
279 | label = new jxl.write.Label(4, 2, String.valueOf(iterationCounter));
280 | writableSheet.addCell(label);
281 | label = new jxl.write.Label(4, 2, String.valueOf(maxSnakeLength));
282 | writableSheet.addCell(label);
283 |
284 | //GA Details
285 | label = new jxl.write.Label(6, 2, "GA Details");
286 | writableSheet.addCell(label);
287 | label = new jxl.write.Label(6, 3, "Population Size");
288 | writableSheet.addCell(label);
289 | label = new jxl.write.Label(6, 4, "Mutation Rate");
290 | writableSheet.addCell(label);
291 | label = new jxl.write.Label(6, 5, "Hall Of Fame Size");
292 | writableSheet.addCell(label);
293 | label = new jxl.write.Label(6, 6, "Tournament Size");
294 | writableSheet.addCell(label);
295 | label = new jxl.write.Label(6, 7, "Min Search Space");
296 | writableSheet.addCell(label);
297 | label = new jxl.write.Label(6, 8, "Max Search Space");
298 | writableSheet.addCell(label);
299 | label = new jxl.write.Label(7, 3, String.valueOf(populationSize));
300 | writableSheet.addCell(label);
301 | label = new jxl.write.Label(7, 4, String.valueOf(ga.mutationRate));
302 | writableSheet.addCell(label);
303 | label = new jxl.write.Label(7, 5, String.valueOf(ga.hallOfFameSize));
304 | writableSheet.addCell(label);
305 | label = new jxl.write.Label(7, 6, String.valueOf(ga.tournamentSize));
306 | writableSheet.addCell(label);
307 | label = new jxl.write.Label(7, 7, String.valueOf(minSearchSpace));
308 | writableSheet.addCell(label);
309 | label = new jxl.write.Label(7, 8, String.valueOf(maxSearchSpace));
310 | writableSheet.addCell(label);
311 | }
312 | catch (WriteException e)
313 | {
314 | e.printStackTrace();
315 | }
316 | }
317 |
318 | private void managemove(int Move)
319 | {
320 | //check for invalid moves. this should never happen now.
321 | if ((Move == 0) && (rightDirection)) //move left
322 | {
323 | invalidMove = true;
324 | }
325 | else if ((Move == 1) && (leftDirection)) //move right
326 | {
327 | invalidMove = true;
328 | }
329 | else if ((Move == 2) && (downDirection)) //move down
330 | {
331 | invalidMove = true;
332 | }
333 | else if ((Move == 3) && (upDirection)) //move up
334 | {
335 | invalidMove = true;
336 | }
337 |
338 | //set the new direction
339 | if ((Move == 0) && (!rightDirection)) //move left
340 | {
341 | leftDirection = true;
342 | upDirection = false;
343 | downDirection = false;
344 | }
345 | else if ((Move == 1) && (!leftDirection)) //move right
346 | {
347 | rightDirection = true;
348 | upDirection = false;
349 | downDirection = false;
350 | }
351 | else if ((Move == 2) && (!downDirection)) //move up
352 | {
353 | upDirection = true;
354 | rightDirection = false;
355 | leftDirection = false;
356 | }
357 | else if ((Move == 3) && (!upDirection))//move down
358 | {
359 | downDirection = true;
360 | rightDirection = false;
361 | leftDirection = false;
362 | }
363 | }
364 |
365 | //start with a length of 3. place the food on the board. food will never be placed somewhere on the snake's body.
366 | private static void initializeGame()
367 | {
368 | inGame = true;
369 | dots = 3;
370 | // rightDirection = true;
371 | leftDirection = false;
372 | rightDirection = false;
373 | upDirection = false;
374 | downDirection = false;
375 | stepsTaken = 0;
376 | stepsTakenSinceLastFood = 0;
377 | invalidMove = false;
378 | //place the width and height of the pixels for each "dot"/length of body. the paint method will take care of the rest.
379 | // for (int i = 0; i <= dots -1; i++)
380 | // {
381 | // x[i] = 50 - i * 15;
382 | // y[i] = 50;
383 | // }
384 |
385 | //snake needs to start in a random pos
386 | //pick direction
387 | int dir = randomInt0and3() + 1;
388 | //always start in the centre of the board.
389 | int headpos = (13* 15) + 5;
390 | //int headpos = randomInt0and25();
391 | if (dir == 1) //going right
392 | {
393 | rightDirection = true;
394 | x[0] = headpos;
395 | y[0] = headpos;
396 | x[1] = headpos - 15;
397 | y[1] = headpos;
398 | x[2] = headpos - 30;
399 | y[2] = headpos;
400 | }
401 | else if (dir == 2) //going left
402 | {
403 | leftDirection = true;
404 | x[0] = headpos;
405 | y[0] = headpos;
406 | x[1] = headpos + 15;
407 | y[1] = headpos;
408 | x[2] = headpos + 30;
409 | y[2] = headpos;
410 | }
411 | else if (dir == 3) //going up
412 | {
413 | upDirection = true;
414 | x[0] = headpos;
415 | y[0] = headpos;
416 | x[1] = headpos;
417 | y[1] = headpos + 15;
418 | x[2] = headpos;
419 | y[2] = headpos + 30;
420 | }
421 | else if (dir == 4) //going down
422 | {
423 | downDirection = true;
424 | x[0] = headpos;
425 | y[0] = headpos;
426 | x[1] = headpos;
427 | y[1] = headpos - 15;
428 | x[2] = headpos;
429 | y[2] = headpos - 30;
430 | }
431 | placeApple();
432 | updatePostitions();
433 | }
434 |
435 | //used to find a random pos on the board.
436 | public static int randomInt0and25()
437 | {
438 | // Random r = new Random();
439 | // int min = 3;
440 | // int max = 21;
441 | // int randomVal = r.nextInt((max - min)) + min;
442 | int randomVal = 13;
443 | return (randomVal * 15) + 5;
444 | }
445 |
446 | //use for a random starting direction.
447 | public static int randomInt0and3()
448 | {
449 | Random r = new Random();
450 | int min = 0;
451 | int max = 4;
452 | int randomVal = r.nextInt((max - min)) + min;
453 | return randomVal;
454 | }
455 |
456 | //pop up message method - currently not being used.
457 | public static void infoBox(String infoMessage)
458 | {
459 | JOptionPane.showMessageDialog(null, infoMessage, "Snake", JOptionPane.INFORMATION_MESSAGE);
460 | }
461 |
462 | //resets the timer if the snake finds food.
463 | private static void restartFoodTimer()
464 | {
465 | timeSinceLastFood = System.currentTimeMillis();
466 | }
467 |
468 | //used to check if the snake is stalling.
469 | private static long getElapsedTimeSinceLastFood()
470 | {
471 | elapsedTimeSinceLastFood = (new Date()).getTime() - timeSinceLastFood;
472 | return elapsedTimeSinceLastFood;
473 | }
474 |
475 | private static void restartGameTimer()
476 | {
477 | gameTime = System.currentTimeMillis();
478 | }
479 |
480 | private static long getElapsedGameTime()
481 | {
482 | elapsedGameTime = (new Date()).getTime() - gameTime;
483 | return elapsedGameTime;
484 | }
485 |
486 | //this is what gets passed to the NN for it to make a decision
487 | // public double[] getInputs()
488 | // {
489 | // double inputs[] = new double[11];
490 | // inputs[0] = headBody.getX();
491 | // inputs[1] = headBody.getY();
492 | // inputs[2] = foodX;
493 | // inputs[3] = foodY;
494 | // double distToFoodX = Math.abs(headBody.getX() - foodX);
495 | // inputs[4] = distToFoodX;
496 | // double distToFoodY = Math.abs(headBody.getY() - foodY);
497 | // inputs[5] = distToFoodY;
498 | // double L = 0.0;
499 | // double R = 0.0;
500 | // double U = 0.0;
501 | // double D = 0.0;
502 | // if (leftDirFree)
503 | // L = 1.0;
504 | // if (rightDirFree)
505 | // R = 1.0;
506 | // if (upDirFree)
507 | // U = 1.0;
508 | // if (downDirFree)
509 | // D = 1.0;
510 | // inputs[6] = L;
511 | // inputs[7] = R;
512 | // inputs[8] = U;
513 | // inputs[9] = D;
514 | // inputs[10] = -1.0;
515 | //
516 | // normalizeInputs(inputs);
517 | //
518 | // return inputs;
519 | // }
520 | public double[] getInputs()
521 | {
522 | double inputs[] = new double[15];
523 | inputs[0] = headBody.getX();
524 | inputs[1] = headBody.getY();
525 | inputs[2] = midBody.getX();
526 | inputs[3] = midBody.getY();
527 | inputs[4] = tailBody.getX();
528 | inputs[5] = tailBody.getY();
529 | inputs[6] = foodX;
530 | inputs[7] = foodY;
531 | double distToFoodX = Math.abs(headBody.getX() - foodX);
532 | inputs[8] = distToFoodX;
533 | double distToFoodY = Math.abs(headBody.getY() - foodY);
534 | inputs[9] = distToFoodY;
535 | double L = 0.0;
536 | double R = 0.0;
537 | double U = 0.0;
538 | double D = 0.0;
539 | if (leftDirFree)
540 | L = 1.0;
541 | if (rightDirFree)
542 | R = 1.0;
543 | if (upDirFree)
544 | U = 1.0;
545 | if (downDirFree)
546 | D = 1.0;
547 | inputs[10] = L;
548 | inputs[11] = R;
549 | inputs[12] = U;
550 | inputs[13] = D;
551 | inputs[14] = -1.0;
552 |
553 | normalizeInputs(inputs);
554 |
555 | return inputs;
556 | }
557 |
558 | //we are using a sigmoid activation function. all inputs must be normalized.
559 | //x and y are normalized to their own x and y mins and maxes. this ensure that their distances don't affect each other.
560 | private void normalizeInputs(double[] inputs)
561 | {
562 | maxX = -1;
563 | maxY = -1;
564 | minX = 999999;
565 | minY = 999999;
566 | for (int i = 0; i <= 9; i++)
567 | {
568 | if (i % 2 == 0)
569 | {
570 | if (inputs[i] > maxX)
571 | maxX = inputs[i];
572 | if (inputs[i] < minX)
573 | minX = inputs[i];
574 | }
575 | else
576 | {
577 | if (inputs[i] > maxY)
578 | maxY = inputs[i];
579 | if (inputs[i] < minY)
580 | minY = inputs[i];
581 | }
582 | }
583 | for (int i = 0; i <= 9; i++)
584 | {
585 | double numerator;
586 | double demoninator;
587 | double normalized;
588 | if (i % 2 == 0)
589 | {
590 | numerator = inputs[i] - minX;
591 | demoninator = maxX - minX;
592 | normalized = numerator / demoninator;
593 | inputs[i] = normalized;
594 | }
595 | else
596 | {
597 | numerator = inputs[i] - minY;
598 | demoninator = maxY - minY;
599 | normalized = numerator / demoninator;
600 | inputs[i] = normalized;
601 | }
602 | }
603 | }
604 |
605 | //take the snake's current pos for everything that we need for the NN inputs
606 | private static void updatePostitions() {
607 | //get the length of the snake
608 | int sizeXandY = 0;
609 |
610 | for (int i : x)
611 | if (i != 0)
612 | sizeXandY++;
613 | else
614 | break;
615 | //set snake body info
616 | headBody.setX(x[0]);
617 | headBody.setY(y[0]);
618 | Double halfPos = snakeLength / 2.0;
619 | String temp = String.valueOf(halfPos);
620 | if (temp.contains(".5"))
621 | halfPos = halfPos + 0.5;
622 | int hp = Integer.valueOf(halfPos.intValue()) - 1; //indexes start at a different places
623 | int tempX = x[hp];
624 | int tempY = y[hp];
625 | midBody.setX(x[hp]);
626 | midBody.setY(y[hp]);
627 | tailBody.setX(x[snakeLength]);
628 | tailBody.setY(y[snakeLength]);
629 |
630 | foodXY.setX(foodX);
631 | foodXY.setY(foodY);
632 |
633 | //available spaces the snake can more. true means the space is free, and the head can move there.
634 | leftDirFree = true;
635 | rightDirFree = true;
636 | upDirFree = true;
637 | downDirFree = true;
638 | //check the direction the snake is moving and rule out the opposite direction
639 | if (leftDirection)
640 | rightDirFree = false;
641 | else if (rightDirection)
642 | leftDirFree = false;
643 | else if (upDirection)
644 | downDirFree = false;
645 | else if (downDirection)
646 | upDirFree = false;
647 | //rule out boundary movements
648 | if (x[0] == 5)
649 | leftDirFree = false;
650 | else if (x[0] == 410)
651 | rightDirFree = false;
652 | if (y[0] == 5)
653 | upDirFree = false;
654 | else if (y[0] == 410)
655 | downDirFree = false;
656 | //rule out moving into the body.
657 | //check to the left
658 | tempX = x[0];
659 | tempY = y[0];
660 | if (leftDirFree) {
661 | int tempXX = tempX - DOT_SIZE;
662 | for (int i = dots; i > 0; i--)
663 | if ((i > 0) && (tempXX == x[i]) && (tempY == y[i])) {
664 | leftDirFree = false;
665 | break;
666 | }
667 | }
668 | if (rightDirFree) {
669 | int tempXX = tempX + DOT_SIZE;
670 | for (int i = dots; i > 0; i--)
671 | if ((i > 0) && (tempXX == x[i]) && (tempY == y[i])) {
672 | rightDirFree = false;
673 | break;
674 | }
675 | }
676 | if (upDirFree) {
677 | int tempYY = tempY - DOT_SIZE;
678 | for (int i = dots; i > 0; i--)
679 | if ((i > 0) && (tempX == x[i]) && (tempYY == y[i])) {
680 | upDirFree = false;
681 | break;
682 | }
683 | }
684 | if (downDirFree) {
685 | int tempYY = tempY + DOT_SIZE;
686 | for (int i = dots; i > 0; i--)
687 | if ((i > 0) && (tempX == x[i]) && (tempYY == y[i]))
688 | {
689 | downDirFree = false;
690 | break;
691 | }
692 | }
693 | }
694 |
695 | //drawing method that handles the changing and updting of pixels
696 | //called by the "repaint()" method.
697 | @Override
698 | protected void paintComponent(Graphics g)
699 | {
700 | super.paintComponent(g);
701 | if (inGame) {
702 |
703 | g.drawImage(imgApple, foodX, foodY, this);
704 |
705 | for (int z = 0; z < dots; z++) {
706 | if (z == 0) {
707 | g.drawImage(imgHead, x[z], y[z], this);
708 | } else {
709 | g.drawImage(imgBody, x[z], y[z], this);
710 | }
711 | }
712 | Toolkit.getDefaultToolkit().sync();
713 | }
714 | else
715 | {
716 | gameOver(g);
717 | }
718 | }
719 |
720 | //handle the moving of the snake.
721 | private static void handleMovement()
722 | {
723 | //shift the tail up.
724 | for (int i = dots; i > 0; i--)
725 | {
726 | x[i] = x[(i - 1)];
727 | y[i] = y[(i - 1)];
728 | }
729 |
730 | //move the head
731 | if (leftDirection)
732 | x[0] -= DOT_SIZE;
733 |
734 |
735 | if (rightDirection)
736 | x[0] += DOT_SIZE;
737 |
738 |
739 | if (upDirection)
740 | y[0] -= DOT_SIZE;
741 |
742 |
743 | if (downDirection)
744 | y[0] += DOT_SIZE;
745 |
746 | stepsTaken++;
747 | stepsTakenSinceLastFood++;
748 | updatePostitions();
749 |
750 | }
751 |
752 | //we only need to check where the head is, as the body can't go where the head hasn't been
753 | private static void checkForCollision() {
754 |
755 | for (int i = dots; i > 0; i--)
756 | if ((i > 3) && (x[0] == x[i]) && (y[0] == y[i]))
757 | inGame = false;
758 |
759 | if (y[0] >= boarderHeight)
760 | inGame = false;
761 |
762 |
763 | if (y[0] < 0)
764 | inGame = false;
765 |
766 |
767 | if (x[0] >= boarderWidth)
768 | inGame = false;
769 |
770 |
771 | if (x[0] < 0)
772 | inGame = false;
773 | }
774 |
775 | //this is not used for anything at the moment.
776 | private void gameOver(Graphics g)
777 | {
778 |
779 | }
780 |
781 | //have we eaten an apple? if so, increase length and place a new apple.
782 | //again, need to have check that the apple does not spawn on the body.
783 | private static void checkEatenApple()
784 | {
785 | if ((x[0] == foodX) && (y[0] == foodY))
786 | {
787 | dots++;
788 | snakeLength++;
789 | applesEaten++;
790 | placeApple();
791 | restartFoodTimer();
792 | stepsTakenSinceLastFood = 0;
793 | }
794 | }
795 |
796 | //random location for the apple, that is not on the snake's body
797 | private static void placeApple()
798 | {
799 | int R = (int) (Math.random() * randomPos);
800 | foodX = (R * DOT_SIZE + 5);
801 | R = (int) (Math.random() * randomPos);
802 | foodY = (R * DOT_SIZE + 5);
803 | while (checkIfFoodPlacedOnBody())
804 | {
805 | R = (int) (Math.random() * randomPos);
806 | foodX = (R * DOT_SIZE + 5);
807 | R = (int) (Math.random() * randomPos);
808 | foodY = (R * DOT_SIZE + 5);
809 | }
810 | }
811 |
812 | private static boolean checkIfFoodPlacedOnBody()
813 | {
814 | for (int i = dots; i > 0; i--)
815 | {
816 | if (foodX == x[i] && foodY == y[i])
817 | return true;
818 | }
819 | return false;
820 | }
821 |
822 | //load the dots that will be drawn on the paint method.
823 | private static void initializeImages()
824 | {
825 | ImageIcon tempIcon = new ImageIcon("body.png");
826 | imgBody = tempIcon.getImage();
827 | tempIcon = new ImageIcon("head.png");
828 | imgHead = tempIcon.getImage();
829 | tempIcon = new ImageIcon("apple.png");
830 | imgApple = tempIcon.getImage();
831 | }
832 |
833 | //this is not used anymore as snake controls itself. if you want to be an asshole you can interrupt the snake's game. but maybe let him, you know? do his thang.
834 | private class TAdapter extends KeyAdapter
835 | {
836 | //what to do when a key is pressed.
837 | //will we eaten an apple?
838 | //will we hit the body or wall?
839 | //okay, cool, time to move.
840 | //repaint -> update the board.
841 | public void keyPressed() {
842 |
843 | }
844 |
845 | @Override
846 | public void keyPressed(KeyEvent e)
847 | {
848 | super.keyPressed(e);
849 |
850 | int key = e.getKeyCode();
851 |
852 | if ((key == KeyEvent.VK_LEFT) && (!rightDirection)) {
853 | leftDirection = true;
854 | upDirection = false;
855 | downDirection = false;
856 | keyPressed();
857 | }
858 |
859 | if ((key == KeyEvent.VK_RIGHT) && (!leftDirection)) {
860 | rightDirection = true;
861 | upDirection = false;
862 | downDirection = false;
863 | keyPressed();
864 | }
865 |
866 | if ((key == KeyEvent.VK_UP) && (!downDirection)) {
867 | upDirection = true;
868 | rightDirection = false;
869 | leftDirection = false;
870 | keyPressed();
871 | }
872 |
873 | if ((key == KeyEvent.VK_DOWN) && (!upDirection)) {
874 | downDirection = true;
875 | rightDirection = false;
876 | leftDirection = false;
877 | keyPressed();
878 | }
879 | }
880 | }
881 | }
882 |
--------------------------------------------------------------------------------
/src/XYPair.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Adriaan on 2016/11/10.
3 | */
4 | public class XYPair
5 | {
6 | int x, y;
7 |
8 | public XYPair(int x, int y)
9 | {
10 | this.x = x;
11 | this.y = y;
12 | }
13 |
14 | public int getX() {
15 | return x;
16 | }
17 |
18 | public void setX(int x) {
19 | this.x = x;
20 | }
21 |
22 | public int getY() {
23 | return y;
24 | }
25 |
26 | public void setY(int y) {
27 | this.y = y;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/neuralNetWork.java:
--------------------------------------------------------------------------------
1 | import java.util.Random;
2 |
3 | /**
4 | * Created by Adriaan on 2016/11/10.
5 | */
6 | public class neuralNetWork
7 | {
8 | int noInputsNeurons, noOutputNeurons, noHiddenNeurons;
9 | public double[][] wWeights;
10 | public double[][] vWeights;
11 |
12 | public neuralNetWork()
13 | {
14 | noInputsNeurons = SnakeGame.noInputsNeurons; //head x and y, mid x and y, tail x and y, is space free in the direction left, right up and down, food x and y, distance to food x and y, bias;
15 | noHiddenNeurons = SnakeGame.noHiddenNeurons;
16 | noOutputNeurons = SnakeGame.noOutputNeurons;
17 | vWeights = new double[noHiddenNeurons][noInputsNeurons]; //2D array for weights going from every input node, to every hidden node.
18 | wWeights = new double[noOutputNeurons][noHiddenNeurons]; //2D array for weights going from every hidden node to every output node
19 |
20 | //setWeightsOfNN();
21 | }
22 |
23 | //will take the weights from the GA and set them here.
24 | public void setWeightsOfNN(double[][] inputtedVWeights, double[][] inputtedWWeights)
25 | {
26 | //give initial weights
27 | vWeights = inputtedVWeights;
28 | wWeights = inputtedWWeights;
29 | }
30 |
31 | //takes the inputs and then uses the NN to get a move out.
32 | public int getNextMove(int curDir, double[] inputs)
33 | {
34 | double highestActual = 0;
35 | int toOutput = 0;
36 | for (int j = 0; j <= noOutputNeurons - 1; j++)
37 | {
38 | double actual = calcuateFNetHiddenAndOutput(inputs).storedOutputNets[j];
39 | if (actual > highestActual && curDir != j)
40 | {
41 | highestActual = actual;
42 | toOutput = j;
43 | }
44 | }
45 | return toOutput;
46 | }
47 |
48 | //for testing purposes
49 | public void setWeightsOfNN()
50 | {
51 | //give initial weights
52 | for (int i = 0; i<= noInputsNeurons -1; i++) //set the last one to be the bias
53 | for (int j = 0; j <= noHiddenNeurons-1; j++)
54 | vWeights[j][i] = randomDouble();
55 |
56 | for (int j = 0; j <= noHiddenNeurons-1; j++)
57 | {
58 | for (int k = 0; k<= noOutputNeurons -1; k++)
59 | wWeights[k][j] = randomDouble();
60 | }
61 | }
62 |
63 | //based on the weights, calculate the NN;
64 | private storedNetClass calcuateFNetHiddenAndOutput(double[] inputPattern)
65 | {
66 | double[] hiddenFNets = new double[noHiddenNeurons];
67 | double[] outputFNets = new double[noOutputNeurons];
68 |
69 | double outputNet, hiddenNet;
70 | for (int k = 0; k<= noOutputNeurons -1; k++)
71 | {
72 | outputNet = 0.0;
73 | for (int j = 0; j<= noHiddenNeurons-1; j++)
74 | {
75 | hiddenNet = 0.0;
76 | for (int i = 0; i<= noInputsNeurons-1; i++)
77 | {
78 | hiddenNet = hiddenNet + (vWeights[j][i] * inputPattern[i]);
79 | }
80 | if (j == (noHiddenNeurons -1)) //bias for hidden layer
81 | hiddenFNets[j] = -1.0;
82 | else
83 | hiddenFNets[j] = getActivationFunctionValue(hiddenNet, "sig");
84 |
85 | outputNet = outputNet + (wWeights[k][j] * hiddenFNets[j]);
86 | }
87 | outputFNets[k] = getActivationFunctionValue(outputNet, "sig");
88 | }
89 | return new storedNetClass(hiddenFNets, outputFNets);
90 | }
91 |
92 |
93 | public double randomDouble()
94 | {
95 | Random r = new Random();
96 | double min = -1 / Math.sqrt(noInputsNeurons);
97 | double max = 1/ Math.sqrt(noInputsNeurons);
98 | double randomVal = (r.nextDouble() * (max - min)) + min;
99 | return randomVal;
100 | }
101 |
102 | private double getActivationFunctionValue(double in, String activFunc)
103 | {
104 | double result;
105 | if (activFunc.equals("lin")) //linear
106 | {
107 | return in;
108 | }
109 | else //if (activFunc.equals("sig")) //sigmoid
110 | {
111 | result = 1.0 / (1.0 + (Math.exp(-in)));
112 | return result;
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/storedNetClass.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Adriaan on 2016/11/11.
3 | */
4 | public class storedNetClass
5 | {
6 | public double[] storedHiddenNets;
7 | public double[] storedOutputNets;
8 |
9 | public storedNetClass(double[] storedHiddenNets, double[] storedOutputNets) {
10 | this.storedHiddenNets = storedHiddenNets;
11 | this.storedOutputNets = storedOutputNets;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------