代码码有大概的注释
三子棋的介绍
- 其实就是井子棋
- 各落子三次,连成一条线则赢(横、竖、对角)
- 下满则为平局
思维导图
这个是要实现整个三子棋的基本思路
- 菜单
- 打印棋盘
- 玩家落子
- 电脑落子
- 判断输赢
- 游戏结束
ok那么开始吧
菜单环节
- 封装一个菜单函数menu()
- 选择(如果玩了一次,还想玩一次咋办?总不可能重新启动吧,那用户体验多差,这里我给用户极致的体验,只要他玩不腻,就死里玩)
**1:**交互界面
//作用就是给你看看,可以选择
void menu()
{
printf("*******************************\n");
printf("******** 1.play *****\n");
printf("******** 1.exit *****\n");
printf("*******************************\n");
}
**2:**选择
//是多次选择所以,的也能过switch
int input = 0;
menu();
scanf("%d", &input);
switch (input)1
{
case 1:
printf("开始游戏");
break;
case 0:
printf("退出游戏");
break;
//这里提示吗,明明告诉告诉你0和1,你却瞎选,我忍,顾客是上帝
default:
printf("输入错误,请重新输入");
break;
}
2.5: 极致体验(防止不过过瘾)
- [ ] do while解析
int main()
{
int input = 0;
do
{
menu();
printf("请输入:<");
scanf("%d", &input);
switch (input)//选择
{
case 1:
printf("开始游戏");//后面改为game()函数
break;
case 0:
printf("退出游戏");
break;
default:
printf("输入错误,请重新输入");
break;
}
return 0;
} while (input);//这里根据你输入值判断是否要继续进行游戏
}
ok那么菜单环节到完成了
游戏
- 创建一个三成三的数组
1 :缺点够灵活,不方便后期更改
void game()
{
char board[3][3];
}
1.5 改进
void game()
{
char board[ROW][COL];//把行列定义在头文件里需要更改,直接去改头文件改就可以了
创建一个头文件
用处:
- 把需要改的值写里面,避免后期一个一个更改
- 避免重复操作(定义的头文件,函数),只需要包含一下他,就不要在包别的头文件里,前提你在自定义头文件里已经包含过了
//包含自定义头文件
#include“ ”
打印棋盘
注:打印棋盘其实就是打印数组
1:初始化棋盘==初始化数组
- 封装一个函数初始化棋盘(InitBoard)
- 数组没初始化,里面都是随机值
- 初始化空格,后面就知道了特别妙
void InitBoard(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] = ' ';//把i行j列的元素变成空格
}
}
}
2:打印棋盘
- 封装一个打印棋盘函数(DisplayBoard)
这个就是棋盘的样子
在打印的时候先打印一个元素一个|在是元素在是|然后在是元素
然后一行分割- - -|- - -|- -
因此可以把它们看成一个整体
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for ( i = 0; i <row; i++)
{
printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
if(i<row-1)//美化棋盘
printf("---|---|---\n");
}
}
第一次运行
第二次
这种写法其实不是特别好,不够灵活,以后要是想玩n子棋咋办
2.5:优化
void DisplayBoard(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]);//打印i行j列上的元素
if ( j< col - 1)//美化棋盘
{
printf("|");
}
}
printf("\n");
if (i < row - 1)//分割线
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)//美化棋盘
{
printf("|");
}
}
}
printf("\n");
}
}
打印行
打印列
第一次
第二次
最终效果
到这里大致就完成了打印棋盘
玩家落子
- 封装一个函数(PlayMove)
- 判断下的位置是否落子
- 判断所下的坐标是否在棋盘内
void PlayMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("请落子:<");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标是否正确
{
//程序员的坐标0,0普通人的坐标1,1
if (board[x - 1][y - 1] == ' ')//如果x-1,y-1的坐标空格就落子
{
board[x - 1][y - 1] = 'O';
break;//落子就跳出不需要在下,博弈,都是你一棋,它一棋
}
else//判成立,代表该位置已经落子
{
printf("改坐标被占用\n");
}
}
else
{
printf("坐标违法,重新输入");
}
}
}
ok玩家下棋就完成了
电脑落子
- 封装一函数(ComputMove)
- 生成坐标(随机值%行,列)
- 判断所下位置是否落子
void ComputMove(char board[ROW][COL], int row, int col)
{
int x = rand()%row;//控制坐是否正确
int y = rand() % col;//控制坐标是否正确
printf("电脑玩家落子\n");
if (board[x][y] == ' ')//判断位置是否落子,无则落子
{
board[x][y] = 'X';
}
}
电脑的落子部分也完成了
判断输赢
返回O玩家赢
返回X电脑赢
返回P平局
返回C继续
- 封装一个函数(IsWin)
- 判断返回值
函数部分
//判断胜负
int IsFull(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for ( i = 0; i < row; i++)
{
for ( i = 0; i < col; i++)
{
if (board[i][j] != ' ')
{
return 0;
}
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col)
{
//判断行是否一致
int i = 0;
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][0];//返回这三个元素中任意一个,
}
}
//判断列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[0][i];
}
}
//判断对角
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][1] && board[2][1] != ' ')
{
return board[1][1];
}
//判断是否平局
//棋盘全满就是平局
//全满就是没有空格
//全满返回1
int back = IsFull(board,row,col);//
if (back == 1)
{
return'P';
}
else
{
return 'C';
}
}
判断部分
while (1)
{
//玩家落
PlayMove(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')//C是继续,不返回他那么就是赢输或者平
{
break;
}
//电脑落子
ComputMove(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')//C是继续,不返回他那么就是赢输或者平
{
break;
}
}
if (ret == 'O')
{
printf("恭喜你赢了\n");
}
if (ret == 'X')
{
printf("很遗憾电脑玩家胜利\n");
}
if (ret == 'P')
{
printf("你和电脑玩家不分伯仲\n");
}
}
ok到这里整个三子棋游戏到此结束!!
总结:
- 这里所运用到知识点都是比较所学过的(循环,数组,函数,分支……)
- 上面还要好多需要优化(AI高级算法)(判断输赢),后面慢慢改进
- 不懂的地方自己慢慢调试,调试永远的神(写的时候好多错,调试好多次才写好),好吧其实调试键已经要被按烂了,都可以写一篇调试博客了哈哈
- 写这个三子棋的过程中我收获挺多,会自己慢慢找错,耐心的写完了这个小游戏(耗时5个多小时),也发现自己好多的不足!!!我身上的坏毛病就和我写出大bug一样,需要慢慢改进!!!!
以上解析,代码若有错误请在评论区指出(或qq:1696912943),博主也很想知道,错了我会及时改正
持续更新中…………