1. game.h(头文件 ------ 声明与定义)
#pragma once
// 解决VS编译器scanf安全警告问题
#define _CRT_SECURE_NO_WARNINGS 1
// 包含所需头文件
#include <stdio.h> // 输入输出函数
#include <stdlib.h> // rand()、srand()函数
#include <time.h> // time()时间函数
// 宏定义棋盘大小,方便后期修改
#define ROW 3 // 棋盘行数
#define COL 3 // 棋盘列数
// ------------------- 函数声明 -------------------
// 打印游戏菜单
void menu();
// 游戏核心逻辑
void game();
// 初始化棋盘,将所有位置设为空格
void init_board(char board[ROW][COL], int row, int col);
// 打印棋盘界面
void print_board(char board[ROW][COL], int row, int col);
// 玩家下棋(输入坐标)
void player_move(char board[ROW][COL], int row, int col);
// 电脑下棋(随机坐标)
void pc_move(char board[ROW][COL], int row, int col);
// 判断游戏状态
// 返回值:*玩家赢 #电脑赢 Q平局 C继续游戏
char is_win(char board[ROW][COL], int row, int col);
// 判断棋盘是否已满(满返回1,未满返回0)
int is_full(char board[ROW][COL], int row, int col);
2. game.c(函数实现 ------ 游戏逻辑)
#include "game.h"
// ------------------- 菜单函数 -------------------
void menu()
{
printf("*********************************\n");
printf("********** 三子棋游戏 *********\n");
printf("********** 1. 开始游戏 ********\n");
printf("********** 2. 退出游戏 ********\n");
printf("*********************************\n");
}
// ------------------- 初始化棋盘 -------------------
// 作用:把棋盘所有位置初始化为空格,保证开局是空棋盘
void init_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
// 遍历每一行
for (i = 0; i < row; i++)
{
// 遍历每一列
for (j = 0; j < col; j++)
{
board[i][j] = ' '; // 赋值为空格
}
}
}
// ------------------- 打印棋盘 -------------------
// 作用:在控制台打印出美观的3x3棋盘格子
void print_board(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
// 打印一行棋子数据
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]); // 打印棋子
if (j < col - 1) // 不是最后一列就打印竖线
printf("|");
}
printf("\n");
// 打印分隔行(最后一行不打印)
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
// ------------------- 玩家下棋 -------------------
// 玩家输入坐标,用 * 表示
void player_move(char board[ROW][COL], int row, int col)
{
printf("===== 玩家回合 =====\n");
// 循环直到输入合法坐标
while (1)
{
printf("请输入下棋坐标(行 列),例如 1 1:");
int x, y;
scanf("%d %d", &x, &y);
// 1. 判断坐标是否在棋盘范围内
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
// 2. 判断该位置是否为空
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*'; // 玩家落子
break; // 跳出循环,结束回合
}
else
{
printf("该位置已有棋子,请重新输入!\n");
}
}
else
{
printf("坐标非法!请输入1~3之间的数字!\n");
}
}
}
// ------------------- 电脑下棋 -------------------
// 电脑随机生成坐标,用 # 表示
void pc_move(char board[ROW][COL], int row, int col)
{
printf("===== 电脑回合 =====\n");
// 循环直到找到空位置
while (1)
{
// 随机生成 0~2 的下标
int x = rand() % row;
int y = rand() % col;
// 判断位置是否为空
if (board[x][y] == ' ')
{
board[x][y] = '#'; // 电脑落子
break;
}
}
}
// ------------------- 判断棋盘是否满了 -------------------
int is_full(char board[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0; // 有空位,棋盘未满
}
}
return 1; // 无空位,棋盘已满
}
// ------------------- 判断输赢 -------------------
// 返回值:
// '*' 玩家赢
// '#' 电脑赢
// 'Q' 平局
// 'C' 继续游戏
char is_win(char board[ROW][COL], int row, int col)
{
int i;
// 1. 判断三行是否连成一线
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
// 2. 判断三列是否连成一线
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
// 3. 判断两条对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
// 4. 判断是否平局(棋盘满了但没人赢)
if (is_full(board, row, col))
{
return 'Q';
}
// 5. 游戏继续
return 'C';
}
// ------------------- 游戏核心逻辑 -------------------
void game()
{
// 定义棋盘数组
char board[ROW][COL];
// 接收游戏状态
char ret;
// 1. 初始化棋盘
init_board(board, ROW, COL);
// 2. 打印初始棋盘
print_board(board, ROW, COL);
// 游戏循环:玩家、电脑轮流下棋
while (1)
{
// 玩家下棋
player_move(board, ROW, COL);
print_board(board, ROW, COL);
// 判断玩家是否赢
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
// 电脑下棋
pc_move(board, ROW, COL);
print_board(board, ROW, COL);
// 判断电脑是否赢
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
// 游戏结束,打印结果
if (ret == '*')
{
printf("玩家获胜!\n");
}
else if (ret == '#')
{
printf("电脑获胜!\n");
}
else
{
printf("平局!\n");
}
}
3. main.c(主函数 ------ 程序入口)
#include "game.h"
int main()
{
// 设置随机数种子,保证电脑每次下棋位置不同
srand((unsigned int)time(NULL));
int choice = 0; // 存储用户菜单选择
// 菜单循环:可以重复玩游戏
while (1)
{
// 打印菜单
menu();
printf("请输入你的选择:");
scanf("%d", &choice);
// 根据选择执行逻辑
switch (choice)
{
case 1:
printf("=== 游戏开始 ===\n");
game(); // 进入游戏
break;
case 2:
printf("=== 退出游戏,再见! ===\n");
return 0; // 结束程序
default:
printf("输入错误,请重新选择!\n");
break;
}
printf("\n");
}
return 0;
}
4.三子棋总结
1.项目介绍
C 语言 实现的控制台版三子棋小游戏
2.功能特点
- 玩家与电脑对战
- 美观的棋盘打印
- 坐标合法性判断
- 输赢 / 平局自动判断
- 支持重复开始游戏
3.游戏规则
- 玩家:
*,电脑:# - 输入
1 1代表第一行第一列 - 任意一行、一列、对角线连成一线即可获胜
- 棋盘下满无人获胜则为平局
4.代码结构
game.h:头文件,宏定义 + 函数声明game.c:函数实现,游戏核心逻辑main.c:程序入口,菜单逻辑