- 一、功能描述
- 二、游戏部分功能介绍
- 三、代码实现
- 1. main()代码
- 2.游戏菜单代码
- 3.playgame()代码
- 3.模式菜单和难度菜单
- 4.初始化棋盘
- 5.打印棋盘
- 6.玩家下棋
- 7.简单人机下棋
- 8.困难人机下棋
- 8.1 电脑检测自己这次落棋后是否能赢
- 8.2 电脑检测是否要堵玩家的棋
- 8.3 困难人机主函数
- 9.判断输赢
- 9.1 判断是否棋盘满
- 9.2 判断输、赢、平局
- 10.双人游戏
- 四、游戏页面以及结果演示
- 1.人机模式
- 1.1 简单人机
- 1.2 困难人机
- 2.双人模式
- 五、全部代码
该版本可以选择双人游戏和人机对战,并且人机对战分为两个等级(简单人机随机下棋;困难人机是优化后的算法具有堵棋、三连功能)。
二、游戏部分功能介绍1.打印游戏菜单
2.初始化棋盘
3.打印棋盘
4.打印模式菜单
5.打印难度菜单
6.双人游戏
7.简单人机
8.困难人机
9.判断棋盘是否下满
10.判断输赢
用户输入
int main() {
srand((unsigned int)time(NULL));//随机数
int input = 0;
do
{
menu();
printf("请输入 >");
scanf("%d", &input);
switch (input) {
case 1:
playgame();
break;
case 0:
printf("游戏退出...n");
break;
default:
printf("请输入正确的格式n");
}
} while (input);
return 0;
}
2.游戏菜单代码
void menu() {
printf("****************************n");
printf("***** 0 退出游戏 ******n");
printf("***** 1 进入游戏 ******n");
printf("****************************n");
}
3.playgame()代码
void playgame() {
char model;//接收用户选择的模式
char difficulty;//接收难度系数
char ch;//接收数据 用于清空缓存区
model_menu();
printf("请你选择模式 >");
while ((ch = getchar()) != 'n' && ch != EOF);//清空缓存区
scanf("%c", &model);
if (model == 'a') {
difficulty_menu();
printf("请选择难度等级:");
while ((ch = getchar()) != 'n' && ch != EOF);//清空缓存区
scanf("%c", &difficulty);
if (difficulty == 'd') {
printf("困难模式开始...n");
playgame_pvc(&difficulty);
}
else if (difficulty == 'e') {
printf("简单模式开始...n");
playgame_pvc(&difficulty);
}
}
else if (model == 'b') {
printf("人人对战n");
play_game_pvp();
}
}
3.模式菜单和难度菜单
//模式菜单
void model_menu() {
printf("***************************n");
printf("** a 人机模式 b 双人模式 **n");
printf("***************************n");
}
//难度菜单
void difficulty_menu() {
printf("***************************n");
printf("** e 简单模式 d 困难模式 **n");
printf("***************************n");
}
4.初始化棋盘
void init_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++) {
board[i][j] = ' ';
}
}
}
5.打印棋盘
void print_board(char board[ROW][COL], int row, int col) {
int i = 0;
for (i = 0; i < row; i++) {
//打印数据
for (int j = 0; j < col; j++) {
if (j < col - 1)
printf(" %c |", board[i][j]);
else
printf(" %cn", board[i][j]);
}
//打印分隔符
if (i < row - 1) {
for (int j = 0; j < row; j++) {
if (j < row - 1)
printf("---|");
else
printf("---n");
}
}
}
}
6.玩家下棋
void person_move(char board[ROW][COL], int row, int col) {
int i = 0, j = 0;
while (1) {
scanf("%d %d", &i, &j);
if (board[i - 1][j - 1] == ' ') {
//注意坐标与二维数组对应关系
board[i - 1][j - 1] = '*';
break;
}
else {
printf("此位置已被下过,请重新落棋:");
}
}
}
7.简单人机下棋
void computer_move_easy(char board[ROW][COL], int row, int col) {
int i = 0, j = 0;
printf("电脑走:n");
while (1) {
i = rand() % row;
j = rand() % col;
if (board[i][j] == ' ') {
board[i][j] = '#';
break;
}
}
}
8.困难人机下棋
8.1 电脑检测自己这次落棋后是否能赢
- 电脑检测棋盘在横向、纵向以及主副对角线是否有两个’#‘,如果有就代表电脑可以直接下上第三个’#‘;如果没有则需要继续判断是否需要堵玩家的棋子。
- 代码:
//检查电脑是否一线两子 如果有直接赢
int computer_will_win(char board[ROW][COL], int row, int col) {
int i = 0;
int j = 0;
int p_win = 0;//标志是否直接赢
if(0 == p_win)
{
//判断电脑横行上是否会赢
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == '#' && board[i][2] == ' ')
{
board[i][2] = '#';
p_win = 1;
break;
}
if (board[i][0] == board[i][2] && board[i][0] == '#' && board[i][1] == ' ')
{
board[i][1] = '#';
p_win = 1;
break;
}
if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
{
board[i][0] = '#';
p_win = 1;
break;
}
}
if (p_win != 0)
return p_win;
//判断电脑列上是否有机会赢
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == '#' && board[2][j] == ' ')
{
board[2][j] = '#';
p_win = 1;
break;
}
if (board[0][j] == board[2][j] && board[2][j] == '#' && board[1][j] == ' ')
{
board[1][j] = '#';
p_win = 1;
break;
}
if (board[1][j] == board[2][j] && board[2][j] == '#' && board[0][j] == ' ')
{
board[0][j] = '#';
p_win = 1;
break;
}
}
if (p_win != 0)
return p_win;
}
//判断电脑在对角线上是否会赢
if (0 == p_win)
{
if (board[0][0] == board[1][1] && board[1][1] == '#' && board[2][2] == ' ')
{
board[2][2] = '#';
p_win = 1;
return p_win;
}
if (board[0][0] == board[2][2] && board[2][2] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
p_win = 1;
return p_win;
}
if (board[1][1] == board[2][2] && board[1][1] == '#' && board[0][0] == ' ')
{
board[0][0] = '#';
p_win = 1;
return p_win;
}
if (board[0][2] == board[1][1] && board[0][2] == '#' && board[2][0] == ' ')
{
board[2][0] = '#';
p_win = 1;
return p_win;
}
if (board[0][2] == board[2][0] && board[2][0] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
p_win = 1;
return p_win;
}
if (board[1][1] == board[2][0] && board[2][0] == '#' && board[0][2] == ' ')
{
board[0][2] = '#';
p_win = 1;
return p_win;
}
}
return p_win;//p_win==0 说明没有直接赢 需继续判断是否要堵棋
}
8.2 电脑检测是否要堵玩家的棋
- 如果程序执行到此说明电脑不能直接赢,而是要判断玩家的棋子有没有一条线上出现二连’ * '的情况。如果有就“堵棋”;如果也不需要“堵棋”,那么电脑就随机下棋了(执行简单人机的核心下棋代码)。
- 代码:
//检测玩家是否能一线两子 如果有就堵
int people_will_win(char board[ROW][COL], int row, int col) {
int i = 0;
int j = 0;
int k = 0;
while (0 == k)
{
//判断玩家在横行上是否会赢
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == '*' && board[i][2] == ' ')
{
board[i][2] = '#';
k = 1;
break;
}
if (board[i][0] == board[i][2] && board[i][0] == '*' && board[i][1] == ' ')
{
board[i][1] = '#';
k = 1;
break;
}
if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
{
board[i][0] = '#';
k = 1;
break;
}
}
if (k != 0)
break;
//判断玩家在竖列上是否会赢
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == '*' && board[2][j] == ' ')
{
board[2][j] = '#';
k = 1;
break;
}
if (board[0][j] == board[2][j] && board[2][j] == '*' && board[1][j] == ' ')
{
board[1][j] = '#';
k = 1;
break;
}
if (board[1][j] == board[2][j] && board[2][j] == '*' && board[0][j] == ' ')
{
board[0][j] = '#';
k = 1;
break;
}
}
break;
}
//判断玩家在对角线上是否会赢
while (0 == k)
{
if (board[0][0] == board[1][1] && board[1][1] == '*' && board[2][2] == ' ')
{
board[2][2] = '#';
k = 1;
break;
}
if (board[0][0] == board[2][2] && board[2][2] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[1][1] == board[2][2] && board[1][1] == '*' && board[0][0] == ' ')
{
board[0][0] = '#';
k = 1;
break;
}
if (board[0][2] == board[1][1] && board[0][2] == '*' && board[2][0] == ' ')
{
board[2][0] = '#';
k = 1;
break;
}
if (board[0][2] == board[2][0] && board[2][0] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[1][1] == board[2][0] && board[2][0] == '*' && board[0][2] == ' ')
{
board[0][2] = '#';
k = 1;
break;
}
break;
}
return k;//返回值如果是1那么已经对玩家进行了堵棋,如果是0则无需堵。
}
8.3 困难人机主函数
//电脑下棋优化版
void computer_move_diff(char board[ROW][COL], int row, int col) {
int i = 0, j = 0;
int p;
printf("电脑走:n");
//电脑先检测自己这一次落棋后自己是否能赢
p = computer_will_win( board, row, col);
if (p == 1) {//电脑已经下过棋
return;
}
//检查玩家是否会赢 会赢直接堵截
p = people_will_win(board, row, col);
if (p == 1) {//电脑对玩家进行了堵截不需要再下
return;
}
//运行到这说明也没有赢 也没有堵截 随机下棋
while (1) {
i = rand() % row;
j = rand() % col;
if (board[i][j] == ' ') {
board[i][j] = '#';
break;
}
}
}
9.判断输赢
9.1 判断是否棋盘满
- 代码:
//判断棋盘是否下满
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;
}
9.2 判断输、赢、平局
- 如果在任一方向出现三连一样的字符(排除三连空格情况),那么久说明有一方赢了,直接返回这个字符(#:代表电脑赢(或者玩家2)、* :代表玩家赢)。如果没有人赢就判断是否出现平局的情况(棋盘满了)。如果以上情况均未发生那就游戏继续。
- 代码:
//检查是否有一方获胜
char check_win(char board[ROW][COL], int row, int col)
{
int i;
//判断横向是否有一样的
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && (board[i][1] != ' '))
return board[i][1];
}
//判断竖向是否有一样的
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
return board[1][i];
}
//判断对角线是否有一样的
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
return board[1][1];
//如果没人赢 检查棋盘是否满 也就是平局
else if (is_full(board, row, col))
return '$';
//以上情况都没有则分不出输赢
return 0;
}
10.双人游戏
- 有了以上各种函数基础双人游戏代码就很简单了,只需要让一方先下棋,打印出棋盘然后判断是否分出胜负;另一方下棋,打印出棋盘然后判断胜负。如此循环知道分出胜负。
- 代码:
//双人对战游戏
void play_game_pvp() {
char key;//接收输赢结果
//定义棋盘
char board[ROW][COL];
//初始化棋盘
init_board(board, ROW, COL);
//打印棋盘
print_board(board, ROW, COL);
while (1)
{
printf("请p1下棋:(输入坐标)>");
person_move(board, ROW, COL);//玩家1下棋
print_board(board, ROW, COL);//打印棋盘
key = check_win(board, ROW, COL);//判输赢平局
//打印输赢结果
if (key == '*')
{
printf("恭喜p1赢啦n");
break;
}
if (key == '#')
{
printf("恭喜p2赢了n");
break;
}
if (key == '$')
{
printf("平局了!n");
break;
}
printf("请p2下棋:(输入坐标)>");
person2_move(board, ROW, COL);//玩家2下棋
print_board(board, ROW, COL);//打印棋盘
key = check_win(board, ROW, COL);//判输赢平局
//打印输赢结果
if (key == '*')
{
printf("恭喜你获得胜利啦n");
break;
}
if (key == '#')
{
printf("p2赢了n");
break;
}
if (key == '$')
{
printf("你们打平局了!n");
break;
}
}
}
四、游戏页面以及结果演示
1.人机模式
1.1 简单人机
- 这时的人机还很呆 不会堵棋,玩家轻易获胜!
- 困难人机一旦二连就可以直接赢。
- 困难人机可以在三个方向赌棋
-
全部代码内容较多 以上也展示的差不多了,避免页面太长,想要直接全部拷贝来自己玩一玩的小伙伴可以码云复制。
-
点击这里获取全部代码
-
写的思想比较简单 可能存在错误如有发现欢迎指正 咱再继续改进。



