目录
序言:
一.整体思路
二.加载逻辑
三.棋盘布置
四.下棋
五.智能化
最后:
想必三子棋大家都玩过吧,回想起小时候在地上用石头画上线,有的用石子儿,有的用树枝,下三子棋,都能玩一天。现在回想起来都是满满的回忆呀。今天带着大家来用C语言,来实现模拟实现一下三子棋游戏,来帮大家找一找童年的记忆。下面进入正题:
我们三子棋主要实现的原理是,利用字符打印出一个棋盘,用二维数组存储我们下的棋子。先给大家看看什么样的。
大致就是这个样子。
然后一步一步下棋,每下一步,我们就把棋盘打印一边。
首先每次游戏开始我们都需要一个菜单:
菜单代码:
void menu()
{
printf("*****************************************\n");
printf("************1.play 0.exit*************\n");
printf("*****************************************\n");
}
游戏的加载逻辑,我们希望可以选择游戏开始或者退出,也不是玩完一局就没有了,而是玩完一局以后还可以继续选择玩或者不玩,只有我们选组退出时,程序才会结束。
代码:
void game()
{
printf("三子棋\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入选项:>\n");
scanf("%d", &input);
printf("\n");
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:>\n");
break;
}
} while (input);
return 0;
}
运行效果:
设置好游戏的加载逻辑以后,后面的游戏内容就全部在game()函数里面完成。并且我们为了是程序模块化,我们将主函数放到main.c文件里面,函数声明,头文件,宏等,我们就放在game.h文件里面,函数的具体实现我们统统放在,game.c文件里面。这样我们的整体程序就会非常有序,可读性提高。
我们使用宏常量来,规定棋盘的大小 :
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3
#define LIN 3
#include
void menu();
void game();
void game()
{
//创建二维数组
char chess[ROW][LIN] = { 0 };
//初始化用来装棋子的二维数组
init_board(chess,ROW,LIN);
//打印棋盘
print_board(chess,ROW,LIN);
}
void init_board(char chess[ROW][LIN], int row, int lin)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < lin; j++)
{
//二维数组全部初始化位空格
chess[i][j] = ' ';
}
}
}
void print_board(char chess[ROW][LIN],int row,int lin)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < lin; j++)
{
//空格 + 棋子 + 空格 + | ,为一组,一共
//需要 lin 组,但是最后一组不需要 |
printf(" %c ",chess[i][j]);
//控制最后一个 | 不打印
if (j < row - 1)
{
printf("|");
}
}
//换行
printf("\n");
// | |
//---|---|---
//为一组,一共需要 row 组,但是最后一组,不需要 ---|---|---
if (i < lin - 1)
{
for (int j = 0; j < row; j++)
{
// ---| 为一组,一共 row 组,最后一组不需要打印 |
printf("---");
if (j < row - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
运行效果:
下棋的主要逻辑实现就是,封装两个函数player_chess()用来表示玩家下棋和电脑下棋computer_board(),玩家输入坐标,并将玩家代表的棋子存入棋盘的二维数组里面,电脑下棋先给他设置成随机下棋,然后每次下完一颗棋子我们就打印一下整个棋盘。我们需要一直下棋,每下一颗棋子都有可能出现胜利的一方,封装一个函数is_win()用来判断是否又人赢了,所以需要每下一颗棋子就需要判断一下是否又赢得玩家,如果又赢得玩家就直接is_win直接返回胜利者的棋子,如果没有人赢就返回‘C’代表继续,如果棋盘已经满了,就返回‘Q’代表平局。
void game()
{
char set;
//随机数生成器
srand((unsigned int)time(NULL));
//创建二维数组
char chess[ROW][LIN] = { 0 };
//初始化用来装棋子的二维数组
init_board(chess,ROW,LIN);
//打印棋盘
print_board(chess,ROW,LIN);
while (1)//一直循环,直到结果出现输赢,或者平局
{
//玩家下棋
player_chess(chess, ROW, LIN );
//打印棋盘
print_board(chess, ROW, LIN);
//判断结果
set=is_win(chess,ROW,LIN);
if ('C' != set)
{
break;
}
//电脑下棋
computer_board(chess, ROW, LIN);
//打印棋盘
print_board(chess, ROW, LIN);
//判断结果
set = is_win(chess, ROW, LIN);
if ('C' != set)
{
break;
}
}
//如果返回的是玩家代表的棋子,
if (set == '*')
{
printf("恭喜你,你赢了!!\n");
}
//如果返回的是电脑代表的棋子
else if ('#' == set)
{
printf("电脑赢了!!\n");
}
//如果是平局
else if ('Q' == set)
{
printf("平局\n");
}
}
void player_chess(char chess[ROW][LIN], int row, int lin)
{
//计数玩家棋子数量
count_board++;
//坐标
int x = 0;
int y = 0;
while (1)
{
printf("请输入棋子坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合理性,是否在棋盘内
if (x >= 1 && x <= row && y >= 1 && y <= lin)
{
//坐标位置是否为空
if (chess[x-1][y-1] == ' ')
{
chess[x-1][y-1] = '*';
break;
}
else
{
printf("该位置已有棋子\n");
}
}
else
{
printf("棋子坐标错误,请重新输入\n");
}
}
}
void computer_board(char chess[ROW][LIN], int row, int lin)
{
while (1)//直到找好位置循环结束。
{
//随机数生成,0~2
int x = rand()%row;
int y = rand()%lin;
//判断是否该位置为空,
if (chess[x][y] == ' ')
{
chess[x][y] = '#';
break;
}
}
}
判断是否有玩家赢is_win()
//判断棋盘是否满了
int is_full(char chess[ROW][LIN], int row, int lin)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < lin; j++)
{
if (chess[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char is_win(char chess[ROW][LIN], int row, int lin)
{
//横着判断是否有三个一样的
for (int i = 0; i < row; i++)
{
if (chess[i][0] == chess[i][1] &&
chess[i][1] == chess[i][2] &&
chess[i][0]!=' ')
{
return chess[i][0];
}
}
//竖着判断是否有三个一样的
for (int i = 0; i < lin; i++)
{
if (chess[0][i] == chess[1][i] &&
chess[1][i] == chess[2][i] &&
chess[0][i] != ' ')
{
return chess[0][i];
}
}
//斜着判断是否有三个一样的
if (chess[0][0] == chess[1][1] &&
chess[1][1] == chess[2][2] &&
chess[0][0] != ' ')
{
return chess[0][0];
}
//斜着判断是否有三个一样的
if (chess[0][2] == chess[1][1] &&
chess[1][1] == chess[2][0] &&
chess[0][2] != ' ')
{
return chess[0][2];
}
//判断棋盘是否满了
int tmp = is_full(chess, ROW, LIN);
if (tmp == 1)
{
return 'Q';
}
return 'C';
}
这样我们三子棋的主要逻辑就实现了
但是大家发现这电脑傻了吧唧的,现在我们就给他智能化,但是智能化的程度取决于设计者。分析那些情况优先的,就像当你电脑还差一颗棋子就可以赢了,这就是最先考虑的情况,其次是当对手还差一颗棋子赢了,还有电脑下一颗可以达成两颗棋子的领先情况,等等还有一些情况小编不好分析,就不多介绍了。
void computer_board(char chess[ROW][LIN], int row, int lin)
{
//差一棋子,优先下(1)
for (int i = 0; i < row; i++)
{
if (chess[i][0] == chess[i][1] && chess[i][0] == '#'&& chess[i][2] == ' ')
{
chess[i][2] = '#';
return;
}
if (chess[i][0] == chess[i][2] && chess[i][0] == '#'&& chess[i][1] == ' ')
{
chess[i][1] = '#';
return;
}
if (chess[i][1] == chess[i][2] && chess[i][1] == '#'&& chess[i][0] == ' ')
{
chess[i][0] = '#';
return;
}
}
//差一棋子,优先下(2)
for (int i = 0; i < lin; i++)
{
if (chess[0][i] == chess[1][i] && chess[0][i] == '#'&& chess[2][i]==' ')
{
chess[2][i] = '#';
return;
}
if (chess[0][i] == chess[2][i] && chess[0][i] == '#'&&chess[1][i] == ' ')
{
chess[1][i] = '#';
return;
}
if (chess[1][i] == chess[2][i] && chess[1][i] == '#'&& chess[0][i] == ' ')
{
chess[0][i] = '#';
return;
}
}
//差一棋子,优先下(3)
if (chess[0][0] == chess[1][1] && chess[0][0] == '#' && chess[2][2] == ' ')
{
chess[2][2] = '#';
return;
}
if (chess[0][0] == chess[2][2] && chess[0][0] == '#' && chess[1][1] == ' ')
{
chess[1][1] = '#';
return;
}
if (chess[2][2] == chess[1][1] && chess[1][1] == '#' && chess[0][0] == ' ')
{
chess[0][0] = '#';
return;
}
//差一棋子,优先下(4)
if (chess[0][2] == chess[1][1] && chess[0][2] == '#' && chess[2][0] == ' ')
{
chess[2][0] = '#';
return;
}
if (chess[0][2] == chess[2][0] && chess[0][2] == '#' && chess[1][1] == ' ')
{
chess[1][1] = '#';
return;
}
if (chess[2][0] == chess[1][1] && chess[1][1] == '#' && chess[0][2] == ' ')
{
chess[0][2] = '#';
return;
}
//对方差一棋子胜利,优先下(5)
for (int i = 0; i < row; i++)
{
if (chess[i][0] == chess[i][1] && chess[i][0] == '*' && chess[i][2] == ' ')
{
chess[i][2] = '#';
return;
}
if (chess[i][0] == chess[i][2] && chess[i][0] == '*' && chess[i][1] == ' ')
{
chess[i][1] = '#';
return;
}
if (chess[i][1] == chess[i][2] && chess[i][1] == '*' && chess[i][0] == ' ')
{
chess[i][0] = '#';
return;
}
}
//对方差一棋子胜利,优先下(6)
for (int i = 0; i < lin; i++)
{
if (chess[0][i] == chess[1][i] && chess[0][i] == '*' && chess[2][i] == ' ')
{
chess[2][i] = '#';
return;
}
if (chess[0][i] == chess[2][i] && chess[0][i] == '*' && chess[1][i] == ' ')
{
chess[1][i] = '#';
return;
}
if (chess[1][i] == chess[2][i] && chess[1][i] == '*' && chess[0][i] == ' ')
{
chess[0][i] = '#';
return;
}
}
//对方差一棋子胜利,优先下(7)
if (chess[0][0] == chess[1][1] && chess[0][0] == '*' && chess[2][2] == ' ')
{
chess[2][2] = '#';
return;
}
if (chess[0][0] == chess[2][2] && chess[0][0] == '*' && chess[1][1] == ' ')
{
chess[1][1] = '#';
return;
}
if (chess[2][2] == chess[1][1] && chess[1][1] == '*' && chess[0][0] == ' ')
{
chess[0][0] = '#';
return;
}
//对方差一棋子胜利,优先下(8)
if (chess[0][2] == chess[1][1] && chess[0][2] == '*' && chess[2][0] == ' ')
{
chess[2][0] = '#';
return;
}
if (chess[0][2] == chess[2][0] && chess[0][2] == '*' && chess[1][1] == ' ')
{
chess[1][1] = '#';
return;
}
if (chess[2][0] == chess[1][1] && chess[1][1] == '*' && chess[0][2] == ' ')
{
chess[0][2] = '#';
return;
}
//抢占先机,下完这一棋子,差一步胜利;(1)
for (int i = 0; i < lin; i++)
{
if (chess[0][i] == '#' && chess[1][i] == ' ' && chess[2][i] == ' ')
{
chess[1][i] = '#';
return;
}
if (chess[1][i] == '#' && chess[0][i] == ' ' && chess[2][i] == ' ')
{
chess[0][i] = '#';
return;
}
if (chess[2][i] == '#' && chess[0][i] == ' ' && chess[1][i] == ' ')
{
chess[0][i] = '#';
return;
}
}
//抢占先机,下完这一棋子,差一步胜利;(2)
for (int i = 0; i < row; i++)
{
if (chess[i][0] == '#' && chess[i][1] == ' ' && chess[i][2] == ' ')
{
chess[i][1] = '#';
return;
}
if (chess[i][1] == '#' && chess[i][0] == ' ' && chess[i][2] == ' ')
{
chess[i][0] = '#';
return;
}
if (chess[i][2] == '#' && chess[i][0] == ' ' && chess[i][1] == ' ')
{
chess[i][0] = '#';
return;
}
}
//抢占先机,下完这一棋子,差一步胜利;(3)
if (chess[0][0] == '#' && chess[1][1] == ' ' && chess[2][2] == ' ')
{
chess[1][1] = '#';
return;
}
if (chess[0][0] == ' ' && chess[1][1] == '#' && chess[2][2] == ' ')
{
chess[2][2] = '#';
return;
}
if (chess[0][0] == ' ' && chess[1][1] == ' ' && chess[2][2] == '#')
{
chess[0][0] = '#';
return;
}
//抢占先机,下完这一棋子,差一步胜利;(4)
if (chess[0][2] == '#' && chess[1][1] == ' ' && chess[2][0] == ' ')
{
chess[1][1] = '#';
return;
}
if (chess[0][2] == ' ' && chess[1][1] == '#' && chess[2][0] == ' ')
{
chess[0][2] = '#';
return;
}
if (chess[0][2] == ' ' && chess[1][1] == ' ' && chess[2][0] == '#')
{
chess[0][2] = '#';
return;
}
//第一步棋子,针对
if (count_board == 1 && chess[0][0] == '*')
{
chess[2][2] = '#';
return;
}
if (count_board == 1 && chess[0][2] == '*')
{
chess[2][0] = '#';
return;
}
if (count_board == 1 && chess[2][0] == '*')
{
chess[0][2] = '#';
return;
}
if (count_board == 1 && chess[2][2] == '*')
{
chess[0][0] = '#';
return;
}
while (1)
{
int x = rand()%row;
int y = rand()%lin;
if (chess[x][y] == ' ')
{
chess[x][y] = '#';
break;
}
}
}
最后展示成果:
这里我就已经输了,哈哈哈。
坚守之心就是不为苦难所惧。苦难是成功的磨刀石,是对人的胆识、智慧和毅力的考验。生活的道 路不是一帆风顺的,往往荆棘丛生。不少人就是迈不过这道坎,害怕、退缩、放弃、变向,结果只 能与成功失之交臂。努力成为你最喜欢的那种人,就算不成功,至少你会喜欢这样努力的自己。加油,诸君,山顶见!!!