1.代码结果演示
2.三子棋实现
2.1游戏思路
(1)创建菜单选择开始游戏或退出
(2)创建棋盘并完成初始化
(3)打印棋盘
(4)玩家下棋
(5)电脑自动下棋
(6)判断胜负
2.2分步实现
2.2.1分别创建头文件game.h、源文件game.c和test.c
game.h :用于存放自定义函数的声明、引用的标准库头文件等
game.c:用于存放函数的定义
test.c:用于程序测试
2.2.2创建菜单并实现选择是否玩游戏
首先创建菜单提供选项
voidmenu()//打印菜单{ printf("***************************\n"); printf("*********1. play **********\n"); printf("*********0. exit **********\n"); printf("***************************\n"); }
再在main函数中实现选择
voidmenu()//打印菜单{ printf("***************************\n"); printf("*********1. play **********\n"); printf("*********0. exit **********\n"); printf("***************************\n"); } intmain() { intinput=0; while (1) { //打印菜单menu(); printf("请选择:>"); scanf("%d", &input); //判断选择,也可以使用switchif (input==1) { printf("三子棋游戏现在开始!\n"); //game();//玩游戏 } elseif (input==0) { printf("游戏结束\n"); break;//退出游戏 } else { printf("选择错误,请重新选择\n"); } } return0; }
测试结果
注:在函数实现的每一步都进行测试,能够及时找到错误并改正
2.2.3创建棋盘并完成初始化
在游戏开始时,棋盘上没有任何棋子,因此我们要对棋盘进行初始化,清空棋盘,保证后续游戏的进行
这里我们创建3*3大小的棋盘,对于数组行和列的大小,我们可以选择使用宏定义,若是想要修改行和列的大小,则只需要修改define定义的行列大小
//在game.h中定义行和列的大小
在game()函数中创建棋盘
//记得引自定义头文件voidgame() { //创建二维数组用于存放下棋数据charboard[ROW][COL] = { 0 }; //初始化棋盘InitBoard(board, ROW, COL); }
接下来我们实现初始化棋盘函数
//初始化棋盘voidInitBoard(charboard[ROW][COL], introw, intcol) { for (inti=0; i<row; i++) { for (intj=0; j<col; j++) { board[i][j] =' ';//将数组中所有元素初始化为空格 } } }
注:在game.h中定义InitBoard函数,在game.c中实现InitBoard函数
调试结果
2.2.4打印棋盘
在实现棋盘的初始化后,我们要将已初始化的棋盘展现出来,以便玩家下棋
//打印棋盘voidDisplayBoard(charboard[ROW][COL], introw, intcol) { for (inti=0; i<row; i++) { for (intj=0; j<col; j++) { printf(" %c ", board[i][j]); if (j<col-1) { printf("|");//打印|以隔开相同行的不同棋子 } } printf("\n"); if (i<row-1)//打印---|---以隔开不同行的棋子 { for (intj=0; j<col; j++) { printf("---"); if (j<col-1) { printf("|"); } } printf("\n"); } } }
测试结果
2.2.5玩家下棋
在实现玩家下棋时,我们要先接收玩家输入的下棋位置
再判断输入的位置是否在棋盘范围内,是否已有棋子
最后将棋子放入对应位置
//玩家下棋voidPlayerMove(charboard[ROW][COL], introw, intcol) { intx=0; inty=0; printf("玩家走:>\n"); while (1) { printf("请输入坐标(中间以空格隔开):>"); scanf("%d %d", &x, &y); if ((x>0&&x<=ROW) && (y>0&&y<=COL)) { if (board[x-1][y-1] ==' ') { board[x-1][y-1] ='*'; break; } else { printf("坐标已被占用,请重新输入!\n"); } } else { printf("输入坐标错误,请重新输入!\n"); } } }
注:玩家下棋时默认棋盘位置是从1开始的,而不是0
运行结果
2.2.6电脑下棋
在实现电脑自动下棋时,我们要生成随机数,并判断生成的坐标是否已有棋子
voidComputerMove(charboard[ROW][COL], introw, intcol) { intx=0; inty=0; printf("电脑下棋:>\n"); while (1) { //在使用rand()时,要引用对应头文件//要使用srand((unsigned int)time(NULL))来进行初始化x=rand() %row; y=rand() %col; if (board[x][y] ==' ') { board[x][y] ='#'; break; } } }
在game.h中引用头文件
在main函数中使用srand
intmain() { srand((unsignedint)time(NULL)); intinput=0; while (1) { //打印菜单menu(); printf("请选择:>"); scanf("%d", &input); if (input==1) { printf("三子棋游戏现在开始!\n"); game();//玩游戏 } elseif (input==0) { printf("游戏结束\n"); break;//退出游戏 } else { printf("选择错误,请重新选择\n"); } } return0; }
运行结果
2.2.7判断输赢
在下棋过程中,我们要在玩家和电脑每一步下棋后判断是否有一方胜出,若没有且棋盘未满,则游戏继续
若玩家赢 -> 函数返回‘*’
若电脑赢 -> 返回'#'
若平局 -> 返回‘Q’
游戏继续 - > 返回‘C’
charIsWin(charboard[ROW][COL], introw, intcol) { inti=0; intj=0; intflag=1; for (i=0; i<row; i++)//判断行是否相等 { flag=1; for (j=0; j<col; j++) { if (board[i][j] !=board[i][0] ||board[i][j] ==' ')//一行的每一个元素是否相同 { flag=0; break; } } if (flag==1) { returnboard[i][0]; } } for (j=0; j<col; j++)//判断列是否相等 { flag=1; for (i=0; i<row; i++)//判断一列的元素是否相同 { if (board[i][j] !=board[0][j] ||board[i][j] ==' ') { flag=0; break; } } if (flag==1) { returnboard[0][j]; } } flag=1; for (i=0; i<row; i++)//主对角线元素是否相同 { if (board[i][i] !=board[0][0] ||board[i][i] ==' ') { flag=0; break; } } if (flag==1) { returnboard[0][0]; } flag=1; for (i=0, j=col-1; i<row; i++, j--)//判断副对角线元素是否相同 { if (board[i][j] !=board[0][col-1] ||board[i][j] ==' ') { flag=0; break; } } if (flag==1) { returnboard[0][col-1]; } //平局for (inti=0; i<row; i++) { for (intj=0; j<col; j++) { if (board[i][j] ==' ') { //还有未下棋的坐标,游戏继续return'C'; } } } return'Q'; }
在完成判断输赢函数后,我们在game()函数中实现循环,当一方胜出或平局时结束游戏
voidgame() { //二维数组用于存放下棋数据charboard[ROW][COL] = { 0 }; //初始化棋盘InitBoard(board, ROW, COL); //打印棋盘DisplayBoard(board, ROW, COL); charret=0; while (1) { //玩家下棋PlayerMove(board, ROW, COL); //打印棋盘DisplayBoard(board, ROW, COL); //判断输赢ret=IsWin(board, ROW, COL); if (ret!='C') { break; } //电脑下棋ComputerMove(board, ROW, COL); //打印棋盘DisplayBoard(board, ROW, COL); //判断输赢ret=IsWin(board, ROW, COL); if (ret!='C') { break; } }
运行结果
3.完整代码
game.h
voidInitBoard(charboard[ROW][COL], introw, intcol); voidDisplayBoard(charboard[ROW][COL], introw, intcol); voidPlayerMove(charboard[ROW][COL], introw, intcol); charIsWin(charboard[ROW][COL], introw, intcol); voidComputerMove(charboard[ROW][COL], introw, intcol);
game.c
//初始化棋盘voidInitBoard(charboard[ROW][COL], introw, intcol) { for (inti=0; i<row; i++) { for (intj=0; j<col; j++) { board[i][j] =' '; } } } //打印棋盘voidDisplayBoard(charboard[ROW][COL], introw, intcol) { for (inti=0; i<row; i++) { for (intj=0; j<col; j++) { printf(" %c ", board[i][j]); if (j<col-1) { printf("|"); } } printf("\n"); if (i<row-1) { for (intj=0; j<col; j++) { printf("---"); if (j<col-1) { printf("|"); } } printf("\n"); } } } //玩家下棋voidPlayerMove(charboard[ROW][COL], introw, intcol) { intx=0; inty=0; printf("玩家下棋\n"); while (1) { printf("请输入坐标(中间以空格隔开):>"); scanf("%d %d", &x, &y); if ((x>0&&x<=ROW) && (y>0&&y<=COL)) { if (board[x-1][y-1] ==' ') { board[x-1][y-1] ='*'; break; } else { printf("坐标已被占用,请重新输入!\n"); } } else { printf("输入坐标错误,请重新输入!\n"); } } } //判断输赢//玩家赢 -- 返回*//电脑赢 -- 返回#//平局 -- 返回Q//继续 -- 返回CcharIsWin(charboard[ROW][COL], introw, intcol) { inti=0; intj=0; intflag=1; for (i=0; i<row; i++)//判断行是否相等 { flag=1; for (j=0; j<col; j++) { if (board[i][j] !=board[i][0] ||board[i][j] ==' ')//一行的每一个元素是否相同 { flag=0; break; } } if (flag==1) { returnboard[i][0]; } } for (j=0; j<col; j++)//判断列是否相等 { flag=1; for (i=0; i<row; i++)//判断一列的元素是否相同 { if (board[i][j] !=board[0][j] ||board[i][j] ==' ') { flag=0; break; } } if (flag==1) { returnboard[0][j]; } } flag=1; for (i=0; i<row; i++)//主对角线元素是否相同 { if (board[i][i] !=board[0][0] ||board[i][i] ==' ') { flag=0; break; } } if (flag==1) { returnboard[0][0]; } flag=1; for (i=0, j=col-1; i<row; i++, j--)//判断副对角线元素是否相同 { if (board[i][j] !=board[0][col-1] ||board[i][j] ==' ') { flag=0; break; } } if (flag==1) { returnboard[0][col-1]; } //平局for (inti=0; i<row; i++) { for (intj=0; j<col; j++) { if (board[i][j] ==' ') { //还有未下棋的坐标,游戏继续return'C'; } } } return'Q'; } //电脑下棋voidComputerMove(charboard[ROW][COL], introw, intcol) { intx=0; inty=0; printf("电脑下棋:>\n"); while (1) { x=rand() %row; y=rand() %col; if (board[x][y] ==' ') { board[x][y] ='#'; break; } } }
test.c
//打印菜单voidmenu() { printf("***************************\n"); printf("*********1. play **********\n"); printf("*********0. exit **********\n"); printf("***************************\n"); } voidgame() { //二维数组用于存放下棋数据charboard[ROW][COL] = { 0 }; //初始化棋盘InitBoard(board, ROW, COL); //打印棋盘DisplayBoard(board, ROW, COL); charret=0; while (1) { //玩家下棋PlayerMove(board, ROW, COL); //打印棋盘DisplayBoard(board, ROW, COL); //判断输赢ret=IsWin(board, ROW, COL); if (ret!='C') { break; } //电脑下棋ComputerMove(board, ROW, COL); //打印棋盘DisplayBoard(board, ROW, COL); //判断输赢ret=IsWin(board, ROW, COL); if (ret!='C') { break; } } if (ret=='*') { printf("玩家赢!\n"); } elseif(ret=='#') { printf("电脑赢!\n"); } else { printf("平局\n"); } } intmain() { srand((unsignedint)time(NULL)); intinput=0; while (1) { //打印菜单menu(); printf("请选择:>"); scanf("%d", &input); if (input==1) { printf("三子棋游戏现在开始!\n"); game();//玩游戏 } elseif (input==0) { printf("游戏结束\n"); break;//退出游戏 } else { printf("选择错误,请重新选择\n"); } } return0; }