#C语言 #手把手学会三子棋
Posted Misaka御坂美琴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#C语言 #手把手学会三子棋相关的知识,希望对你有一定的参考价值。
一 三子棋游戏实现逻辑
1 游戏菜单界面
2 打印棋盘
3 玩家下棋
4 电脑随机下棋
5 判断胜负
二 具体程序实现
1 游戏主逻辑与游戏菜单界面
1.1主函数设计
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define COLS 3// 三子棋棋盘为3x3
#define ROWS 3
// 1 该区域用于声明接下来要写的每一个函数,后面会讲到暂时先不管这些函数。(此处我不用头文件引用的方式)
void InitBoard(int rows, int cols, char board[ROWS][COLS]);
void DispalyBoard(int row, int col, char board[ROWS][COLS]);
void PlayerMove(char board[ROWS][COLS], int rows, int cols);
void PcMove(char board[ROWS][COLS], int rows, int cols);
int is_full(char board[ROWS][COLS], int rows, int cols);
char IsWin (char board[ROWS][COLS], int rows, int cols);
void menu();
void game();
//2 主函数逻辑
int main()`
{
//3 input 接受玩家输入的数字以判断进入(退出)游戏`
int input = 0;
//4 do while循环可实现玩家循环游戏,玩家也可选择0退出游戏。
do{
menu(); //5 菜单函数打印游戏菜单
scanf("%d", &input);//6 接受一个玩家输入的数 1 代表进入游戏 0 代表退出游戏
switch (input)
{
case 1:
printf("游戏开始\\n");
game();//7 game()函数是游戏实现的函数
break;
case 0:
printf("退出游戏\\n");
break;
default:
printf("重新输入\\n");
}
}
while (input);`
}
1.2 menu()函数(打印菜单)
// 打印游戏菜单
void menu()
{
printf(" *********************\\n");
printf(" ******* 0.Exit *****\\n");
printf("******* 1.Play *****\\n");
printf("*********************\\n");
printf("请选择>>:");
}
1.3 game()函数
// 三子棋游戏实现的game()函数
void game()
{
char board[ROWS][COLS];// 1 棋盘:通过创建一个3X3的二维数组来表示棋盘
InitBoard(ROWS,COLS,board);//2(具体代码在后面) 初始化棋盘函数:给二维数组每一个元素赋值
DispalyBoard(ROWS, COLS, board);//3 (具体代码在后面详述) 打印棋盘
}
1.4 尝试运行一下
2 打印游戏棋盘
InitBoard (初始化二维数组board)函数
DisplayBoard(打印棋盘)函数
2.1 InitBoard void InitBoard(int rows, int cols, char board[ROWS][COLS])
void InitBoard(int rows, int cols, char board[ROWS][COLS])// rows 参数代表行 cols 代表列 board代表二维数组
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = ' ';// 给每一char类型元素赋一个值' '(空格)以确保下棋前显示棋盘时我们看到的是一个空棋盘。
}
}
}
2.2 DispalyBoard(int row, int col, char board[ROWS][COLS])
void DispalyBoard(int row, int col, char board[ROWS][COLS])
{
for (int i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);// 1 打印空格元素
if (j < col - 1) printf("|");//2 分割同一行元素
}
printf("\\n");// 3 一行打印好之后换行
if (i < row)
{
for (j = 0; j < row; j++)
{
printf("---");//4 打印分割行 用---分割每一行
if (j < col - 1) printf("|");
}
}
printf("\\n");
}
}
2.3 尝试运行一下
3 玩家下棋实现
3.1 void PlayerMove(char board[ROWS][COLS], int rows, int cols)三个参数分别为 1二维数组 2行数 3列数
void PlayerMove(char board[ROWS][COLS], int rows, int cols)
{
printf("玩家走 ");
printf("请输入坐标:>");//1 提示玩家输入要下棋的位置的坐标
int x = 0, y = 0, i, j;
while (1)//2 通过while循环,实现当玩家下棋的位置已经被占用或输入位置错误时能够重新输入。
{
scanf("%d %d", &x, &y);//3 输入要下棋位置的(例:1 1代表第一行第一列,代表二维数组中board[0][0])
if (x >= 1&&x<= rows &&y>=1&&y<= cols)
{
i = x - 1;
j = y - 1; //4 注意数组的下标从0开始,所以要减一(例:1 1代表第一行第一列,代表二维数组中board[0][0])
if (board[i][j] == ' ')//5 判断下棋的位置是否是初始化是赋值的空格,若不是表示该位置已被玩家或电脑棋子占用,不能再在这个位置下棋。
{
board[i][j] = '*';//6 玩家下棋赋值为'*'
break;//7 成功下一个棋子后跳出循环
}
else
{
printf("坐标被占用请重新输入\\n");//8 提醒该位置被占用
}
}
else
{
printf("坐标非法请重新输入\\n");//9 提醒玩家所输入的位置非法(例:坐标4 4 不存在于3X3的棋盘中)
}
}
}
3.2 调整一下game()函数
void game()
{
char board[ROWS][COLS];
char ret = 0;
InitBoard(ROWS,COLS,board);
DispalyBoard(ROWS, COLS, board);
while (1)// 1 实现玩家循环下棋
{
PlayerMove(board,ROWS,COLS);//2 玩家下棋
DispalyBoard(ROWS,COLS,board);//3 将玩家下棋的结果打印显示到屏幕上
}
3.3 尝试运行一下
4 实现电脑随机下棋
4.1 添加头文件 <time.h> <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <stdlib.h>// 1 包含rand(),rand()生产随机数
#include<time.h>// 2 随机数种子,以免产生伪随机数。
4.2 void PcMove(char board[ROWS][COLS], int rows, int cols)
void PcMove(char board[ROWS][COLS], int rows, int cols)
{
int x = 0, y = 0;
printf("PC走:>\\n");
while (1)
{
x = rand()%rows; y = rand() % cols;//1 令x是0~2的随机数 y是0~2 的随机数
if (board[x][y] == ' ')// 2 判断电脑所下位置是否没被下
{
board[x][y] = '#';//3 # 为电脑的棋子
break;
}
}
}
4.3 game()函数调整 添加
PcMove()和 打印电脑下棋后的棋盘
void game()
{
char board[ROWS][COLS];
char ret = 0;
InitBoard(ROWS, COLS, board);
DispalyBoard(ROWS, COLS, board);
while (1)
{
PlayerMove(board, ROWS, COLS);
DispalyBoard(ROWS, COLS, board);
PcMove(board, ROWS, COLS);// 1 电脑下棋
DispalyBoard(ROWS, COLS, board);//2 打印电脑下棋后的棋盘
}
}
4.4 运行
5 判断玩家/电脑的胜负
5.1 Is_full函数 判断棋盘是否下满
int is_full(char board[ROWS][COLS], int rows, int cols)
{
int i = 0; int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
if (board[i][j] == ' ') return 0;// 1 假如存在空格表示棋盘未下满,跳出循环返回0
}
}
return 1;//2 遍历整个数组也没有找到空格表示棋盘已经下满,返回 1
}
5.2 IsWin函数 ( 判断胜负)
(类型是char ,返回不同的char 类型的值表示不同含义,以让game()函数判断结果)
char IsWin(char board[ROWS][COLS], int rows, int cols)
{
int i = 0;
for (i = 0; i < rows; i++)
{
// 1 判断是否有一行全为同一个值(某一方的棋子),并且该值不是初始化时的空格。
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];// 2 有一行假如全为某一方的棋子,返回该棋子的char类型值给game()函数。
}
// 3 判断是否有一列的 值(某一方的棋子) 相同并且该值不能为空格。
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];//4 有一列假如全为某一方的棋子,返回该棋子的char类型值给game()函数。
}
//5 同理判断是否左上角到右下角这一条斜线的值是否相同,且不能为初始化时二维数组时赋的给它的空格的值。
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
//6 判断右上角到左下角这条斜线是否相同,且不为空格。
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[1][1] != ' ')
{
return board[1][1];
}
}
// 7 经过前面的判断加入还没有返回一个值表示还未分出胜负,此时判断棋盘是否下满,以判断是否平局。
if (is_full(board, rows, cols))
{
return 'Q';// 8 加入下满给game()函数返回Q表示平局
}
else
{
return 'C';//9 假如经过前面的判断依然没有返回一个值表示还没有分出胜负,此时返回一个C表示游戏继续。
}
}
5.3 在game()函数中加入判断结果的逻辑
void game()
{
char board[ROWS][COLS];
InitBoard(ROWS, COLS, board);
DispalyBoard(ROWS, COLS, board);
char ret=0;//1 创建一个char类型变量 ret接收IsWin函数的返回值
while (1)
{
PlayerMove(board, ROWS, COLS);
DispalyBoard(ROWS, COLS, board);
ret = IsWin(board, ROWS, COLS);
if (ret != 'C')//3 判断玩家下棋后是否胜出,否则继续下棋循环。
{
break;
}
PcMove(board, ROWS, COLS);
DispalyBoard(ROWS, COLS, board);
if (ret != 'C')//4 判断PC下棋后是否胜出,否则继续下棋循环。
{
break;
}
}
// 4 当ret不等于c时跳出循环,根据ret的值判断结果
// 4.1 ret=* 表示玩家赢 4.2ret=#表示电脑赢 4.3 ret返回其他值
if (ret == '*') printf("Player 胜出\\n");
else if (ret == '#') printf("PC 胜出\\n");
else printf("平局\\n");
}
6 最终代码和结果展示。
```c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <stdlib.h>
#include<time.h>
#define COLS 3//
#define ROWS 3
void menu();
void InitBoard(int rows, int cols, char board[ROWS][COLS]);
void DispalyBoard(int row, int col, char board[ROWS][COLS]);
void PlayerMove(char board[ROWS][COLS], int rows, int cols);
void PcMove(char board[ROWS][COLS], int rows, int cols);
int is_full(char board[ROWS][COLS], int rows, int cols);
char IsWin(char board[ROWS][COLS], int rows, int cols);
void game();
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
scanf("%d", &input);
switch (input)
{
case 1:
printf("游戏开始\\n");
game();
break;
case 0:
printf("退出游戏\\n");
break;
default:
printf("重新输入\\n");
}
} while (input);
}
void menu()
{
printf("*********************\\n");
printf("******* 0.Exit *****\\n");
printf("******* 1.Play *****\\n");
printf("*********************\\n");
printf("请选择>>:");
}
void InitBoard(int rows, int cols, char board[ROWS][COLS])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = ' ';
}
}
}
void DispalyBoard(int row, int col, char board[ROWS][COLS])
{
// 3展示棋盘的逻辑 数据的打印,分割行的打印,分割列的打印
for (int i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
//1
if (j < col - 1) printf("|");
}
printf("\\n");
if (i < row)
{
for (j = 0; j < row; j++)
{
// 2 分割行的打印
printf("---");
if (j < col - 1) printf("|");
}
}
printf("\\n");
}
}
void PlayerMove(char board[ROWS][COLS], int rows, int cols)
{
printf("玩家走 ");
printf("请输入坐标:>");
int x = 0, y = 0, i, j;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= rows && y >= 1 && y <= cols)
{
i = x - 1; j = y - 1;
if (board[i][j] == ' ')
{
board[i][j] = '*';
break;
}
else
{
printf("坐标被占用请重新输入\\n");
}
}
else
{
printf("坐标非法请重新输入\\n");
}
}
}
void PcMove(char board[ROWS][COLS], int rows, int cols)
{
int x = 0, y = 0;
printf("PC走:>\\n");
while (1)
{
x = rand() % rows; y = rand() % cols;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int is_full(char board[ROWS][COLS], int rows, int cols)
{
int i = 0; int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
if (board[i][j] == ' ') return 0;
}
}
return 1;
}
char IsWin(char board[ROWS][COLS], int rows, int cols)
{
// 1.1 Player Is Winner 1.2 Pc Is Winner 2 平局 3 继续
int i = 0;
for (i = 0; i < rows; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[1][1] != ' ')
{
return board[1][1];
}
}
if (is_full(board, rows, cols))
{
return 'Q';
}
else
{
return 'C';
}
}
void game()
{
char board[ROWS][COLS];
char ret = 0;
InitBoard(ROWS, COLS, board);
DispalyBoard(ROWS, COLS, board);
while (1)
{
PlayerMove(board, ROWS, COLS);
DispalyBoard(ROWS, COLS, board);
ret = IsWin(board, ROWS, COLS);
if (ret != 'C')
{
break;
}
PcMove(board, ROWS, COLS);
DispalyBoard(ROWS, COLS, board);
ret = IsWin(board, ROWS, COLS);
if (ret != 'C')
{
break;
}
}
if (ret == '*') printf("Player 胜出\\n");
else if (ret == '#') printf("PC 胜出\\n");
else printf("平局\\n");
}
``
以上是关于#C语言 #手把手学会三子棋的主要内容,如果未能解决你的问题,请参考以下文章