/** * Java. Level 1. Lesson 4. Example of homework * Tic-tac-toe in console with simple AI * * @author Sergey Iryupin * @version dated Jun 15, 2019 */ import java.util.Random; import java.util.Scanner; class HW4Lesson { final int SIZE = 3; // size of the game map final int WIN_SIZE = 3; // size of win-line final char DOT_X = 'x'; // sign of human final char DOT_O = 'o'; // sign of AI final char DOT_EMPTY = '.'; // sign of empty cell final String MSG_FOR_HUMAN = "Enter X and Y (1..3):"; final String MSG_YOU_WON = "YOU WON!"; final String MSG_AI_WON = "AI WON!"; final String MSG_DRAW = "Sorry, DRAW!"; final String MSG_GAME_OVER = "GAME OVER."; char[][] map; Scanner sc; Random rand; public static void main(String[] args) { new HW4Lesson().game(); } HW4Lesson() { map = new char[SIZE][SIZE]; sc = new Scanner(System.in); rand = new Random(); } void game() { initMap(); while (true) { printMap(); turnHuman(DOT_X); if (checkWin(DOT_X)) { System.out.println(MSG_YOU_WON); break; } if (isMapFull()) { System.out.println(MSG_DRAW); break; } turnAI(DOT_O, DOT_X); //printMap(); if (checkWin(DOT_O)) { System.out.println(MSG_AI_WON); break; } if (isMapFull()) { // this code doesn't matter System.out.println(MSG_DRAW); // because a human always break; // makes a move last in 3x3 } } System.out.println(MSG_GAME_OVER); printMap(); } void initMap() { // init game's field for (int i = 0; i < SIZE; i++) for (int j = 0; j < SIZE; j++) map[i][j] = DOT_EMPTY; } void printMap() { // output game's field for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) System.out.print(map[i][j] + " "); System.out.println(); } System.out.println(); } void turnHuman(char dot) { // human action int x, y; do { System.out.println(MSG_FOR_HUMAN); x = sc.nextInt() - 1; y = sc.nextInt() - 1; } while (!isCellValid(x, y)); map[y][x] = dot; } void turnAI(char dot, char enemyDot) { // AI action int x, y; for (x = 0; x < SIZE; x++) // simple blocking for (y = 0; y < SIZE; y++) if (isCellValid(x, y)) { // if cell empty map[y][x] = enemyDot; // try to be like enemy if (checkWin(enemyDot)) { // if win map[y][x] = dot; // block return; // and exit } map[y][x] = DOT_EMPTY; // restore cell } do { x = rand.nextInt(SIZE); y = rand.nextInt(SIZE); } while (!isCellValid(x, y)); map[y][x] = dot; } boolean checkWin(char dot) { // check win condition for (int y = 0; y < SIZE; y++) for (int x = 0; x < SIZE; x++) for (int dy = -1; dy < 2; dy++) for (int dx = -1; dx < 2; dx++) if (checkLine(x, y, dx, dy, dot) == WIN_SIZE) return true; /* simple checking of win in 3x3 map // check horizontals and verticals for (int i = 0; i < SIZE; i++) if ((map[i][0] == dot && map[i][1] == dot && map[i][2] == dot) || (map[0][i] == dot && map[1][i] == dot && map[2][i] == dot)) return true; // check diagonals if ((map[0][0] == dot && map[1][1] == dot && map[2][2] == dot) || (map[2][0] == dot && map[1][1] == dot && map[0][2] == dot)) return true; */ return false; } int checkLine(int x, int y, int dx, int dy, char dot) { int count = 0; // check line for win if (dx == 0 && dy == 0) return 0; for (int i = 0, xi = x, yi = y; i < WIN_SIZE; i++, xi += dx, yi += dy) if (xi >= 0 && yi >= 0 && xi < SIZE && yi < SIZE && map[yi][xi] == dot) count++; return count; } boolean isMapFull() { // check field filling for (int i = 0; i < SIZE; i++) for (int j = 0; j < SIZE; j++) if (map[i][j] == DOT_EMPTY) return false; return true; } boolean isCellValid(int x, int y) { // check cell if (x < 0 || y < 0 || x >= SIZE || y >= SIZE) return false; return map[y][x] == DOT_EMPTY; // by DSerov } }