TicTacToeDe.ino 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. TicTacToeDe.ino
  3. */
  4. #include <Arduino.h>
  5. #include <U8g2lib.h>
  6. /*==============================================*/
  7. /* Konstante Werte */
  8. #define GITTER_X_OFFSET 35
  9. #define GITTER_Y_OFFSET 2
  10. #define ZELLE_BREITE 17
  11. #define ZELLE_HOEHE 17
  12. #define ZELLE_RAHMENBREITE 3
  13. #define FELD_NICHT_BELEGT 0
  14. #define FELD_MARKIERT_DURCH_SPIELER 1
  15. #define FELD_MARKIERT_DURCH_COMPUTER 2
  16. /*==============================================*/
  17. /* Variablen */
  18. /* U8g2 Graphics API, setup for ARDUBOY Production, Kickstarter Edition */
  19. U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 12, /* dc=*/ 4, /* reset=*/ 6);
  20. uint8_t cursor_position; /* Aktuelle Cursorposition die vom User ausgewählt wurde */
  21. u8g2_uint_t zelle_x, zelle_y; /* Berechnete Position einer Zelle (berechne_zell_position) */
  22. int spielfeld[3][3]; /* Enthält die aktuelle Belegung mit x und o */
  23. int gewinner; /* Zeigt den gewinner an (wenn es einen gibt) */
  24. /*==============================================*/
  25. /* vorbelegung und spiel initalisierenalisierung */
  26. void spiel_initalisieren(void)
  27. {
  28. int x, y;
  29. gewinner = FELD_NICHT_BELEGT;
  30. for( y = 0; y < 3; y = y + 1 )
  31. {
  32. for( x = 0; x < 3; x = x + 1 )
  33. {
  34. spielfeld[y][x] = FELD_NICHT_BELEGT;
  35. }
  36. }
  37. }
  38. /*==============================================*/
  39. /* Hilfsroutine */
  40. /* berechne die Zell-Position, Ergebnis in zelle_x und zelle_y */
  41. void berechne_zell_position(uint8_t x, uint8_t y )
  42. {
  43. zelle_x = x;
  44. zelle_x*=ZELLE_BREITE+ZELLE_RAHMENBREITE;
  45. zelle_x+= GITTER_X_OFFSET;
  46. zelle_y = y;
  47. zelle_y *=ZELLE_HOEHE+ZELLE_RAHMENBREITE;
  48. zelle_y +=GITTER_Y_OFFSET;
  49. }
  50. /*==============================================*/
  51. /* "game engine" */
  52. void zeichne_gitter(void)
  53. {
  54. u8g2_uint_t x, y;
  55. x = GITTER_X_OFFSET+ZELLE_BREITE;
  56. u8g2.drawVLine(x+1, GITTER_Y_OFFSET, ZELLE_HOEHE*3+ZELLE_RAHMENBREITE*2);
  57. x += ZELLE_BREITE+ZELLE_RAHMENBREITE;
  58. u8g2.drawVLine(x+1, GITTER_Y_OFFSET, ZELLE_HOEHE*3+ZELLE_RAHMENBREITE*2);
  59. y = GITTER_Y_OFFSET+ZELLE_HOEHE;
  60. u8g2.drawHLine(GITTER_X_OFFSET, y+1, ZELLE_BREITE*3+ZELLE_RAHMENBREITE*2);
  61. y += ZELLE_HOEHE+ZELLE_RAHMENBREITE;
  62. u8g2.drawHLine(GITTER_X_OFFSET, y+1, ZELLE_BREITE*3+ZELLE_RAHMENBREITE*2);
  63. }
  64. void zeichne_spielfeld(void)
  65. {
  66. int x, y;
  67. for( y = 0; y < 3; y = y + 1 )
  68. {
  69. for( x = 0; x < 3; x = x + 1 )
  70. {
  71. if ( spielfeld[y][x] == FELD_NICHT_BELEGT )
  72. {
  73. /* nichts anzeigen */
  74. }
  75. if ( spielfeld[y][x] == FELD_MARKIERT_DURCH_SPIELER )
  76. {
  77. berechne_zell_position(x, y);
  78. u8g2.drawLine(zelle_x, zelle_y, zelle_x+ZELLE_BREITE-1, zelle_y+ZELLE_HOEHE-1);
  79. u8g2.drawLine(zelle_x+ZELLE_BREITE-1, zelle_y, zelle_x, zelle_y+ZELLE_HOEHE-1);
  80. }
  81. if ( spielfeld[y][x] == FELD_MARKIERT_DURCH_COMPUTER )
  82. {
  83. berechne_zell_position(x, y);
  84. u8g2.drawCircle(zelle_x+ZELLE_BREITE/2, zelle_y+ZELLE_HOEHE/2, ZELLE_HOEHE/2);
  85. }
  86. } /* for x */
  87. } /* for y */
  88. }
  89. void zeichne_gitter_und_spielfeld(void)
  90. {
  91. zeichne_gitter();
  92. zeichne_spielfeld();
  93. }
  94. void zeige_spielfeld_an(void)
  95. {
  96. u8g2.firstPage();
  97. do
  98. {
  99. yield(); // Arduino
  100. zeichne_gitter_und_spielfeld();
  101. } while ( u8g2.nextPage() );
  102. }
  103. /*==============================================*/
  104. /* Benitzerschnittstelle (User Interface) */
  105. /* Zeichne den Cursor für die Benutzereingabe */
  106. void zeichne_cursor(void)
  107. {
  108. u8g2_uint_t x, y;
  109. x = cursor_position % 3;
  110. y = cursor_position / 3;
  111. berechne_zell_position(x, y );
  112. u8g2.drawFrame(zelle_x, zelle_y, ZELLE_BREITE, ZELLE_HOEHE);
  113. u8g2.drawFrame(zelle_x+1, zelle_y+1, ZELLE_BREITE-2, ZELLE_HOEHE-2);
  114. }
  115. void zug_spieler(void)
  116. {
  117. static uint8_t keycode = 0;
  118. int x;
  119. int y;
  120. int zaehler = 0;
  121. for(;;) /* check valid entry */
  122. {
  123. for(;;) /* cursor movement loop */
  124. {
  125. keycode = 0;
  126. u8g2.firstPage();
  127. do
  128. {
  129. zeichne_gitter_und_spielfeld();
  130. zeichne_cursor();
  131. if ( keycode == 0 )
  132. keycode = u8g2.getMenuEvent();
  133. } while ( u8g2.nextPage() );
  134. while ( keycode == 0 )
  135. {
  136. yield(); // Arduino
  137. keycode = u8g2.getMenuEvent();
  138. }
  139. if ( keycode == U8X8_MSG_GPIO_MENU_DOWN )
  140. {
  141. cursor_position += 3;
  142. if ( cursor_position > 9 )
  143. cursor_position -= 9;
  144. }
  145. if ( keycode == U8X8_MSG_GPIO_MENU_NEXT )
  146. {
  147. if ( cursor_position % 3 == 2 )
  148. cursor_position-=2;
  149. else
  150. cursor_position += 1;
  151. }
  152. if ( keycode == U8X8_MSG_GPIO_MENU_UP )
  153. {
  154. cursor_position -= 3;
  155. if ( cursor_position > 9 )
  156. cursor_position += 9;
  157. }
  158. if ( keycode == U8X8_MSG_GPIO_MENU_PREV )
  159. {
  160. if ( cursor_position % 3 == 0 )
  161. cursor_position+=2;
  162. else
  163. cursor_position -= 1;
  164. }
  165. cursor_position = cursor_position % 9;
  166. if ( keycode == U8X8_MSG_GPIO_MENU_SELECT )
  167. break;
  168. if ( keycode == U8X8_MSG_GPIO_MENU_HOME )
  169. break;
  170. }
  171. y = cursor_position / 3;
  172. x = cursor_position % 3;
  173. if ( spielfeld[y][x] == FELD_NICHT_BELEGT )
  174. {
  175. spielfeld[y][x] = FELD_MARKIERT_DURCH_SPIELER ;
  176. return;
  177. }
  178. /*
  179. if ( zaehler > 3 )
  180. {
  181. printf("Du doedl, jetzt langts aber...\n");
  182. exit(1);
  183. }
  184. printf("Ahh, das feld ist schon belegt, nochmal...\n");
  185. zaehler = zaehler + 1;
  186. */
  187. }
  188. }
  189. /*==============================================*/
  190. /* Künstliche Computer Intelligenz */
  191. void zug_computer(void)
  192. {
  193. int x, y;
  194. /* Sehr dumme AI: Nimm den nächsten freien Platz */
  195. for( y = 0; y < 3; y = y + 1 )
  196. {
  197. for( x = 0; x < 3; x = x + 1 )
  198. {
  199. if ( spielfeld[y][x] == FELD_NICHT_BELEGT )
  200. {
  201. spielfeld[y][x] = FELD_MARKIERT_DURCH_COMPUTER;
  202. return;
  203. }
  204. }
  205. }
  206. }
  207. /*==============================================*/
  208. /* Spiel Zuende Prüfung */
  209. /* gibt 1 zurück, wenn in der zeile überall markierung gesetzt ist */
  210. int zeile_gewonnen(int y, int markierung)
  211. {
  212. int x;
  213. for( x = 0; x < 3; x++ )
  214. {
  215. if ( spielfeld[y][x] != markierung )
  216. return 0;
  217. }
  218. return 1;
  219. }
  220. /* gibt 1 zurück, wenn in der zeile überall markierung gesetzt ist */
  221. int spalte_gewonnen(int x, int markierung)
  222. {
  223. int y;
  224. for( y = 0; y < 3; y++ )
  225. {
  226. if ( spielfeld[y][x] != markierung )
  227. return 0;
  228. }
  229. return 1;
  230. }
  231. int diagonale_gewonnen(int markierung)
  232. {
  233. int i;
  234. for( i = 0; i < 3; i ++ )
  235. {
  236. if ( spielfeld[i][i] != markierung )
  237. return 0;
  238. }
  239. return 1;
  240. }
  241. int inverse_diagonale_gewonnen(int markierung)
  242. {
  243. int i;
  244. for( i = 0; i < 3; i ++ )
  245. {
  246. if ( spielfeld[2-i][i] != markierung )
  247. return 0;
  248. }
  249. return 1;
  250. }
  251. int ist_das_spiel_zuende(void)
  252. {
  253. int i, x, y;
  254. int ist_alles_voll;
  255. zeige_spielfeld_an();
  256. for( i = 0; i < 3; i ++ )
  257. {
  258. if ( zeile_gewonnen(i, FELD_MARKIERT_DURCH_SPIELER) )
  259. gewinner = FELD_MARKIERT_DURCH_SPIELER;
  260. if ( zeile_gewonnen(i, FELD_MARKIERT_DURCH_COMPUTER) )
  261. gewinner = FELD_MARKIERT_DURCH_COMPUTER;
  262. if ( spalte_gewonnen(i, FELD_MARKIERT_DURCH_SPIELER) )
  263. gewinner = FELD_MARKIERT_DURCH_SPIELER;
  264. if ( spalte_gewonnen(i, FELD_MARKIERT_DURCH_COMPUTER) )
  265. gewinner = FELD_MARKIERT_DURCH_COMPUTER;
  266. }
  267. if ( diagonale_gewonnen(FELD_MARKIERT_DURCH_SPIELER) )
  268. gewinner = FELD_MARKIERT_DURCH_SPIELER;
  269. if ( diagonale_gewonnen(FELD_MARKIERT_DURCH_COMPUTER) )
  270. gewinner = FELD_MARKIERT_DURCH_COMPUTER;
  271. if ( inverse_diagonale_gewonnen(FELD_MARKIERT_DURCH_SPIELER) )
  272. gewinner = FELD_MARKIERT_DURCH_SPIELER;
  273. if ( inverse_diagonale_gewonnen(FELD_MARKIERT_DURCH_COMPUTER) )
  274. gewinner = FELD_MARKIERT_DURCH_COMPUTER;
  275. if ( gewinner != FELD_NICHT_BELEGT )
  276. return 1;
  277. ist_alles_voll = 1;
  278. for( y = 0; y < 3; y = y + 1 )
  279. {
  280. for( x = 0; x < 3; x = x + 1 )
  281. {
  282. if ( spielfeld[y][x] == FELD_NICHT_BELEGT )
  283. {
  284. ist_alles_voll = 0;
  285. }
  286. }
  287. }
  288. if ( ist_alles_voll )
  289. return 1;
  290. return 0;
  291. }
  292. /*==============================================*/
  293. void zeige_ergebnis_an(void)
  294. {
  295. u8g2.setFont(u8g2_font_helvB12_tr);
  296. if ( gewinner == FELD_MARKIERT_DURCH_SPIELER )
  297. u8g2.userInterfaceMessage("Spieler", "gewinnt", "", " ok ");
  298. else if ( gewinner == FELD_MARKIERT_DURCH_COMPUTER )
  299. u8g2.userInterfaceMessage("Computer", "gewinnt", "", " ok ");
  300. else
  301. u8g2.userInterfaceMessage("", "Unentschieden", "", " ok ");
  302. }
  303. /*==============================================*/
  304. void setup(void) // Arduino setup
  305. {
  306. // Intialisierung für Arduboy (Production)
  307. u8g2.begin(/*Select=*/ 7, /*Right/Next=*/ A1, /*Left/Prev=*/ A2, /*Up=*/ A0, /*Down=*/ A3, /*Home/Cancel=*/ 8);
  308. }
  309. void loop(void) // Arduino loop
  310. {
  311. spiel_initalisieren();
  312. zeige_spielfeld_an();
  313. for(;;)
  314. {
  315. zug_spieler();
  316. zeige_spielfeld_an();
  317. if ( ist_das_spiel_zuende() )
  318. {
  319. break;
  320. } /* if */
  321. delay(300);
  322. zug_computer();
  323. zeige_spielfeld_an();
  324. if ( ist_das_spiel_zuende() )
  325. {
  326. break;
  327. } /* if */
  328. } /* for */
  329. zeige_ergebnis_an();
  330. }