parent
adacc8c96d
commit
2ff4b8c475
@ -0,0 +1,319 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define SIZE 15
|
||||
#define HISTORY_SIZE 500
|
||||
|
||||
typedef enum {
|
||||
MODE_HUMAN_VS_HUMAN,
|
||||
MODE_HUMAN_VS_AI,
|
||||
MODE_EXIT
|
||||
} GameMode;
|
||||
|
||||
typedef enum {
|
||||
EASY,
|
||||
MEDIUM,
|
||||
HARD
|
||||
} Difficulty;
|
||||
|
||||
typedef struct {
|
||||
char board[SIZE][SIZE];
|
||||
GameMode mode;
|
||||
Difficulty difficulty;
|
||||
char currentPlayer;
|
||||
int lastMove[2];
|
||||
int history[HISTORY_SIZE][2];
|
||||
int stepCount;
|
||||
} GameState;
|
||||
|
||||
void clearScreen() {
|
||||
system("cls");
|
||||
}
|
||||
|
||||
void initGame(GameState* game, GameMode mode) {
|
||||
memset(game->board, '+', sizeof(game->board));
|
||||
game->mode = mode;
|
||||
game->currentPlayer = 'X';
|
||||
game->stepCount = 0;
|
||||
game->difficulty = MEDIUM;
|
||||
memset(game->history, -1, sizeof(game->history));
|
||||
}
|
||||
|
||||
void printBoard(const GameState* game) {
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
printf(" ");
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
printf("%2d", i + 1);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
printf("%2d ", i + 1);
|
||||
for (int j = 0; j < SIZE; j++) {
|
||||
if (game->board[i][j] == 'X') {
|
||||
SetConsoleTextAttribute(hConsole, 12);
|
||||
}
|
||||
else if (game->board[i][j] == 'O') {
|
||||
SetConsoleTextAttribute(hConsole, 9);
|
||||
}
|
||||
printf("%2c", game->board[i][j]);
|
||||
SetConsoleTextAttribute(hConsole, 7);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool isValidMove(const GameState* game, int x, int y) {
|
||||
return x >= 0 && x < SIZE && y >= 0 && y < SIZE && game->board[x][y] == '+';
|
||||
}
|
||||
|
||||
bool checkWin(const GameState* game, int x, int y) {
|
||||
const int dirs[4][2] = { {0, 1}, {1, 0}, {1, 1}, {1, -1} };
|
||||
char player = game->board[x][y];
|
||||
|
||||
for (int d = 0; d < 4; d++) {
|
||||
int count = 1;
|
||||
|
||||
for (int step = 1; step < 5; step++) {
|
||||
int nx = x + dirs[d][0] * step;
|
||||
int ny = y + dirs[d][1] * step;
|
||||
if (nx < 0 || nx >= SIZE || ny < 0 || ny >= SIZE || game->board[nx][ny] != player) break;
|
||||
count++;
|
||||
}
|
||||
|
||||
for (int step = 1; step < 5; step++) {
|
||||
int nx = x - dirs[d][0] * step;
|
||||
int ny = y - dirs[d][1] * step;
|
||||
if (nx < 0 || nx >= SIZE || ny < 0 || ny >= SIZE || game->board[nx][ny] != player) break;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count >= 5) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void showWinMessage(char winner) {
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
clearScreen();
|
||||
|
||||
SetConsoleTextAttribute(hConsole, 14); // 黄色
|
||||
printf("================================\n");
|
||||
printf(" PLAYER %c WINS THE GAME!\n", winner);
|
||||
printf("================================\n\n");
|
||||
SetConsoleTextAttribute(hConsole, 7); // 恢复白色
|
||||
|
||||
printf("Press Enter to return to main menu...");
|
||||
while (getchar() != '\n'); // 清空输入缓冲区
|
||||
getchar(); // 等待回车
|
||||
}
|
||||
|
||||
void showDrawMessage() {
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
clearScreen();
|
||||
|
||||
SetConsoleTextAttribute(hConsole, 11); // 浅蓝色
|
||||
printf("================================\n");
|
||||
printf(" DRAW GAME!\n");
|
||||
printf("================================\n\n");
|
||||
SetConsoleTextAttribute(hConsole, 7); // 恢复白色
|
||||
|
||||
printf("Press Enter to return to main menu...");
|
||||
while (getchar() != '\n');
|
||||
getchar();
|
||||
}
|
||||
|
||||
void aiMove(GameState* game) {
|
||||
int x, y;
|
||||
|
||||
if (game->difficulty == EASY) {
|
||||
do {
|
||||
x = rand() % SIZE;
|
||||
y = rand() % SIZE;
|
||||
} while (!isValidMove(game, x, y));
|
||||
}
|
||||
else if (game->difficulty == MEDIUM) {
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
for (int j = 0; j < SIZE; j++) {
|
||||
if (isValidMove(game, i, j)) {
|
||||
game->board[i][j] = 'O';
|
||||
if (checkWin(game, i, j)) {
|
||||
game->lastMove[0] = i;
|
||||
game->lastMove[1] = j;
|
||||
game->history[game->stepCount][0] = i;
|
||||
game->history[game->stepCount][1] = j;
|
||||
game->stepCount++;
|
||||
return;
|
||||
}
|
||||
game->board[i][j] = '+';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
for (int j = 0; j < SIZE; j++) {
|
||||
if (isValidMove(game, i, j)) {
|
||||
game->board[i][j] = 'X';
|
||||
if (checkWin(game, i, j)) {
|
||||
game->board[i][j] = 'O';
|
||||
game->lastMove[0] = i;
|
||||
game->lastMove[1] = j;
|
||||
game->history[game->stepCount][0] = i;
|
||||
game->history[game->stepCount][1] = j;
|
||||
game->stepCount++;
|
||||
return;
|
||||
}
|
||||
game->board[i][j] = '+';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
x = rand() % SIZE;
|
||||
y = rand() % SIZE;
|
||||
} while (!isValidMove(game, x, y));
|
||||
}
|
||||
else {
|
||||
do {
|
||||
x = rand() % SIZE;
|
||||
y = rand() % SIZE;
|
||||
} while (!isValidMove(game, x, y));
|
||||
}
|
||||
|
||||
game->board[x][y] = 'O';
|
||||
game->lastMove[0] = x;
|
||||
game->lastMove[1] = y;
|
||||
game->history[game->stepCount][0] = x;
|
||||
game->history[game->stepCount][1] = y;
|
||||
game->stepCount++;
|
||||
}
|
||||
|
||||
void showMainMenu() {
|
||||
clearScreen();
|
||||
printf("=== GOMOKU GAME ===\n");
|
||||
printf("1. Player vs Player\n");
|
||||
printf("2. Player vs AI\n");
|
||||
printf("3. Set Difficulty\n");
|
||||
printf("4. Exit Game\n");
|
||||
printf("Select: ");
|
||||
}
|
||||
|
||||
void setDifficulty(GameState* game) {
|
||||
clearScreen();
|
||||
printf("=== SET DIFFICULTY ===\n");
|
||||
printf("1. Easy\n");
|
||||
printf("2. Medium\n");
|
||||
printf("3. Hard\n");
|
||||
printf("Select: ");
|
||||
|
||||
int choice;
|
||||
scanf("%d", &choice);
|
||||
|
||||
switch (choice) {
|
||||
case 1: game->difficulty = EASY; break;
|
||||
case 2: game->difficulty = MEDIUM; break;
|
||||
case 3: game->difficulty = HARD; break;
|
||||
default: printf("Invalid choice, keeping current difficulty\n");
|
||||
}
|
||||
}
|
||||
|
||||
GameMode gameLoop(GameState* game) {
|
||||
while (1) {
|
||||
clearScreen();
|
||||
printBoard(game);
|
||||
|
||||
if (game->mode == MODE_HUMAN_VS_AI && game->currentPlayer == 'O') {
|
||||
printf("AI is thinking...\n");
|
||||
Sleep(800);
|
||||
aiMove(game);
|
||||
printf("AI moved to: %d %d\n", game->lastMove[0] + 1, game->lastMove[1] + 1);
|
||||
}
|
||||
else {
|
||||
printf("Player %c's turn (enter row and column, or 4 to exit): ", game->currentPlayer);
|
||||
|
||||
int row, col;
|
||||
if (scanf("%d", &row) != 1) {
|
||||
printf("Invalid input format!\n");
|
||||
while (getchar() != '\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (row == 4) {
|
||||
return MODE_EXIT;
|
||||
}
|
||||
|
||||
if (scanf("%d", &col) != 1) {
|
||||
printf("Invalid input format!\n");
|
||||
while (getchar() != '\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
row--; col--;
|
||||
if (!isValidMove(game, row, col)) {
|
||||
printf("Invalid move, try again\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
game->board[row][col] = game->currentPlayer;
|
||||
game->lastMove[0] = row;
|
||||
game->lastMove[1] = col;
|
||||
game->history[game->stepCount][0] = row;
|
||||
game->history[game->stepCount][1] = col;
|
||||
game->stepCount++;
|
||||
}
|
||||
|
||||
if (checkWin(game, game->lastMove[0], game->lastMove[1])) {
|
||||
showWinMessage(game->currentPlayer);
|
||||
return game->mode;
|
||||
}
|
||||
|
||||
if (game->stepCount == SIZE * SIZE) {
|
||||
showDrawMessage();
|
||||
return game->mode;
|
||||
}
|
||||
|
||||
game->currentPlayer = (game->currentPlayer == 'X') ? 'O' : 'X';
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
srand((unsigned int)time(NULL));
|
||||
GameState game;
|
||||
int choice;
|
||||
GameMode result;
|
||||
|
||||
while (1) {
|
||||
showMainMenu();
|
||||
|
||||
if (scanf("%d", &choice) != 1) {
|
||||
while (getchar() != '\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (choice) {
|
||||
case 1:
|
||||
initGame(&game, MODE_HUMAN_VS_HUMAN);
|
||||
result = gameLoop(&game);
|
||||
if (result == MODE_EXIT) continue;
|
||||
break;
|
||||
case 2:
|
||||
initGame(&game, MODE_HUMAN_VS_AI);
|
||||
result = gameLoop(&game);
|
||||
if (result == MODE_EXIT) continue;
|
||||
break;
|
||||
case 3:
|
||||
setDifficulty(&game);
|
||||
break;
|
||||
case 4:
|
||||
return 0;
|
||||
default:
|
||||
printf("Invalid selection!\n");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue